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).
24 #ifdef HAVE_SYS_TIME_H
30 #if defined (HOST_WIN32)
33 #if defined (HAVE_WCHAR_H)
37 #include "mono/utils/mono-membar.h"
38 #include <mono/metadata/object.h>
39 #include <mono/metadata/threads.h>
40 #include <mono/metadata/threads-types.h>
41 #include <mono/metadata/threadpool-ms.h>
42 #include <mono/metadata/threadpool-ms-io.h>
43 #include <mono/metadata/monitor.h>
44 #include <mono/metadata/reflection.h>
45 #include <mono/metadata/assembly.h>
46 #include <mono/metadata/tabledefs.h>
47 #include <mono/metadata/exception.h>
48 #include <mono/metadata/file-io.h>
49 #include <mono/metadata/console-io.h>
50 #include <mono/metadata/mono-route.h>
51 #include <mono/metadata/socket-io.h>
52 #include <mono/metadata/mono-endian.h>
53 #include <mono/metadata/tokentype.h>
54 #include <mono/metadata/domain-internals.h>
55 #include <mono/metadata/metadata-internals.h>
56 #include <mono/metadata/class-internals.h>
57 #include <mono/metadata/reflection-internals.h>
58 #include <mono/metadata/marshal.h>
59 #include <mono/metadata/gc-internals.h>
60 #include <mono/metadata/mono-gc.h>
61 #include <mono/metadata/rand.h>
62 #include <mono/metadata/sysmath.h>
63 #include <mono/metadata/string-icalls.h>
64 #include <mono/metadata/debug-helpers.h>
65 #include <mono/metadata/process.h>
66 #include <mono/metadata/environment.h>
67 #include <mono/metadata/profiler-private.h>
68 #include <mono/metadata/locales.h>
69 #include <mono/metadata/filewatcher.h>
70 #include <mono/metadata/security.h>
71 #include <mono/metadata/mono-config.h>
72 #include <mono/metadata/cil-coff.h>
73 #include <mono/metadata/number-formatter.h>
74 #include <mono/metadata/security-manager.h>
75 #include <mono/metadata/security-core-clr.h>
76 #include <mono/metadata/mono-perfcounters.h>
77 #include <mono/metadata/mono-debug.h>
78 #include <mono/metadata/mono-ptr-array.h>
79 #include <mono/metadata/verify-internals.h>
80 #include <mono/metadata/runtime.h>
81 #include <mono/metadata/file-mmap.h>
82 #include <mono/metadata/seq-points-data.h>
83 #include <mono/io-layer/io-layer.h>
84 #include <mono/utils/monobitset.h>
85 #include <mono/utils/mono-time.h>
86 #include <mono/utils/mono-proclib.h>
87 #include <mono/utils/mono-string.h>
88 #include <mono/utils/mono-error-internals.h>
89 #include <mono/utils/mono-mmap.h>
90 #include <mono/utils/mono-io-portability.h>
91 #include <mono/utils/mono-digest.h>
92 #include <mono/utils/bsearch.h>
93 #include <mono/utils/mono-os-mutex.h>
94 #include <mono/utils/mono-threads.h>
96 #if defined (HOST_WIN32)
100 #include "decimal-ms.h"
101 #include "number-ms.h"
103 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
104 #include <sys/utsname.h>
107 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
109 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
111 /* Lazy class loading functions */
112 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
113 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
114 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
115 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
116 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
120 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
122 static inline MonoBoolean
123 is_generic_parameter (MonoType *type)
125 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
129 mono_class_init_or_throw (MonoClass *klass)
131 if (!mono_class_init (klass))
132 mono_raise_exception (mono_class_get_exception_for_failure (klass));
135 ICALL_EXPORT MonoObject *
136 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
142 ac = (MonoClass *)arr->obj.vtable->klass;
144 esize = mono_array_element_size (ac);
145 ea = (gpointer*)((char*)arr->vector + (pos * esize));
147 if (ac->element_class->valuetype)
148 return mono_value_box (arr->obj.vtable->domain, ac->element_class, ea);
150 return (MonoObject *)*ea;
153 ICALL_EXPORT MonoObject *
154 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
160 MONO_CHECK_ARG_NULL (idxs, NULL);
163 ic = (MonoClass *)io->obj.vtable->klass;
165 ac = (MonoClass *)arr->obj.vtable->klass;
167 g_assert (ic->rank == 1);
168 if (io->bounds != NULL || io->max_length != ac->rank) {
169 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
173 ind = (gint32 *)io->vector;
175 if (arr->bounds == NULL) {
176 if (*ind < 0 || *ind >= arr->max_length) {
177 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
181 return ves_icall_System_Array_GetValueImpl (arr, *ind);
184 for (i = 0; i < ac->rank; i++) {
185 if ((ind [i] < arr->bounds [i].lower_bound) ||
186 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
187 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
192 pos = ind [0] - arr->bounds [0].lower_bound;
193 for (i = 1; i < ac->rank; i++)
194 pos = pos * arr->bounds [i].length + ind [i] -
195 arr->bounds [i].lower_bound;
197 return ves_icall_System_Array_GetValueImpl (arr, pos);
201 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
203 MonoClass *ac, *vc, *ec;
213 vc = value->vtable->klass;
217 ac = arr->obj.vtable->klass;
218 ec = ac->element_class;
220 esize = mono_array_element_size (ac);
221 ea = (gpointer*)((char*)arr->vector + (pos * esize));
222 va = (gpointer*)((char*)value + sizeof (MonoObject));
224 if (mono_class_is_nullable (ec)) {
225 mono_nullable_init ((guint8*)ea, value, ec);
230 mono_gc_bzero_atomic (ea, esize);
234 #define NO_WIDENING_CONVERSION G_STMT_START{\
235 mono_set_pending_exception (mono_get_exception_argument ( \
236 "value", "not a widening conversion")); \
240 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
241 if (esize < vsize + (extra)) { \
242 mono_set_pending_exception (mono_get_exception_argument ( \
243 "value", "not a widening conversion")); \
248 #define INVALID_CAST G_STMT_START{ \
249 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
250 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
254 /* Check element (destination) type. */
255 switch (ec->byval_arg.type) {
256 case MONO_TYPE_STRING:
257 switch (vc->byval_arg.type) {
258 case MONO_TYPE_STRING:
264 case MONO_TYPE_BOOLEAN:
265 switch (vc->byval_arg.type) {
266 case MONO_TYPE_BOOLEAN:
279 NO_WIDENING_CONVERSION;
288 if (!ec->valuetype) {
289 if (!mono_object_isinst (value, ec))
291 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
295 if (mono_object_isinst (value, ec)) {
296 if (ec->has_references)
297 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
299 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
306 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
308 et = ec->byval_arg.type;
309 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
310 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
312 vt = vc->byval_arg.type;
313 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
314 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
316 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
322 case MONO_TYPE_CHAR: \
323 CHECK_WIDENING_CONVERSION(0); \
324 *(etype *) ea = (etype) u64; \
326 /* You can't assign a signed value to an unsigned array. */ \
331 /* You can't assign a floating point number to an integer array. */ \
334 NO_WIDENING_CONVERSION; \
338 #define ASSIGN_SIGNED(etype) G_STMT_START{\
344 CHECK_WIDENING_CONVERSION(0); \
345 *(etype *) ea = (etype) i64; \
347 /* You can assign an unsigned value to a signed array if the array's */ \
348 /* element size is larger than the value size. */ \
353 case MONO_TYPE_CHAR: \
354 CHECK_WIDENING_CONVERSION(1); \
355 *(etype *) ea = (etype) u64; \
357 /* You can't assign a floating point number to an integer array. */ \
360 NO_WIDENING_CONVERSION; \
364 #define ASSIGN_REAL(etype) G_STMT_START{\
368 CHECK_WIDENING_CONVERSION(0); \
369 *(etype *) ea = (etype) r64; \
371 /* All integer values fit into a floating point array, so we don't */ \
372 /* need to CHECK_WIDENING_CONVERSION here. */ \
377 *(etype *) ea = (etype) i64; \
383 case MONO_TYPE_CHAR: \
384 *(etype *) ea = (etype) u64; \
391 u64 = *(guint8 *) va;
394 u64 = *(guint16 *) va;
397 u64 = *(guint32 *) va;
400 u64 = *(guint64 *) va;
406 i64 = *(gint16 *) va;
409 i64 = *(gint32 *) va;
412 i64 = *(gint64 *) va;
415 r64 = *(gfloat *) va;
418 r64 = *(gdouble *) va;
421 u64 = *(guint16 *) va;
423 case MONO_TYPE_BOOLEAN:
424 /* Boolean is only compatible with itself. */
437 NO_WIDENING_CONVERSION;
444 /* If we can't do a direct copy, let's try a widening conversion. */
447 ASSIGN_UNSIGNED (guint16);
449 ASSIGN_UNSIGNED (guint8);
451 ASSIGN_UNSIGNED (guint16);
453 ASSIGN_UNSIGNED (guint32);
455 ASSIGN_UNSIGNED (guint64);
457 ASSIGN_SIGNED (gint8);
459 ASSIGN_SIGNED (gint16);
461 ASSIGN_SIGNED (gint32);
463 ASSIGN_SIGNED (gint64);
465 ASSIGN_REAL (gfloat);
467 ASSIGN_REAL (gdouble);
471 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
475 #undef NO_WIDENING_CONVERSION
476 #undef CHECK_WIDENING_CONVERSION
477 #undef ASSIGN_UNSIGNED
483 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
489 MONO_CHECK_ARG_NULL (idxs,);
491 ic = idxs->obj.vtable->klass;
492 ac = arr->obj.vtable->klass;
494 g_assert (ic->rank == 1);
495 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
496 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
500 ind = (gint32 *)idxs->vector;
502 if (arr->bounds == NULL) {
503 if (*ind < 0 || *ind >= arr->max_length) {
504 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
508 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
512 for (i = 0; i < ac->rank; i++)
513 if ((ind [i] < arr->bounds [i].lower_bound) ||
514 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
515 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
519 pos = ind [0] - arr->bounds [0].lower_bound;
520 for (i = 1; i < ac->rank; i++)
521 pos = pos * arr->bounds [i].length + ind [i] -
522 arr->bounds [i].lower_bound;
524 ves_icall_System_Array_SetValueImpl (arr, value, pos);
527 ICALL_EXPORT MonoArray *
528 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
531 MonoClass *aklass, *klass;
534 gboolean bounded = FALSE;
536 MONO_CHECK_ARG_NULL (type, NULL);
537 MONO_CHECK_ARG_NULL (lengths, NULL);
539 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
541 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
543 for (i = 0; i < mono_array_length (lengths); i++) {
544 if (mono_array_get (lengths, gint32, i) < 0) {
545 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
550 klass = mono_class_from_mono_type (type->type);
551 mono_class_init_or_throw (klass);
553 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
554 /* vectors are not the same as one dimensional arrays with no-zero bounds */
559 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
561 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
562 for (i = 0; i < aklass->rank; ++i) {
563 sizes [i] = mono_array_get (lengths, guint32, i);
565 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
567 sizes [i + aklass->rank] = 0;
570 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
571 mono_error_set_pending_exception (&error);
576 ICALL_EXPORT MonoArray *
577 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
580 MonoClass *aklass, *klass;
583 gboolean bounded = FALSE;
585 MONO_CHECK_ARG_NULL (type, NULL);
586 MONO_CHECK_ARG_NULL (lengths, NULL);
588 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
590 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
592 for (i = 0; i < mono_array_length (lengths); i++) {
593 if ((mono_array_get (lengths, gint64, i) < 0) ||
594 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
595 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
600 klass = mono_class_from_mono_type (type->type);
601 mono_class_init_or_throw (klass);
603 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
604 /* vectors are not the same as one dimensional arrays with no-zero bounds */
609 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
611 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
612 for (i = 0; i < aklass->rank; ++i) {
613 sizes [i] = mono_array_get (lengths, guint64, i);
615 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
617 sizes [i + aklass->rank] = 0;
620 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
621 mono_error_set_pending_exception (&error);
627 ves_icall_System_Array_GetRank (MonoObject *arr)
629 return arr->vtable->klass->rank;
633 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
635 gint32 rank = arr->obj.vtable->klass->rank;
638 if ((dimension < 0) || (dimension >= rank)) {
639 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
643 if (arr->bounds == NULL)
644 length = arr->max_length;
646 length = arr->bounds [dimension].length;
648 #ifdef MONO_BIG_ARRAYS
649 if (length > G_MAXINT32) {
650 mono_set_pending_exception (mono_get_exception_overflow ());
658 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
660 gint32 rank = arr->obj.vtable->klass->rank;
662 if ((dimension < 0) || (dimension >= rank)) {
663 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
667 if (arr->bounds == NULL)
668 return arr->max_length;
670 return arr->bounds [dimension].length;
674 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
676 gint32 rank = arr->obj.vtable->klass->rank;
678 if ((dimension < 0) || (dimension >= rank)) {
679 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
683 if (arr->bounds == NULL)
686 return arr->bounds [dimension].lower_bound;
690 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
692 int sz = mono_array_element_size (mono_object_class (arr));
693 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
696 ICALL_EXPORT gboolean
697 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
702 MonoVTable *src_vtable;
703 MonoVTable *dest_vtable;
704 MonoClass *src_class;
705 MonoClass *dest_class;
707 src_vtable = source->obj.vtable;
708 dest_vtable = dest->obj.vtable;
710 if (src_vtable->rank != dest_vtable->rank)
713 if (source->bounds || dest->bounds)
716 /* there's no integer overflow since mono_array_length returns an unsigned integer */
717 if ((dest_idx + length > mono_array_length_fast (dest)) ||
718 (source_idx + length > mono_array_length_fast (source)))
721 src_class = src_vtable->klass->element_class;
722 dest_class = dest_vtable->klass->element_class;
725 * Handle common cases.
728 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
729 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
731 if (src_class == mono_defaults.object_class && dest_class->valuetype)
734 /* Check if we're copying a char[] <==> (u)short[] */
735 if (src_class != dest_class) {
736 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
739 /* 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. */
740 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
744 if (dest_class->valuetype) {
745 element_size = mono_array_element_size (source->obj.vtable->klass);
746 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
747 if (dest_class->has_references) {
748 mono_value_copy_array (dest, dest_idx, source_addr, length);
750 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
751 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
754 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
761 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
767 ac = (MonoClass *)arr->obj.vtable->klass;
769 esize = mono_array_element_size (ac);
770 ea = (gpointer*)((char*)arr->vector + (pos * esize));
772 mono_gc_memmove_atomic (value, ea, esize);
776 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
782 ac = (MonoClass *)arr->obj.vtable->klass;
783 ec = ac->element_class;
785 esize = mono_array_element_size (ac);
786 ea = (gpointer*)((char*)arr->vector + (pos * esize));
788 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
789 g_assert (esize == sizeof (gpointer));
790 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
792 g_assert (ec->inited);
793 g_assert (esize == mono_class_value_size (ec, NULL));
794 if (ec->has_references)
795 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
797 mono_gc_memmove_atomic (ea, value, esize);
802 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
804 MonoClass *klass = array->obj.vtable->klass;
805 guint32 size = mono_array_element_size (klass);
806 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
808 const char *field_data;
810 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
811 MonoException *exc = mono_get_exception_argument("array",
812 "Cannot initialize array of non-primitive type.");
813 mono_set_pending_exception (exc);
817 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
818 MonoException *exc = mono_get_exception_argument("field_handle",
819 "Field doesn't have an RVA");
820 mono_set_pending_exception (exc);
824 size *= array->max_length;
825 field_data = mono_field_get_data (field_handle);
827 if (size > mono_type_size (field_handle->type, &align)) {
828 MonoException *exc = mono_get_exception_argument("field_handle",
829 "Field not large enough to fill array");
830 mono_set_pending_exception (exc);
834 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
836 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
837 guint ## n *src = (guint ## n *) field_data; \
839 nEnt = (size / sizeof(guint ## n)); \
841 for (i = 0; i < nEnt; i++) { \
842 data[i] = read ## n (&src[i]); \
846 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
848 switch (type->type) {
865 memcpy (mono_array_addr (array, char, 0), field_data, size);
869 memcpy (mono_array_addr (array, char, 0), field_data, size);
874 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
876 return offsetof (MonoString, chars);
879 ICALL_EXPORT MonoObject *
880 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
882 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
886 MonoObject *ret = mono_object_clone_checked (obj, &error);
887 mono_error_set_pending_exception (&error);
894 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
900 MONO_CHECK_ARG_NULL (handle,);
902 klass = mono_class_from_mono_type (handle);
903 MONO_CHECK_ARG (handle, klass,);
905 if (klass->generic_container)
908 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
909 if (!is_ok (&error)) {
910 mono_error_set_pending_exception (&error);
914 /* This will call the type constructor */
915 if (!mono_runtime_class_init_full (vtable, &error))
916 mono_error_set_pending_exception (&error);
920 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
924 mono_image_check_for_module_cctor (image);
925 if (image->has_module_cctor) {
926 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
927 if (!mono_error_ok (&error)) {
928 mono_error_set_pending_exception (&error);
931 /*It's fine to raise the exception here*/
932 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
933 if (!is_ok (&error)) {
934 mono_error_set_pending_exception (&error);
937 if (!mono_runtime_class_init_full (vtable, &error))
938 mono_error_set_pending_exception (&error);
942 ICALL_EXPORT MonoBoolean
943 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
948 /* later make this configurable and per-arch */
949 int min_size = 4096 * 4 * sizeof (void*);
950 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
951 /* if we have no info we are optimistic and assume there is enough room */
955 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
959 current = (guint8 *)&stack_addr;
960 if (current > stack_addr) {
961 if ((current - stack_addr) < min_size)
964 if (current - (stack_addr - stack_size) < min_size)
970 ICALL_EXPORT MonoObject *
971 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
974 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
975 mono_error_set_pending_exception (&error);
981 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
984 MonoObject **values = NULL;
987 gint32 result = (int)(gsize)mono_defaults.int32_class;
988 MonoClassField* field;
991 klass = mono_object_class (this_obj);
993 if (mono_class_num_fields (klass) == 0)
997 * Compute the starting value of the hashcode for fields of primitive
998 * types, and return the remaining fields in an array to the managed side.
999 * This way, we can avoid costly reflection operations in managed code.
1002 while ((field = mono_class_get_fields (klass, &iter))) {
1003 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1005 if (mono_field_is_deleted (field))
1007 /* FIXME: Add more types */
1008 switch (field->type->type) {
1010 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1012 case MONO_TYPE_STRING: {
1014 s = *(MonoString**)((guint8*)this_obj + field->offset);
1016 result ^= mono_string_hash (s);
1021 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1022 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1023 values [count++] = o;
1029 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1030 for (i = 0; i < count; ++i)
1031 mono_array_setref (*fields, i, values [i]);
1038 ICALL_EXPORT MonoBoolean
1039 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1042 MonoObject **values = NULL;
1044 MonoClassField* field;
1048 MONO_CHECK_ARG_NULL (that, FALSE);
1050 if (this_obj->vtable != that->vtable)
1053 klass = mono_object_class (this_obj);
1055 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1056 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1059 * Do the comparison for fields of primitive type and return a result if
1060 * possible. Otherwise, return the remaining fields in an array to the
1061 * managed side. This way, we can avoid costly reflection operations in
1066 while ((field = mono_class_get_fields (klass, &iter))) {
1067 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1069 if (mono_field_is_deleted (field))
1071 /* FIXME: Add more types */
1072 switch (field->type->type) {
1075 case MONO_TYPE_BOOLEAN:
1076 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1081 case MONO_TYPE_CHAR:
1082 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1087 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1092 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1096 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1100 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1105 case MONO_TYPE_STRING: {
1106 MonoString *s1, *s2;
1107 guint32 s1len, s2len;
1108 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1109 s2 = *(MonoString**)((guint8*)that + field->offset);
1112 if ((s1 == NULL) || (s2 == NULL))
1114 s1len = mono_string_length (s1);
1115 s2len = mono_string_length (s2);
1119 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1125 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1126 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1127 values [count++] = o;
1128 o = mono_field_get_value_object (mono_object_domain (this_obj), field, that);
1129 values [count++] = o;
1132 if (klass->enumtype)
1133 /* enums only have one non-static field */
1139 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1140 for (i = 0; i < count; ++i)
1141 mono_array_setref_fast (*fields, i, values [i]);
1148 ICALL_EXPORT MonoReflectionType *
1149 ves_icall_System_Object_GetType (MonoObject *obj)
1152 MonoReflectionType *ret;
1153 #ifndef DISABLE_REMOTING
1154 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1155 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1158 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1160 mono_error_raise_exception (&error);
1166 ves_icall_MonoType_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1168 mtype->type = &obj->vtable->klass->byval_arg;
1169 g_assert (mtype->type->type);
1173 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1175 MONO_CHECK_ARG_NULL (obj, 0);
1178 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1179 mono_error_raise_exception (&error);
1184 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1185 MonoReflectionMethod *method,
1186 MonoArray *opt_param_types)
1188 MONO_CHECK_ARG_NULL (method, 0);
1191 gint32 result = mono_image_create_method_token (
1192 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1193 mono_error_raise_exception (&error);
1198 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1201 mono_image_create_pefile (mb, file, &error);
1202 mono_error_raise_exception (&error);
1206 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1209 if (!mono_image_build_metadata (mb, &error))
1210 mono_error_raise_exception (&error);
1214 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1216 mono_image_register_token (mb->dynamic_image, token, obj);
1219 ICALL_EXPORT MonoObject*
1220 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1224 mono_loader_lock ();
1225 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1226 mono_loader_unlock ();
1232 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1234 MonoMethod **dest = (MonoMethod **)data;
1236 /* skip unmanaged frames */
1252 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1254 MonoMethod **dest = (MonoMethod **)data;
1256 /* skip unmanaged frames */
1261 if (!strcmp (m->klass->name_space, "System.Reflection"))
1270 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1272 MonoMethod **dest = (MonoMethod **)data;
1274 /* skip unmanaged frames */
1278 if (m->wrapper_type != MONO_WRAPPER_NONE)
1281 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1295 static MonoReflectionType *
1296 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1298 MonoMethod *m, *dest;
1300 MonoType *type = NULL;
1301 MonoAssembly *assembly = NULL;
1302 gboolean type_resolve = FALSE;
1304 mono_error_init (error);
1307 * We must compute the calling assembly as type loading must happen under a metadata context.
1308 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1309 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1311 m = mono_method_get_last_managed ();
1314 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1319 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1320 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1321 * to crash. This only seems to happen in some strange remoting
1322 * scenarios and I was unable to figure out what's happening there.
1323 * Dec 10, 2005 - Martin.
1327 assembly = dest->klass->image->assembly;
1328 type_resolve = TRUE;
1330 g_warning (G_STRLOC);
1333 if (info->assembly.name)
1334 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1338 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1339 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1342 if (!info->assembly.name && !type) /* try mscorlib */
1343 type = mono_reflection_get_type (NULL, info, ignoreCase, &type_resolve);
1345 if (assembly && !type && type_resolve) {
1346 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1347 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1353 return mono_type_get_object_checked (mono_domain_get (), type, error);
1356 ICALL_EXPORT MonoReflectionType*
1357 ves_icall_System_Type_internal_from_name (MonoString *name,
1358 MonoBoolean throwOnError,
1359 MonoBoolean ignoreCase)
1362 char *str = mono_string_to_utf8 (name);
1363 MonoTypeNameParse info;
1364 MonoReflectionType *type;
1367 parsedOk = mono_reflection_parse_type (str, &info);
1369 /* mono_reflection_parse_type() mangles the string */
1371 mono_reflection_free_type_info (&info);
1374 mono_set_pending_exception (mono_get_exception_argument("typeName", "failed parse"));
1379 type = type_from_parsed_name (&info, ignoreCase, &error);
1381 mono_reflection_free_type_info (&info);
1384 if (!mono_error_ok (&error)) {
1386 mono_error_set_pending_exception (&error);
1388 mono_error_cleanup (&error);
1393 MonoException *e = NULL;
1396 e = mono_get_exception_type_load (name, NULL);
1398 mono_loader_clear_error ();
1400 mono_set_pending_exception (e);
1409 ICALL_EXPORT MonoReflectionType*
1410 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1413 MonoReflectionType *ret;
1414 MonoDomain *domain = mono_domain_get ();
1416 ret = mono_type_get_object_checked (domain, handle, &error);
1417 mono_error_raise_exception (&error);
1422 /* System.TypeCode */
1441 TYPECODE_STRING = 18
1444 ICALL_EXPORT guint32
1445 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1447 int t = type->type->type;
1449 if (type->type->byref)
1450 return TYPECODE_OBJECT;
1454 case MONO_TYPE_VOID:
1455 return TYPECODE_OBJECT;
1456 case MONO_TYPE_BOOLEAN:
1457 return TYPECODE_BOOLEAN;
1459 return TYPECODE_BYTE;
1461 return TYPECODE_SBYTE;
1463 return TYPECODE_UINT16;
1465 return TYPECODE_INT16;
1466 case MONO_TYPE_CHAR:
1467 return TYPECODE_CHAR;
1471 return TYPECODE_OBJECT;
1473 return TYPECODE_UINT32;
1475 return TYPECODE_INT32;
1477 return TYPECODE_UINT64;
1479 return TYPECODE_INT64;
1481 return TYPECODE_SINGLE;
1483 return TYPECODE_DOUBLE;
1484 case MONO_TYPE_VALUETYPE: {
1485 MonoClass *klass = type->type->data.klass;
1487 if (klass->enumtype) {
1488 t = mono_class_enum_basetype (klass)->type;
1490 } else if (mono_is_corlib_image (klass->image)) {
1491 if (strcmp (klass->name_space, "System") == 0) {
1492 if (strcmp (klass->name, "Decimal") == 0)
1493 return TYPECODE_DECIMAL;
1494 else if (strcmp (klass->name, "DateTime") == 0)
1495 return TYPECODE_DATETIME;
1498 return TYPECODE_OBJECT;
1500 case MONO_TYPE_STRING:
1501 return TYPECODE_STRING;
1502 case MONO_TYPE_SZARRAY:
1503 case MONO_TYPE_ARRAY:
1504 case MONO_TYPE_OBJECT:
1506 case MONO_TYPE_MVAR:
1507 case MONO_TYPE_TYPEDBYREF:
1508 return TYPECODE_OBJECT;
1509 case MONO_TYPE_CLASS:
1511 MonoClass *klass = type->type->data.klass;
1512 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1513 if (strcmp (klass->name, "DBNull") == 0)
1514 return TYPECODE_DBNULL;
1517 return TYPECODE_OBJECT;
1518 case MONO_TYPE_GENERICINST:
1519 return TYPECODE_OBJECT;
1521 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1527 mono_type_is_primitive (MonoType *type)
1529 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1530 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1534 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1536 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1537 return mono_class_enum_basetype (type->data.klass);
1538 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1539 return mono_class_enum_basetype (type->data.generic_class->container_class);
1543 ICALL_EXPORT guint32
1544 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1549 g_assert (type != NULL);
1551 klass = mono_class_from_mono_type (type->type);
1552 klassc = mono_class_from_mono_type (c->type);
1554 if (type->type->byref ^ c->type->byref)
1557 if (type->type->byref) {
1558 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1559 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1561 klass = mono_class_from_mono_type (t);
1562 klassc = mono_class_from_mono_type (ot);
1564 if (mono_type_is_primitive (t)) {
1565 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1566 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1567 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1568 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1569 return t->type == ot->type;
1571 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1574 if (klass->valuetype)
1575 return klass == klassc;
1576 return klass->valuetype == klassc->valuetype;
1579 return mono_class_is_assignable_from (klass, klassc);
1582 ICALL_EXPORT guint32
1583 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1585 MonoClass *klass = mono_class_from_mono_type (type->type);
1586 mono_class_init_or_throw (klass);
1587 return mono_object_isinst (obj, klass) != NULL;
1590 ICALL_EXPORT guint32
1591 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1593 MonoClass *klass = mono_class_from_mono_type (type->type);
1594 return klass->flags;
1597 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1598 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1601 MonoClass *klass = field->field->parent;
1602 MonoMarshalType *info;
1606 if (klass->generic_container ||
1607 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1610 ftype = mono_field_get_type (field->field);
1611 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1614 info = mono_marshal_load_type_info (klass);
1616 for (i = 0; i < info->num_fields; ++i) {
1617 if (info->fields [i].field == field->field) {
1618 if (!info->fields [i].mspec)
1621 MonoReflectionMarshalAsAttribute* obj;
1622 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1623 if (!mono_error_ok (&error))
1624 mono_error_set_pending_exception (&error);
1633 ICALL_EXPORT MonoReflectionField*
1634 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1637 gboolean found = FALSE;
1644 klass = handle->parent;
1646 klass = mono_class_from_mono_type (type);
1648 /* Check that the field belongs to the class */
1649 for (k = klass; k; k = k->parent) {
1650 if (k == handle->parent) {
1657 /* The managed code will throw the exception */
1661 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1662 mono_error_raise_exception (&error);
1666 ICALL_EXPORT MonoArray*
1667 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1670 MonoType *type = mono_field_get_type_checked (field->field, &error);
1671 if (!mono_error_ok (&error)) {
1672 mono_error_set_pending_exception (&error);
1676 return type_array_from_modifiers (field->field->parent->image, type, optional);
1680 vell_icall_get_method_attributes (MonoMethod *method)
1682 return method->flags;
1686 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1689 MonoReflectionType *rt;
1690 MonoDomain *domain = mono_domain_get ();
1691 MonoMethodSignature* sig;
1693 sig = mono_method_signature_checked (method, &error);
1694 if (!mono_error_ok (&error)) {
1695 mono_error_set_pending_exception (&error);
1699 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1700 if (!mono_error_ok (&error)) {
1701 mono_error_set_pending_exception (&error);
1705 MONO_STRUCT_SETREF (info, parent, rt);
1707 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1708 if (!mono_error_ok (&error)) {
1709 mono_error_set_pending_exception (&error);
1713 MONO_STRUCT_SETREF (info, ret, rt);
1715 info->attrs = method->flags;
1716 info->implattrs = method->iflags;
1717 if (sig->call_convention == MONO_CALL_DEFAULT)
1718 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1720 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1725 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1728 ICALL_EXPORT MonoArray*
1729 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1731 MonoDomain *domain = mono_domain_get ();
1733 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1736 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1737 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1740 MonoDomain *domain = mono_domain_get ();
1741 MonoReflectionMarshalAsAttribute* res = NULL;
1742 MonoMarshalSpec **mspecs;
1745 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1746 mono_method_get_marshal_info (method, mspecs);
1749 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1750 if (!mono_error_ok (&error)) {
1751 mono_error_set_pending_exception (&error);
1756 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1758 mono_metadata_free_marshal_spec (mspecs [i]);
1765 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1767 MonoClass *parent = field->field->parent;
1768 if (!parent->size_inited)
1769 mono_class_init (parent);
1770 mono_class_setup_fields_locking (parent);
1772 return field->field->offset - sizeof (MonoObject);
1775 ICALL_EXPORT MonoReflectionType*
1776 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1779 MonoReflectionType *ret;
1782 parent = declaring? field->field->parent: field->klass;
1784 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1785 mono_error_raise_exception (&error);
1791 ICALL_EXPORT MonoObject *
1792 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1794 MonoClass *fklass = field->klass;
1795 MonoClassField *cf = field->field;
1796 MonoDomain *domain = mono_object_domain (field);
1798 if (fklass->image->assembly->ref_only) {
1799 mono_set_pending_exception (mono_get_exception_invalid_operation (
1800 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1804 if (mono_security_core_clr_enabled ())
1805 mono_security_core_clr_ensure_reflection_access_field (cf);
1807 return mono_field_get_value_object (domain, cf, obj);
1811 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1814 MonoClassField *cf = field->field;
1818 if (field->klass->image->assembly->ref_only) {
1819 mono_set_pending_exception (mono_get_exception_invalid_operation (
1820 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1824 if (mono_security_core_clr_enabled ())
1825 mono_security_core_clr_ensure_reflection_access_field (cf);
1827 type = mono_field_get_type_checked (cf, &error);
1828 if (!mono_error_ok (&error)) {
1829 mono_error_set_pending_exception (&error);
1833 v = (gchar *) value;
1835 switch (type->type) {
1838 case MONO_TYPE_BOOLEAN:
1841 case MONO_TYPE_CHAR:
1850 case MONO_TYPE_VALUETYPE:
1853 v += sizeof (MonoObject);
1855 case MONO_TYPE_STRING:
1856 case MONO_TYPE_OBJECT:
1857 case MONO_TYPE_CLASS:
1858 case MONO_TYPE_ARRAY:
1859 case MONO_TYPE_SZARRAY:
1862 case MONO_TYPE_GENERICINST: {
1863 MonoGenericClass *gclass = type->data.generic_class;
1864 g_assert (!gclass->context.class_inst->is_open);
1866 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1867 MonoClass *nklass = mono_class_from_mono_type (type);
1868 MonoObject *nullable;
1871 * Convert the boxed vtype into a Nullable structure.
1872 * This is complicated by the fact that Nullables have
1873 * a variable structure.
1875 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1876 if (!mono_error_ok (&error)) {
1877 mono_error_set_pending_exception (&error);
1881 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1883 v = (gchar *)mono_object_unbox (nullable);
1886 if (gclass->container_class->valuetype && (v != NULL))
1887 v += sizeof (MonoObject);
1891 g_error ("type 0x%x not handled in "
1892 "ves_icall_FieldInfo_SetValueInternal", type->type);
1897 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1898 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
1899 if (!is_ok (&error)) {
1900 mono_error_set_pending_exception (&error);
1903 if (!vtable->initialized) {
1904 if (!mono_runtime_class_init_full (vtable, &error)) {
1905 mono_error_set_pending_exception (&error);
1909 mono_field_static_set_value (vtable, cf, v);
1911 mono_field_set_value (obj, cf, v);
1916 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1925 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1926 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1930 if (MONO_TYPE_IS_REFERENCE (f->type))
1931 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1933 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1936 ICALL_EXPORT MonoObject *
1937 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1939 MonoObject *o = NULL;
1940 MonoClassField *field = rfield->field;
1942 MonoDomain *domain = mono_object_domain (rfield);
1944 MonoTypeEnum def_type;
1945 const char *def_value;
1949 mono_class_init (field->parent);
1951 t = mono_field_get_type_checked (field, &error);
1952 if (!mono_error_ok (&error)) {
1953 mono_error_set_pending_exception (&error);
1957 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
1958 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1962 if (image_is_dynamic (field->parent->image)) {
1963 MonoClass *klass = field->parent;
1964 int fidx = field - klass->fields;
1966 g_assert (fidx >= 0 && fidx < klass->field.count);
1967 g_assert (klass->ext);
1968 g_assert (klass->ext->field_def_values);
1969 def_type = klass->ext->field_def_values [fidx].def_type;
1970 def_value = klass->ext->field_def_values [fidx].data;
1971 if (def_type == MONO_TYPE_END) {
1972 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1976 def_value = mono_class_get_field_default_value (field, &def_type);
1977 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
1979 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1984 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1988 case MONO_TYPE_BOOLEAN:
1991 case MONO_TYPE_CHAR:
1999 case MONO_TYPE_R8: {
2002 /* boxed value type */
2003 t = g_new0 (MonoType, 1);
2005 klass = mono_class_from_mono_type (t);
2007 o = mono_object_new_checked (domain, klass, &error);
2008 if (!mono_error_ok (&error)) {
2009 mono_error_set_pending_exception (&error);
2012 v = ((gchar *) o) + sizeof (MonoObject);
2013 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2016 case MONO_TYPE_STRING:
2017 case MONO_TYPE_CLASS:
2018 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2021 g_assert_not_reached ();
2027 ICALL_EXPORT MonoReflectionType*
2028 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2031 MonoReflectionType *ret;
2034 type = mono_field_get_type_checked (ref_field->field, &error);
2035 if (!mono_error_ok (&error)) {
2036 mono_error_set_pending_exception (&error);
2040 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2041 if (!mono_error_ok (&error)) {
2042 mono_error_set_pending_exception (&error);
2049 /* From MonoProperty.cs */
2051 PInfo_Attributes = 1,
2052 PInfo_GetMethod = 1 << 1,
2053 PInfo_SetMethod = 1 << 2,
2054 PInfo_ReflectedType = 1 << 3,
2055 PInfo_DeclaringType = 1 << 4,
2060 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2063 MonoReflectionType *rt;
2064 MonoReflectionMethod *rm;
2065 MonoDomain *domain = mono_object_domain (property);
2066 const MonoProperty *pproperty = property->property;
2068 if ((req_info & PInfo_ReflectedType) != 0) {
2069 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2070 mono_error_raise_exception (&error);
2072 MONO_STRUCT_SETREF (info, parent, rt);
2074 if ((req_info & PInfo_DeclaringType) != 0) {
2075 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2076 mono_error_raise_exception (&error);
2078 MONO_STRUCT_SETREF (info, declaring_type, rt);
2081 if ((req_info & PInfo_Name) != 0)
2082 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2084 if ((req_info & PInfo_Attributes) != 0)
2085 info->attrs = pproperty->attrs;
2087 if ((req_info & PInfo_GetMethod) != 0) {
2088 if (pproperty->get &&
2089 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2090 pproperty->get->klass == property->klass)) {
2091 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2092 mono_error_raise_exception (&error);
2097 MONO_STRUCT_SETREF (info, get, rm);
2099 if ((req_info & PInfo_SetMethod) != 0) {
2100 if (pproperty->set &&
2101 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2102 pproperty->set->klass == property->klass)) {
2103 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2104 mono_error_raise_exception (&error);
2109 MONO_STRUCT_SETREF (info, set, rm);
2112 * There may be other methods defined for properties, though, it seems they are not exposed
2113 * in the reflection API
2118 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2121 MonoReflectionType *rt;
2122 MonoReflectionMethod *rm;
2123 MonoDomain *domain = mono_object_domain (event);
2125 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2126 mono_error_raise_exception (&error);
2128 MONO_STRUCT_SETREF (info, reflected_type, rt);
2130 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2131 mono_error_raise_exception (&error);
2133 MONO_STRUCT_SETREF (info, declaring_type, rt);
2135 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2136 info->attrs = event->event->attrs;
2138 if (event->event->add) {
2139 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2140 mono_error_raise_exception (&error);
2145 MONO_STRUCT_SETREF (info, add_method, rm);
2147 if (event->event->remove) {
2148 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2149 mono_error_raise_exception (&error);
2154 MONO_STRUCT_SETREF (info, remove_method, rm);
2156 if (event->event->raise) {
2157 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2158 mono_error_raise_exception (&error);
2163 MONO_STRUCT_SETREF (info, raise_method, rm);
2165 #ifndef MONO_SMALL_CONFIG
2166 if (event->event->other) {
2168 while (event->event->other [n])
2170 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2172 for (i = 0; i < n; i++) {
2173 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2174 mono_error_raise_exception (&error);
2175 mono_array_setref (info->other_methods, i, rm);
2182 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2187 mono_class_setup_interfaces (klass, error);
2188 if (!mono_error_ok (error))
2191 for (i = 0; i < klass->interface_count; i++) {
2192 ic = klass->interfaces [i];
2193 g_hash_table_insert (ifaces, ic, ic);
2195 collect_interfaces (ic, ifaces, error);
2196 if (!mono_error_ok (error))
2202 MonoArray *iface_array;
2203 MonoGenericContext *context;
2207 } FillIfaceArrayData;
2210 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2212 MonoReflectionType *rt;
2213 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2214 MonoClass *ic = (MonoClass *)key;
2215 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2217 if (!mono_error_ok (data->error))
2220 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2221 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2222 if (!mono_error_ok (data->error))
2226 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2227 if (!mono_error_ok (data->error))
2230 mono_array_setref (data->iface_array, data->next_idx++, rt);
2233 mono_metadata_free_type (inflated);
2237 get_interfaces_hash (gconstpointer v1)
2239 MonoClass *k = (MonoClass*)v1;
2241 return k->type_token;
2244 ICALL_EXPORT MonoArray*
2245 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2248 MonoClass *klass = mono_class_from_mono_type (type->type);
2250 FillIfaceArrayData data = { 0 };
2253 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2255 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2256 data.context = mono_class_get_context (klass);
2257 klass = klass->generic_class->container_class;
2260 for (parent = klass; parent; parent = parent->parent) {
2261 mono_class_setup_interfaces (parent, &error);
2262 if (!mono_error_ok (&error))
2264 collect_interfaces (parent, iface_hash, &error);
2265 if (!mono_error_ok (&error))
2269 data.error = &error;
2270 data.domain = mono_object_domain (type);
2272 len = g_hash_table_size (iface_hash);
2274 g_hash_table_destroy (iface_hash);
2275 if (!data.domain->empty_types)
2276 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2277 return data.domain->empty_types;
2280 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2281 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2282 if (!mono_error_ok (&error))
2285 g_hash_table_destroy (iface_hash);
2286 return data.iface_array;
2289 g_hash_table_destroy (iface_hash);
2290 mono_error_set_pending_exception (&error);
2295 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2297 gboolean variance_used;
2298 MonoClass *klass = mono_class_from_mono_type (type->type);
2299 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2300 MonoReflectionMethod *member;
2303 int i = 0, len, ioffset;
2307 mono_class_init_or_throw (klass);
2308 mono_class_init_or_throw (iclass);
2310 mono_class_setup_vtable (klass);
2312 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2316 len = mono_class_num_methods (iclass);
2317 domain = mono_object_domain (type);
2318 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2319 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2321 while ((method = mono_class_get_methods (iclass, &iter))) {
2322 member = mono_method_get_object_checked (domain, method, iclass, &error);
2323 mono_error_raise_exception (&error);
2324 mono_array_setref (*methods, i, member);
2325 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2326 mono_error_raise_exception (&error);
2327 mono_array_setref (*targets, i, member);
2334 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2336 MonoClass *klass = mono_class_from_mono_type (type->type);
2337 mono_class_init_or_throw (klass);
2339 if (image_is_dynamic (klass->image)) {
2340 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2341 *packing = tb->packing_size;
2342 *size = tb->class_size;
2344 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2348 ICALL_EXPORT MonoReflectionType*
2349 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2352 MonoReflectionType *ret;
2355 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2356 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2357 mono_error_raise_exception (&error);
2362 klass = mono_class_from_mono_type (type->type);
2363 mono_class_init_or_throw (klass);
2365 // GetElementType should only return a type for:
2366 // Array Pointer PassedByRef
2367 if (type->type->byref)
2368 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2369 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2370 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2371 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2372 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2376 mono_error_raise_exception (&error);
2381 ICALL_EXPORT MonoReflectionType*
2382 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2385 MonoReflectionType *ret;
2387 if (type->type->byref)
2390 MonoClass *klass = mono_class_from_mono_type (type->type);
2394 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2395 mono_error_raise_exception (&error);
2400 ICALL_EXPORT MonoBoolean
2401 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2403 return type->type->type == MONO_TYPE_PTR;
2406 ICALL_EXPORT MonoBoolean
2407 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2409 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)));
2412 ICALL_EXPORT MonoBoolean
2413 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2415 return type->type->byref;
2418 ICALL_EXPORT MonoBoolean
2419 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2421 MonoClass *klass = mono_class_from_mono_type (type->type);
2422 mono_class_init_or_throw (klass);
2424 return mono_class_is_com_object (klass);
2427 ICALL_EXPORT guint32
2428 ves_icall_RuntimeTypeHandle_GetMetadataToken (MonoReflectionType *obj)
2430 return mono_reflection_get_token ((MonoObject*)obj);
2433 ICALL_EXPORT MonoReflectionModule*
2434 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2437 MonoReflectionModule *result = NULL;
2438 MonoClass *klass = mono_class_from_mono_type (type->type);
2439 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2440 if (!mono_error_ok (&error))
2441 mono_error_set_pending_exception (&error);
2445 ICALL_EXPORT MonoReflectionAssembly*
2446 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2449 MonoDomain *domain = mono_domain_get ();
2450 MonoClass *klass = mono_class_from_mono_type (type->type);
2451 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2453 mono_error_set_pending_exception (&error);
2457 ICALL_EXPORT MonoReflectionType*
2458 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2461 MonoReflectionType *ret;
2462 MonoDomain *domain = mono_domain_get ();
2465 if (type->type->byref)
2467 if (type->type->type == MONO_TYPE_VAR) {
2468 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2469 klass = param ? param->owner.klass : NULL;
2470 } else if (type->type->type == MONO_TYPE_MVAR) {
2471 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2472 klass = param ? param->owner.method->klass : NULL;
2474 klass = mono_class_from_mono_type (type->type)->nested_in;
2480 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2481 mono_error_raise_exception (&error);
2486 ICALL_EXPORT MonoString*
2487 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2489 MonoDomain *domain = mono_domain_get ();
2490 MonoClass *klass = mono_class_from_mono_type (type->type);
2492 if (type->type->byref) {
2493 char *n = g_strdup_printf ("%s&", klass->name);
2494 MonoString *res = mono_string_new (domain, n);
2500 return mono_string_new (domain, klass->name);
2504 ICALL_EXPORT MonoString*
2505 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2507 MonoDomain *domain = mono_domain_get ();
2508 MonoClass *klass = mono_class_from_mono_type (type->type);
2510 while (klass->nested_in)
2511 klass = klass->nested_in;
2513 if (klass->name_space [0] == '\0')
2516 return mono_string_new (domain, klass->name_space);
2520 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2524 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2525 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2529 klass = mono_class_from_mono_type (type->type);
2535 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2538 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2542 ICALL_EXPORT MonoArray*
2543 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2546 MonoReflectionType *rt;
2548 MonoClass *klass, *pklass;
2549 MonoDomain *domain = mono_object_domain (type);
2552 klass = mono_class_from_mono_type (type->type);
2554 if (klass->generic_container) {
2555 MonoGenericContainer *container = klass->generic_container;
2556 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2557 for (i = 0; i < container->type_argc; ++i) {
2558 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2560 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2561 mono_error_raise_exception (&error);
2563 mono_array_setref (res, i, rt);
2565 } else if (klass->generic_class) {
2566 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2567 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2568 for (i = 0; i < inst->type_argc; ++i) {
2569 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2570 mono_error_raise_exception (&error);
2572 mono_array_setref (res, i, rt);
2580 ICALL_EXPORT gboolean
2581 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2585 if (!IS_MONOTYPE (type))
2588 if (type->type->byref)
2591 klass = mono_class_from_mono_type (type->type);
2592 return klass->generic_container != NULL;
2595 ICALL_EXPORT MonoReflectionType*
2596 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2599 MonoReflectionType *ret;
2602 if (type->type->byref)
2605 klass = mono_class_from_mono_type (type->type);
2607 if (klass->generic_container) {
2608 return type; /* check this one */
2610 if (klass->generic_class) {
2611 MonoClass *generic_class = klass->generic_class->container_class;
2614 tb = mono_class_get_ref_info (generic_class);
2616 if (generic_class->wastypebuilder && tb)
2617 return (MonoReflectionType *)tb;
2619 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2620 mono_error_raise_exception (&error);
2628 ICALL_EXPORT MonoReflectionType*
2629 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2632 MonoReflectionType *ret;
2634 MonoType *geninst, **types;
2637 g_assert (IS_MONOTYPE (type));
2638 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2640 count = mono_array_length (type_array);
2641 types = g_new0 (MonoType *, count);
2643 for (i = 0; i < count; i++) {
2644 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2645 types [i] = t->type;
2648 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2653 klass = mono_class_from_mono_type (geninst);
2655 /*we might inflate to the GTD*/
2656 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2657 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2661 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2662 mono_error_raise_exception (&error);
2667 ICALL_EXPORT gboolean
2668 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2672 if (!IS_MONOTYPE (type))
2675 if (type->type->byref)
2678 klass = mono_class_from_mono_type (type->type);
2679 return klass->generic_class != NULL || klass->generic_container != NULL;
2683 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2685 if (!IS_MONOTYPE (type))
2688 if (is_generic_parameter (type->type))
2689 return mono_type_get_generic_param_num (type->type);
2693 ICALL_EXPORT GenericParameterAttributes
2694 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2696 g_assert (IS_MONOTYPE (type));
2697 g_assert (is_generic_parameter (type->type));
2698 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2701 ICALL_EXPORT MonoArray *
2702 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2705 MonoReflectionType *rt;
2706 MonoGenericParamInfo *param_info;
2712 g_assert (IS_MONOTYPE (type));
2714 domain = mono_object_domain (type);
2715 param_info = mono_generic_param_info (type->type->data.generic_param);
2716 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2719 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2720 for (i = 0; i < count; i++) {
2721 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2722 mono_error_raise_exception (&error);
2724 mono_array_setref (res, i, rt);
2731 ICALL_EXPORT MonoBoolean
2732 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2734 return is_generic_parameter (type->type);
2737 ICALL_EXPORT MonoBoolean
2738 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2740 return is_generic_parameter (tb->type.type);
2744 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2745 MonoReflectionType *t)
2747 enumtype->type = t->type;
2750 ICALL_EXPORT MonoReflectionMethod*
2751 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2752 MonoReflectionMethod* generic)
2759 MonoReflectionMethod *ret = NULL;
2761 domain = ((MonoObject *)type)->vtable->domain;
2763 klass = mono_class_from_mono_type (type->type);
2764 mono_class_init_or_throw (klass);
2767 while ((method = mono_class_get_methods (klass, &iter))) {
2768 if (method->token == generic->method->token) {
2769 ret = mono_method_get_object_checked (domain, method, klass, &error);
2770 mono_error_raise_exception (&error);
2777 ICALL_EXPORT MonoReflectionMethod *
2778 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2781 MonoType *type = ref_type->type;
2783 MonoReflectionMethod *ret = NULL;
2785 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2786 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2789 if (type->type == MONO_TYPE_VAR)
2792 method = mono_type_get_generic_param_owner (type)->owner.method;
2795 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2796 if (!mono_error_ok (&error))
2797 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2801 ICALL_EXPORT MonoBoolean
2802 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2804 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2808 ICALL_EXPORT MonoBoolean
2809 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2811 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2816 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2818 MonoDomain *domain = mono_domain_get ();
2819 MonoImage *image = method->method->klass->image;
2820 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2821 MonoTableInfo *tables = image->tables;
2822 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2823 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2824 guint32 im_cols [MONO_IMPLMAP_SIZE];
2825 guint32 scope_token;
2826 const char *import = NULL;
2827 const char *scope = NULL;
2829 if (image_is_dynamic (image)) {
2830 MonoReflectionMethodAux *method_aux =
2831 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2833 import = method_aux->dllentry;
2834 scope = method_aux->dll;
2837 if (!import || !scope) {
2838 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2843 if (piinfo->implmap_idx) {
2844 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2846 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2847 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2848 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2849 scope = mono_metadata_string_heap (image, scope_token);
2853 *flags = piinfo->piflags;
2854 *entry_point = mono_string_new (domain, import);
2855 *dll_name = mono_string_new (domain, scope);
2858 ICALL_EXPORT MonoReflectionMethod *
2859 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2861 MonoMethodInflated *imethod;
2863 MonoReflectionMethod *ret = NULL;
2866 if (method->method->is_generic)
2869 if (!method->method->is_inflated)
2872 imethod = (MonoMethodInflated *) method->method;
2874 result = imethod->declaring;
2875 /* Not a generic method. */
2876 if (!result->is_generic)
2879 if (image_is_dynamic (method->method->klass->image)) {
2880 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2881 MonoReflectionMethod *res;
2884 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2885 * the dynamic case as well ?
2887 mono_image_lock ((MonoImage*)image);
2888 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2889 mono_image_unlock ((MonoImage*)image);
2895 if (imethod->context.class_inst) {
2896 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2897 /*Generic methods gets the context of the GTD.*/
2898 if (mono_class_get_context (klass)) {
2899 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2900 if (!mono_error_ok (&error))
2905 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2907 if (!mono_error_ok (&error))
2908 mono_error_set_pending_exception (&error);
2912 ICALL_EXPORT gboolean
2913 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2915 return mono_method_signature (method->method)->generic_param_count != 0;
2918 ICALL_EXPORT gboolean
2919 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2921 return method->method->is_generic;
2924 ICALL_EXPORT MonoArray*
2925 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2928 MonoReflectionType *rt;
2933 domain = mono_object_domain (method);
2935 if (method->method->is_inflated) {
2936 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2939 count = inst->type_argc;
2940 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2942 for (i = 0; i < count; i++) {
2943 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2944 mono_error_raise_exception (&error);
2946 mono_array_setref (res, i, rt);
2953 count = mono_method_signature (method->method)->generic_param_count;
2954 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2956 for (i = 0; i < count; i++) {
2957 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2958 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2959 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
2961 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2962 mono_error_raise_exception (&error);
2964 mono_array_setref (res, i, rt);
2970 ICALL_EXPORT MonoObject *
2971 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
2975 * Invoke from reflection is supposed to always be a virtual call (the API
2976 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2977 * greater flexibility.
2979 MonoMethod *m = method->method;
2980 MonoMethodSignature *sig = mono_method_signature (m);
2983 void *obj = this_arg;
2987 if (mono_security_core_clr_enabled ())
2988 mono_security_core_clr_ensure_reflection_access_method (m);
2990 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2991 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
2992 mono_error_cleanup (&error); /* FIXME does this make sense? */
2993 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2998 if (!mono_object_isinst (this_arg, m->klass)) {
2999 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3000 char *target_name = mono_type_get_full_name (m->klass);
3001 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3002 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3004 g_free (target_name);
3008 m = mono_object_get_virtual_method (this_arg, m);
3009 /* must pass the pointer to the value for valuetype methods */
3010 if (m->klass->valuetype)
3011 obj = mono_object_unbox (this_arg);
3012 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3013 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3018 if (sig->ret->byref) {
3019 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"));
3023 pcount = params? mono_array_length (params): 0;
3024 if (pcount != sig->param_count) {
3025 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3029 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3030 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."));
3034 image = m->klass->image;
3035 if (image->assembly->ref_only) {
3036 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."));
3040 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3041 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3045 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3049 intptr_t *lower_bounds;
3050 pcount = mono_array_length (params);
3051 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3052 /* Note: the synthetized array .ctors have int32 as argument type */
3053 for (i = 0; i < pcount; ++i)
3054 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3056 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3057 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3058 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3059 if (!mono_error_ok (&error)) {
3060 mono_error_set_pending_exception (&error);
3064 for (i = 0; i < mono_array_length (arr); ++i) {
3065 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3066 if (!mono_error_ok (&error)) {
3067 mono_error_set_pending_exception (&error);
3070 mono_array_setref_fast (arr, i, subarray);
3072 return (MonoObject*)arr;
3075 if (m->klass->rank == pcount) {
3076 /* Only lengths provided. */
3077 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3078 if (!mono_error_ok (&error)) {
3079 mono_error_set_pending_exception (&error);
3083 return (MonoObject*)arr;
3085 g_assert (pcount == (m->klass->rank * 2));
3086 /* The arguments are lower-bound-length pairs */
3087 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3089 for (i = 0; i < pcount / 2; ++i) {
3090 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3091 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3094 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3095 if (!mono_error_ok (&error)) {
3096 mono_error_set_pending_exception (&error);
3100 return (MonoObject*)arr;
3103 return mono_runtime_invoke_array (m, obj, params, NULL);
3106 #ifndef DISABLE_REMOTING
3107 ICALL_EXPORT MonoObject *
3108 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3110 MonoDomain *domain = mono_object_domain (method);
3111 MonoMethod *m = method->method;
3112 MonoMethodSignature *sig = mono_method_signature (m);
3113 MonoArray *out_args;
3115 int i, j, outarg_count = 0;
3117 if (m->klass == mono_defaults.object_class) {
3118 if (!strcmp (m->name, "FieldGetter")) {
3119 MonoClass *k = this_arg->vtable->klass;
3123 /* If this is a proxy, then it must be a CBO */
3124 if (k == mono_defaults.transparent_proxy_class) {
3125 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3126 this_arg = tp->rp->unwrapped_server;
3127 g_assert (this_arg);
3128 k = this_arg->vtable->klass;
3131 name = mono_array_get (params, MonoString *, 1);
3132 str = mono_string_to_utf8 (name);
3135 MonoClassField* field = mono_class_get_field_from_name (k, str);
3137 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3138 if (field_klass->valuetype)
3139 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
3141 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3143 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3144 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3145 mono_array_setref (out_args, 0, result);
3153 g_assert_not_reached ();
3155 } else if (!strcmp (m->name, "FieldSetter")) {
3156 MonoClass *k = this_arg->vtable->klass;
3162 /* If this is a proxy, then it must be a CBO */
3163 if (k == mono_defaults.transparent_proxy_class) {
3164 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3165 this_arg = tp->rp->unwrapped_server;
3166 g_assert (this_arg);
3167 k = this_arg->vtable->klass;
3170 name = mono_array_get (params, MonoString *, 1);
3171 str = mono_string_to_utf8 (name);
3174 MonoClassField* field = mono_class_get_field_from_name (k, str);
3176 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3177 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3179 if (field_klass->valuetype) {
3180 size = mono_type_size (field->type, &align);
3181 g_assert (size == mono_class_value_size (field_klass, NULL));
3182 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3184 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3187 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3188 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3198 g_assert_not_reached ();
3203 for (i = 0; i < mono_array_length (params); i++) {
3204 if (sig->params [i]->byref)
3208 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3210 /* handle constructors only for objects already allocated */
3211 if (!strcmp (method->method->name, ".ctor"))
3212 g_assert (this_arg);
3214 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3215 g_assert (!method->method->klass->valuetype);
3216 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3218 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3219 if (sig->params [i]->byref) {
3221 arg = mono_array_get (params, gpointer, i);
3222 mono_array_setref (out_args, j, arg);
3227 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3234 read_enum_value (const char *mem, int type)
3237 case MONO_TYPE_BOOLEAN:
3239 return *(guint8*)mem;
3241 return *(gint8*)mem;
3242 case MONO_TYPE_CHAR:
3244 return read16 (mem);
3246 return (gint16) read16 (mem);
3248 return read32 (mem);
3250 return (gint32) read32 (mem);
3253 return read64 (mem);
3255 g_assert_not_reached ();
3261 write_enum_value (char *mem, int type, guint64 value)
3265 case MONO_TYPE_I1: {
3266 guint8 *p = (guint8*)mem;
3271 case MONO_TYPE_I2: {
3272 guint16 *p = (guint16 *)mem;
3277 case MONO_TYPE_I4: {
3278 guint32 *p = (guint32 *)mem;
3283 case MONO_TYPE_I8: {
3284 guint64 *p = (guint64 *)mem;
3289 g_assert_not_reached ();
3294 ICALL_EXPORT MonoObject *
3295 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3303 domain = mono_object_domain (enumType);
3304 enumc = mono_class_from_mono_type (enumType->type);
3306 mono_class_init_or_throw (enumc);
3308 etype = mono_class_enum_basetype (enumc);
3310 res = mono_object_new_checked (domain, enumc, &error);
3311 mono_error_raise_exception (&error);
3312 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3317 ICALL_EXPORT MonoBoolean
3318 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3320 int size = mono_class_value_size (a->vtable->klass, NULL);
3321 guint64 a_val = 0, b_val = 0;
3323 memcpy (&a_val, mono_object_unbox (a), size);
3324 memcpy (&b_val, mono_object_unbox (b), size);
3326 return (a_val & b_val) == b_val;
3329 ICALL_EXPORT MonoObject *
3330 ves_icall_System_Enum_get_value (MonoObject *eobj)
3342 g_assert (eobj->vtable->klass->enumtype);
3344 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3345 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3346 mono_error_raise_exception (&error);
3347 dst = (char *)res + sizeof (MonoObject);
3348 src = (char *)eobj + sizeof (MonoObject);
3349 size = mono_class_value_size (enumc, NULL);
3351 memcpy (dst, src, size);
3356 ICALL_EXPORT MonoReflectionType *
3357 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3360 MonoReflectionType *ret;
3364 klass = mono_class_from_mono_type (type->type);
3365 mono_class_init_or_throw (klass);
3367 etype = mono_class_enum_basetype (klass);
3369 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3373 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3374 mono_error_raise_exception (&error);
3380 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3382 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3383 gpointer odata = (char *)other + sizeof (MonoObject);
3384 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3385 g_assert (basetype);
3390 if (eobj->vtable->klass != other->vtable->klass)
3393 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3394 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3395 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3398 return me > other ? 1 : -1; \
3401 switch (basetype->type) {
3403 COMPARE_ENUM_VALUES (guint8);
3405 COMPARE_ENUM_VALUES (gint8);
3406 case MONO_TYPE_CHAR:
3408 COMPARE_ENUM_VALUES (guint16);
3410 COMPARE_ENUM_VALUES (gint16);
3412 COMPARE_ENUM_VALUES (guint32);
3414 COMPARE_ENUM_VALUES (gint32);
3416 COMPARE_ENUM_VALUES (guint64);
3418 COMPARE_ENUM_VALUES (gint64);
3422 #undef COMPARE_ENUM_VALUES
3423 /* indicates that the enum was of an unsupported unerlying type */
3428 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3430 gpointer data = (char *)eobj + sizeof (MonoObject);
3431 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3432 g_assert (basetype);
3434 switch (basetype->type) {
3435 case MONO_TYPE_I1: {
3436 gint8 value = *((gint8*)data);
3437 return ((int)value ^ (int)value << 8);
3440 return *((guint8*)data);
3441 case MONO_TYPE_CHAR:
3443 return *((guint16*)data);
3445 case MONO_TYPE_I2: {
3446 gint16 value = *((gint16*)data);
3447 return ((int)(guint16)value | (((int)value) << 16));
3450 return *((guint32*)data);
3452 return *((gint32*)data);
3454 case MONO_TYPE_I8: {
3455 gint64 value = *((gint64*)data);
3456 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3459 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3464 ICALL_EXPORT MonoBoolean
3465 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3467 MonoDomain *domain = mono_object_domain (type);
3468 MonoClass *enumc = mono_class_from_mono_type (type->type);
3469 guint j = 0, nvalues;
3471 MonoClassField *field;
3473 guint64 field_value, previous_value = 0;
3474 gboolean sorted = TRUE;
3476 mono_class_init_or_throw (enumc);
3478 if (!enumc->enumtype) {
3479 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3483 base_type = mono_class_enum_basetype (enumc)->type;
3485 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3486 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3487 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3490 while ((field = mono_class_get_fields (enumc, &iter))) {
3492 MonoTypeEnum def_type;
3494 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3496 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3498 if (mono_field_is_deleted (field))
3500 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3502 p = mono_class_get_field_default_value (field, &def_type);
3503 /* len = */ mono_metadata_decode_blob_size (p, &p);
3505 field_value = read_enum_value (p, base_type);
3506 mono_array_set (*values, guint64, j, field_value);
3508 if (previous_value > field_value)
3511 previous_value = field_value;
3519 BFLAGS_IgnoreCase = 1,
3520 BFLAGS_DeclaredOnly = 2,
3521 BFLAGS_Instance = 4,
3523 BFLAGS_Public = 0x10,
3524 BFLAGS_NonPublic = 0x20,
3525 BFLAGS_FlattenHierarchy = 0x40,
3526 BFLAGS_InvokeMethod = 0x100,
3527 BFLAGS_CreateInstance = 0x200,
3528 BFLAGS_GetField = 0x400,
3529 BFLAGS_SetField = 0x800,
3530 BFLAGS_GetProperty = 0x1000,
3531 BFLAGS_SetProperty = 0x2000,
3532 BFLAGS_ExactBinding = 0x10000,
3533 BFLAGS_SuppressChangeType = 0x20000,
3534 BFLAGS_OptionalParamBinding = 0x40000
3537 ICALL_EXPORT MonoArray*
3538 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3542 MonoClass *startklass, *klass, *refklass;
3547 char *utf8_name = NULL;
3548 int (*compare_func) (const char *s1, const char *s2) = NULL;
3549 MonoClassField *field;
3550 MonoPtrArray tmp_array;
3552 domain = ((MonoObject *)type)->vtable->domain;
3553 if (type->type->byref)
3554 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3556 klass = startklass = mono_class_from_mono_type (type->type);
3557 refklass = mono_class_from_mono_type (reftype->type);
3559 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3562 if (mono_class_has_failure (klass)) {
3563 mono_ptr_array_destroy (tmp_array);
3564 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3569 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3570 guint32 flags = mono_field_get_flags (field);
3572 if (mono_field_is_deleted_with_flags (field, flags))
3574 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3575 if (bflags & BFLAGS_Public)
3577 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3578 if (bflags & BFLAGS_NonPublic) {
3585 if (flags & FIELD_ATTRIBUTE_STATIC) {
3586 if (bflags & BFLAGS_Static)
3587 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3590 if (bflags & BFLAGS_Instance)
3598 if (utf8_name == NULL) {
3599 utf8_name = mono_string_to_utf8 (name);
3600 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3603 if (compare_func (mono_field_get_name (field), utf8_name))
3607 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3608 if (!mono_error_ok (&error))
3610 mono_ptr_array_append (tmp_array, member);
3612 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3615 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3617 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3618 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3620 mono_ptr_array_destroy (tmp_array);
3622 if (utf8_name != NULL)
3627 mono_ptr_array_destroy (tmp_array);
3628 mono_error_raise_exception (&error);
3629 g_assert_not_reached ();
3633 method_nonpublic (MonoMethod* method, gboolean start_klass)
3635 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3636 case METHOD_ATTRIBUTE_ASSEM:
3637 return (start_klass || mono_defaults.generic_ilist_class);
3638 case METHOD_ATTRIBUTE_PRIVATE:
3640 case METHOD_ATTRIBUTE_PUBLIC:
3648 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3651 MonoClass *startklass;
3655 /*FIXME, use MonoBitSet*/
3656 guint32 method_slots_default [8];
3657 guint32 *method_slots = NULL;
3658 int (*compare_func) (const char *s1, const char *s2) = NULL;
3660 array = g_ptr_array_new ();
3665 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3667 /* An optimization for calls made from Delegate:CreateDelegate () */
3668 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3669 method = mono_get_delegate_invoke (klass);
3670 if (mono_loader_get_last_error ())
3673 g_ptr_array_add (array, method);
3677 mono_class_setup_methods (klass);
3678 mono_class_setup_vtable (klass);
3679 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3682 if (is_generic_parameter (&klass->byval_arg))
3683 nslots = mono_class_get_vtable_size (klass->parent);
3685 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3686 if (nslots >= sizeof (method_slots_default) * 8) {
3687 method_slots = g_new0 (guint32, nslots / 32 + 1);
3689 method_slots = method_slots_default;
3690 memset (method_slots, 0, sizeof (method_slots_default));
3693 mono_class_setup_methods (klass);
3694 mono_class_setup_vtable (klass);
3695 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3699 while ((method = mono_class_get_methods (klass, &iter))) {
3701 if (method->slot != -1) {
3702 g_assert (method->slot < nslots);
3703 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3705 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3706 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3709 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3711 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3712 if (bflags & BFLAGS_Public)
3714 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3720 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3721 if (bflags & BFLAGS_Static)
3722 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3725 if (bflags & BFLAGS_Instance)
3733 if (compare_func (name, method->name))
3738 g_ptr_array_add (array, method);
3740 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3742 if (method_slots != method_slots_default)
3743 g_free (method_slots);
3748 if (method_slots != method_slots_default)
3749 g_free (method_slots);
3750 g_ptr_array_free (array, TRUE);
3752 if (mono_class_has_failure (klass)) {
3753 *ex = mono_class_get_exception_for_failure (klass);
3755 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3756 mono_loader_clear_error ();
3761 ICALL_EXPORT MonoArray*
3762 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3764 static MonoClass *MethodInfo_array;
3768 MonoVTable *array_vtable;
3769 MonoException *ex = NULL;
3770 const char *mname = NULL;
3771 GPtrArray *method_array;
3772 MonoClass *klass, *refklass;
3775 mono_error_init (&error);
3777 if (!MethodInfo_array) {
3778 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3779 mono_memory_barrier ();
3780 MethodInfo_array = klass;
3783 klass = mono_class_from_mono_type (type->type);
3784 refklass = mono_class_from_mono_type (reftype->type);
3785 domain = ((MonoObject *)type)->vtable->domain;
3786 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3787 if (!is_ok (&error)) {
3788 mono_error_set_pending_exception (&error);
3791 if (type->type->byref) {
3792 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3793 mono_error_set_pending_exception (&error);
3799 mname = mono_string_to_utf8 (name);
3801 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3802 g_free ((char*)mname);
3804 mono_set_pending_exception (ex);
3808 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3809 if (!mono_error_ok (&error)) {
3810 mono_error_set_pending_exception (&error);
3814 for (i = 0; i < method_array->len; ++i) {
3815 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3816 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3817 if (!mono_error_ok (&error))
3819 mono_array_setref (res, i, rm);
3823 g_ptr_array_free (method_array, TRUE);
3824 if (!mono_error_ok (&error))
3825 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3829 ICALL_EXPORT MonoArray*
3830 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3833 MonoClass *startklass, *klass, *refklass;
3838 gpointer iter = NULL;
3839 MonoPtrArray tmp_array;
3842 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3844 domain = ((MonoObject *)type)->vtable->domain;
3845 if (type->type->byref)
3846 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3847 klass = startklass = mono_class_from_mono_type (type->type);
3848 refklass = mono_class_from_mono_type (reftype->type);
3850 mono_class_setup_methods (klass);
3851 if (mono_class_has_failure (klass)) {
3852 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3857 while ((method = mono_class_get_methods (klass, &iter))) {
3859 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3861 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3862 if (bflags & BFLAGS_Public)
3865 if (bflags & BFLAGS_NonPublic)
3871 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3872 if (bflags & BFLAGS_Static)
3873 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3876 if (bflags & BFLAGS_Instance)
3882 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3883 if (!mono_error_ok (&error)) {
3884 mono_error_set_pending_exception (&error);
3888 mono_ptr_array_append (tmp_array, member);
3891 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
3893 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3894 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3896 mono_ptr_array_destroy (tmp_array);
3902 property_hash (gconstpointer data)
3904 MonoProperty *prop = (MonoProperty*)data;
3906 return g_str_hash (prop->name);
3910 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3912 if (method1->is_inflated)
3913 method1 = ((MonoMethodInflated*) method1)->declaring;
3914 if (method2->is_inflated)
3915 method2 = ((MonoMethodInflated*) method2)->declaring;
3917 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3921 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3923 // Properties are hide-by-name-and-signature
3924 if (!g_str_equal (prop1->name, prop2->name))
3927 /* If we see a property in a generic method, we want to
3928 compare the generic signatures, not the inflated signatures
3929 because we might conflate two properties that were
3933 public T this[T t] { getter { return t; } } // method 1
3934 public U this[U u] { getter { return u; } } // method 2
3937 If we see int Foo<int,int>::Item[int] we need to know if
3938 the indexer came from method 1 or from method 2, and we
3939 shouldn't conflate them. (Bugzilla 36283)
3941 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
3944 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
3951 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3956 return method_nonpublic (accessor, start_klass);
3959 ICALL_EXPORT MonoArray*
3960 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3964 MonoClass *startklass, *klass;
3970 gchar *propname = NULL;
3971 int (*compare_func) (const char *s1, const char *s2) = NULL;
3973 GHashTable *properties = NULL;
3974 MonoPtrArray tmp_array;
3976 mono_error_init (&error);
3978 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
3980 domain = ((MonoObject *)type)->vtable->domain;
3981 if (type->type->byref)
3982 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
3983 klass = startklass = mono_class_from_mono_type (type->type);
3986 propname = mono_string_to_utf8 (name);
3987 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3990 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3992 mono_class_setup_methods (klass);
3993 mono_class_setup_vtable (klass);
3994 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3998 while ((prop = mono_class_get_properties (klass, &iter))) {
4004 flags = method->flags;
4007 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4008 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4009 if (bflags & BFLAGS_Public)
4011 } else if (bflags & BFLAGS_NonPublic) {
4012 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4013 property_accessor_nonpublic(prop->set, startklass == klass)) {
4020 if (flags & METHOD_ATTRIBUTE_STATIC) {
4021 if (bflags & BFLAGS_Static)
4022 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4025 if (bflags & BFLAGS_Instance)
4034 if (compare_func (propname, prop->name))
4038 if (g_hash_table_lookup (properties, prop))
4041 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4044 mono_ptr_array_append (tmp_array, pr);
4046 g_hash_table_insert (properties, prop, prop);
4048 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4051 g_hash_table_destroy (properties);
4054 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4055 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4056 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4058 mono_ptr_array_destroy (tmp_array);
4065 if (mono_class_has_failure (klass)) {
4066 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4068 mono_error_set_from_loader_error (&error);
4069 mono_loader_clear_error ();
4074 g_hash_table_destroy (properties);
4077 mono_ptr_array_destroy (tmp_array);
4079 mono_error_set_pending_exception (&error);
4085 event_hash (gconstpointer data)
4087 MonoEvent *event = (MonoEvent*)data;
4089 return g_str_hash (event->name);
4093 event_equal (MonoEvent *event1, MonoEvent *event2)
4095 // Events are hide-by-name
4096 return g_str_equal (event1->name, event2->name);
4099 ICALL_EXPORT MonoArray*
4100 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4104 MonoClass *startklass, *klass;
4110 char *utf8_name = NULL;
4111 int (*compare_func) (const char *s1, const char *s2) = NULL;
4112 GHashTable *events = NULL;
4113 MonoPtrArray tmp_array;
4115 mono_error_init (&error);
4117 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4119 domain = mono_object_domain (type);
4120 if (type->type->byref)
4121 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4122 klass = startklass = mono_class_from_mono_type (type->type);
4124 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4126 mono_class_setup_methods (klass);
4127 mono_class_setup_vtable (klass);
4128 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4132 while ((event = mono_class_get_events (klass, &iter))) {
4134 method = event->add;
4136 method = event->remove;
4138 method = event->raise;
4140 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4141 if (bflags & BFLAGS_Public)
4143 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4144 if (bflags & BFLAGS_NonPublic)
4149 if (bflags & BFLAGS_NonPublic)
4155 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4156 if (bflags & BFLAGS_Static)
4157 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4160 if (bflags & BFLAGS_Instance)
4165 if (bflags & BFLAGS_Instance)
4171 if (utf8_name == NULL) {
4172 utf8_name = mono_string_to_utf8 (name);
4173 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4176 if (compare_func (event->name, utf8_name))
4180 if (g_hash_table_lookup (events, event))
4183 MonoReflectionEvent *ev_obj;
4184 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4187 mono_ptr_array_append (tmp_array, ev_obj);
4189 g_hash_table_insert (events, event, event);
4191 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4194 g_hash_table_destroy (events);
4196 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4198 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4199 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4201 mono_ptr_array_destroy (tmp_array);
4203 if (utf8_name != NULL)
4209 if (mono_class_has_failure (klass)) {
4210 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4212 mono_error_set_from_loader_error (&error);
4213 mono_loader_clear_error ();
4219 g_hash_table_destroy (events);
4220 if (utf8_name != NULL)
4223 mono_ptr_array_destroy (tmp_array);
4225 mono_error_set_pending_exception (&error);
4229 ICALL_EXPORT MonoArray*
4230 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4233 MonoReflectionType *rt;
4241 MonoPtrArray tmp_array;
4243 domain = ((MonoObject *)type)->vtable->domain;
4244 if (type->type->byref)
4245 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4246 klass = mono_class_from_mono_type (type->type);
4249 * If a nested type is generic, return its generic type definition.
4250 * Note that this means that the return value is essentially the set
4251 * of nested types of the generic type definition of @klass.
4253 * A note in MSDN claims that a generic type definition can have
4254 * nested types that aren't generic. In any case, the container of that
4255 * nested type would be the generic type definition.
4257 if (klass->generic_class)
4258 klass = klass->generic_class->container_class;
4260 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4262 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4264 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4265 if (bflags & BFLAGS_Public)
4268 if (bflags & BFLAGS_NonPublic)
4276 str = mono_string_to_utf8 (name);
4277 mono_identifier_unescape_type_name_chars (str);
4280 if (strcmp (nested->name, str))
4284 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4285 mono_error_raise_exception (&error);
4287 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4290 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4292 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4293 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4295 mono_ptr_array_destroy (tmp_array);
4303 ICALL_EXPORT MonoReflectionType*
4304 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4307 MonoReflectionType *ret;
4309 MonoType *type = NULL;
4310 MonoTypeNameParse info;
4311 gboolean type_resolve;
4313 /* On MS.NET, this does not fire a TypeResolve event */
4314 type_resolve = TRUE;
4315 str = mono_string_to_utf8 (name);
4316 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4317 if (!mono_reflection_parse_type (str, &info)) {
4319 mono_reflection_free_type_info (&info);
4321 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4324 /*g_print ("failed parse\n");*/
4328 if (info.assembly.name) {
4330 mono_reflection_free_type_info (&info);
4332 /* 1.0 and 2.0 throw different exceptions */
4333 if (mono_defaults.generic_ilist_class)
4334 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4336 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4342 if (module != NULL) {
4344 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4349 if (assembly_is_dynamic (assembly->assembly)) {
4350 /* Enumerate all modules */
4351 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4355 if (abuilder->modules) {
4356 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4357 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4358 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4364 if (!type && abuilder->loaded_modules) {
4365 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4366 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4367 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4374 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4376 mono_reflection_free_type_info (&info);
4378 MonoException *e = NULL;
4381 e = mono_get_exception_type_load (name, NULL);
4383 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4384 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4386 mono_loader_clear_error ();
4389 mono_set_pending_exception (e);
4391 } else if (mono_loader_get_last_error ()) {
4393 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4396 mono_loader_clear_error ();
4399 if (type->type == MONO_TYPE_CLASS) {
4400 MonoClass *klass = mono_type_get_class (type);
4402 /* need to report exceptions ? */
4403 if (throwOnError && mono_class_has_failure (klass)) {
4404 /* report SecurityException (or others) that occured when loading the assembly */
4405 MonoException *exc = mono_class_get_exception_for_failure (klass);
4406 mono_loader_clear_error ();
4407 mono_set_pending_exception (exc);
4412 /* g_print ("got it\n"); */
4413 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4414 mono_error_raise_exception (&error);
4420 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4423 gchar *shadow_ini_file;
4426 /* Check for shadow-copied assembly */
4427 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4428 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4430 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4431 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4437 g_free (shadow_ini_file);
4438 if (content != NULL) {
4441 *filename = content;
4448 ICALL_EXPORT MonoString *
4449 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4451 MonoDomain *domain = mono_object_domain (assembly);
4452 MonoAssembly *mass = assembly->assembly;
4453 MonoString *res = NULL;
4458 if (g_path_is_absolute (mass->image->name)) {
4459 absolute = g_strdup (mass->image->name);
4460 dirname = g_path_get_dirname (absolute);
4462 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4463 dirname = g_strdup (mass->basedir);
4466 replace_shadow_path (domain, dirname, &absolute);
4471 for (i = strlen (absolute) - 1; i >= 0; i--)
4472 if (absolute [i] == '\\')
4477 uri = g_filename_to_uri (absolute, NULL, NULL);
4479 const char *prepend = "file://";
4481 if (*absolute == '/' && *(absolute + 1) == '/') {
4484 prepend = "file:///";
4487 uri = g_strconcat (prepend, absolute, NULL);
4491 res = mono_string_new (domain, uri);
4498 ICALL_EXPORT MonoBoolean
4499 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4501 MonoAssembly *mass = assembly->assembly;
4503 return mass->in_gac;
4506 ICALL_EXPORT MonoReflectionAssembly*
4507 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4512 MonoImageOpenStatus status;
4513 MonoReflectionAssembly* result = NULL;
4515 name = mono_string_to_utf8 (mname);
4516 res = mono_assembly_load_with_partial_name (name, &status);
4522 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4524 mono_error_set_pending_exception (&error);
4528 ICALL_EXPORT MonoString *
4529 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4531 MonoDomain *domain = mono_object_domain (assembly);
4534 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4539 ICALL_EXPORT MonoBoolean
4540 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4542 return assembly->assembly->ref_only;
4545 ICALL_EXPORT MonoString *
4546 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4548 MonoDomain *domain = mono_object_domain (assembly);
4550 return mono_string_new (domain, assembly->assembly->image->version);
4553 ICALL_EXPORT MonoReflectionMethod*
4554 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4557 MonoReflectionMethod *res = NULL;
4560 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4564 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4565 if (!mono_error_ok (&error))
4568 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4571 if (!mono_error_ok (&error))
4572 mono_error_set_pending_exception (&error);
4576 ICALL_EXPORT MonoReflectionModule*
4577 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4580 MonoReflectionModule *result = NULL;
4581 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4582 if (!mono_error_ok (&error))
4583 mono_error_set_pending_exception (&error);
4587 ICALL_EXPORT MonoArray*
4588 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4590 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4591 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4595 for (i = 0; i < table->rows; ++i) {
4596 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4597 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4603 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4605 static MonoMethod *create_version = NULL;
4609 mono_error_init (error);
4612 if (!create_version) {
4613 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4614 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4615 g_assert (create_version);
4616 mono_method_desc_free (desc);
4622 args [3] = &revision;
4623 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4624 return_val_if_nok (error, NULL);
4626 mono_runtime_invoke_checked (create_version, result, args, error);
4627 return_val_if_nok (error, NULL);
4632 ICALL_EXPORT MonoArray*
4633 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4637 MonoDomain *domain = mono_object_domain (assembly);
4639 static MonoMethod *create_culture = NULL;
4640 MonoImage *image = assembly->assembly->image;
4644 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4647 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4649 if (count > 0 && !create_culture) {
4650 MonoMethodDesc *desc = mono_method_desc_new (
4651 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4652 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4653 g_assert (create_culture);
4654 mono_method_desc_free (desc);
4657 for (i = 0; i < count; i++) {
4658 MonoObject *version;
4659 MonoReflectionAssemblyName *aname;
4660 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4662 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4664 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4665 domain, mono_class_get_assembly_name_class (), &error);
4666 mono_error_raise_exception (&error);
4668 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4670 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4671 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4672 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4673 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4674 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4675 aname->versioncompat = 1; /* SameMachine (default) */
4676 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4678 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4679 mono_error_raise_exception (&error);
4681 MONO_OBJECT_SETREF (aname, version, version);
4683 if (create_culture) {
4685 MonoBoolean assembly_ref = 1;
4686 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4687 args [1] = &assembly_ref;
4689 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4690 mono_error_raise_exception (&error);
4692 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4695 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4696 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4697 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4699 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4700 /* public key token isn't copied - the class library will
4701 automatically generate it from the public key if required */
4702 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4703 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4705 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4706 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4709 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4712 /* note: this function doesn't return the codebase on purpose (i.e. it can
4713 be used under partial trust as path information isn't present). */
4715 mono_array_setref (result, i, aname);
4720 /* move this in some file in mono/util/ */
4722 g_concat_dir_and_file (const char *dir, const char *file)
4724 g_return_val_if_fail (dir != NULL, NULL);
4725 g_return_val_if_fail (file != NULL, NULL);
4728 * If the directory name doesn't have a / on the end, we need
4729 * to add one so we get a proper path to the file
4731 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4732 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4734 return g_strconcat (dir, file, NULL);
4738 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4741 char *n = mono_string_to_utf8 (name);
4742 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4744 guint32 cols [MONO_MANIFEST_SIZE];
4745 guint32 impl, file_idx;
4749 for (i = 0; i < table->rows; ++i) {
4750 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4751 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4752 if (strcmp (val, n) == 0)
4756 if (i == table->rows)
4759 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4762 * this code should only be called after obtaining the
4763 * ResourceInfo and handling the other cases.
4765 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4766 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4768 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4773 module = assembly->assembly->image;
4776 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4777 mono_error_raise_exception (&error);
4778 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4780 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4783 ICALL_EXPORT gboolean
4784 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4787 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4789 guint32 cols [MONO_MANIFEST_SIZE];
4790 guint32 file_cols [MONO_FILE_SIZE];
4794 n = mono_string_to_utf8 (name);
4795 for (i = 0; i < table->rows; ++i) {
4796 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4797 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4798 if (strcmp (val, n) == 0)
4802 if (i == table->rows)
4805 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4806 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4809 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4810 case MONO_IMPLEMENTATION_FILE:
4811 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4812 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4813 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4814 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4815 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4816 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4819 info->location = RESOURCE_LOCATION_EMBEDDED;
4822 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4823 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4824 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4825 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4826 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4827 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4829 mono_set_pending_exception (ex);
4832 MonoReflectionAssembly *assm_obj;
4833 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4835 mono_error_set_pending_exception (&error);
4838 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4840 /* Obtain info recursively */
4841 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4842 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4845 case MONO_IMPLEMENTATION_EXP_TYPE:
4846 g_assert_not_reached ();
4854 ICALL_EXPORT MonoObject*
4855 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4857 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4858 MonoArray *result = NULL;
4863 /* check hash if needed */
4865 n = mono_string_to_utf8 (name);
4866 for (i = 0; i < table->rows; ++i) {
4867 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4868 if (strcmp (val, n) == 0) {
4871 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4872 fn = mono_string_new (mono_object_domain (assembly), n);
4874 return (MonoObject*)fn;
4882 for (i = 0; i < table->rows; ++i) {
4883 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4887 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4890 for (i = 0; i < table->rows; ++i) {
4891 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4892 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4893 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4894 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4899 return (MonoObject*)result;
4902 ICALL_EXPORT MonoArray*
4903 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4906 MonoDomain *domain = mono_domain_get();
4909 int i, j, file_count = 0;
4910 MonoImage **modules;
4911 guint32 module_count, real_module_count;
4912 MonoTableInfo *table;
4913 guint32 cols [MONO_FILE_SIZE];
4914 MonoImage *image = assembly->assembly->image;
4916 g_assert (image != NULL);
4917 g_assert (!assembly_is_dynamic (assembly->assembly));
4919 table = &image->tables [MONO_TABLE_FILE];
4920 file_count = table->rows;
4922 modules = image->modules;
4923 module_count = image->module_count;
4925 real_module_count = 0;
4926 for (i = 0; i < module_count; ++i)
4928 real_module_count ++;
4930 klass = mono_class_get_module_class ();
4931 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4933 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
4934 mono_error_raise_exception (&error);
4935 mono_array_setref (res, 0, image_obj);
4937 for (i = 0; i < module_count; ++i)
4939 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
4940 mono_error_raise_exception (&error);
4941 mono_array_setref (res, j, rm);
4945 for (i = 0; i < file_count; ++i, ++j) {
4946 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4947 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
4948 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
4949 mono_error_raise_exception (&error);
4950 mono_array_setref (res, j, rm);
4953 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4955 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4956 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
4959 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
4960 mono_error_raise_exception (&error);
4961 mono_array_setref (res, j, rm);
4968 ICALL_EXPORT MonoReflectionMethod*
4969 ves_icall_GetCurrentMethod (void)
4971 MonoReflectionMethod *res = NULL;
4974 MonoMethod *m = mono_method_get_last_managed ();
4977 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
4981 while (m->is_inflated)
4982 m = ((MonoMethodInflated*)m)->declaring;
4984 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
4985 mono_error_raise_exception (&error);
4991 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4994 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4997 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4998 //method is inflated, we should inflate it on the other class
4999 MonoGenericContext ctx;
5000 ctx.method_inst = inflated->context.method_inst;
5001 ctx.class_inst = inflated->context.class_inst;
5002 if (klass->generic_class)
5003 ctx.class_inst = klass->generic_class->context.class_inst;
5004 else if (klass->generic_container)
5005 ctx.class_inst = klass->generic_container->context.class_inst;
5006 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5007 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5011 mono_class_setup_methods (method->klass);
5012 if (mono_class_has_failure (method->klass))
5014 for (i = 0; i < method->klass->method.count; ++i) {
5015 if (method->klass->methods [i] == method) {
5020 mono_class_setup_methods (klass);
5021 if (mono_class_has_failure (klass))
5023 g_assert (offset >= 0 && offset < klass->method.count);
5024 return klass->methods [offset];
5027 ICALL_EXPORT MonoReflectionMethod*
5028 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5030 MonoReflectionMethod *res = NULL;
5034 klass = mono_class_from_mono_type (type);
5035 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5037 if (method->klass != klass) {
5038 method = mono_method_get_equivalent_method (method, klass);
5043 klass = method->klass;
5044 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5045 mono_error_raise_exception (&error);
5049 ICALL_EXPORT MonoReflectionMethodBody*
5050 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5052 return mono_method_body_get_object (mono_domain_get (), method);
5055 ICALL_EXPORT MonoReflectionAssembly*
5056 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5059 MonoReflectionAssembly *result;
5060 MonoMethod *dest = NULL;
5062 mono_stack_walk_no_il (get_executing, &dest);
5064 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5066 mono_error_set_pending_exception (&error);
5071 ICALL_EXPORT MonoReflectionAssembly*
5072 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5075 MonoReflectionAssembly *result;
5076 MonoDomain* domain = mono_domain_get ();
5078 if (!domain->entry_assembly)
5081 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5083 mono_error_set_pending_exception (&error);
5087 ICALL_EXPORT MonoReflectionAssembly*
5088 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5093 MonoReflectionAssembly *result;
5096 mono_stack_walk_no_il (get_executing, &dest);
5098 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5102 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5105 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5107 mono_error_set_pending_exception (&error);
5111 ICALL_EXPORT MonoString *
5112 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5113 gboolean assembly_qualified)
5115 MonoDomain *domain = mono_object_domain (object);
5116 MonoTypeNameFormat format;
5121 format = assembly_qualified ?
5122 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5123 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5125 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5127 name = mono_type_get_name_full (object->type, format);
5131 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5136 res = mono_string_new (domain, name);
5143 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5145 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5146 mono_class_init_or_throw (klass);
5147 return mono_security_core_clr_class_level (klass);
5151 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5153 MonoClassField *field = rfield->field;
5154 return mono_security_core_clr_field_level (field, TRUE);
5158 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5160 MonoMethod *method = rfield->method;
5161 return mono_security_core_clr_method_level (method, TRUE);
5165 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)
5167 static MonoMethod *create_culture = NULL;
5171 const char *pkey_ptr;
5173 MonoBoolean assembly_ref = 0;
5175 mono_error_init (error);
5177 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5178 aname->major = name->major;
5179 aname->minor = name->minor;
5180 aname->build = name->build;
5181 aname->flags = name->flags;
5182 aname->revision = name->revision;
5183 aname->hashalg = name->hash_alg;
5184 aname->versioncompat = 1; /* SameMachine (default) */
5185 aname->processor_architecture = name->arch;
5187 if (by_default_version) {
5188 MonoObject *version;
5190 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5191 return_if_nok (error);
5193 MONO_OBJECT_SETREF (aname, version, version);
5197 if (absolute != NULL && *absolute != '\0') {
5198 const gchar *prepend = "file://";
5201 codebase = g_strdup (absolute);
5206 for (i = strlen (codebase) - 1; i >= 0; i--)
5207 if (codebase [i] == '\\')
5210 if (*codebase == '/' && *(codebase + 1) == '/') {
5213 prepend = "file:///";
5217 result = g_strconcat (prepend, codebase, NULL);
5223 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5227 if (!create_culture) {
5228 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5229 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5230 g_assert (create_culture);
5231 mono_method_desc_free (desc);
5234 if (name->culture) {
5235 args [0] = mono_string_new (domain, name->culture);
5236 args [1] = &assembly_ref;
5238 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5239 return_if_nok (error);
5241 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5244 if (name->public_key) {
5245 pkey_ptr = (char*)name->public_key;
5246 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5248 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5249 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5250 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5251 } else if (default_publickey) {
5252 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5253 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5256 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5257 if (name->public_key_token [0]) {
5261 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5262 p = mono_array_addr (aname->keyToken, char, 0);
5264 for (i = 0, j = 0; i < 8; i++) {
5265 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5266 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5269 } else if (default_token) {
5270 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5274 ICALL_EXPORT MonoString *
5275 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5277 MonoDomain *domain = mono_object_domain (assembly);
5278 MonoAssembly *mass = assembly->assembly;
5282 name = mono_stringify_assembly_name (&mass->aname);
5283 res = mono_string_new (domain, name);
5290 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5294 MonoAssembly *mass = assembly->assembly;
5296 if (g_path_is_absolute (mass->image->name)) {
5297 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5298 mono_error_set_pending_exception (&error);
5301 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5303 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5304 mono_error_set_pending_exception (&error);
5310 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5314 MonoImageOpenStatus status = MONO_IMAGE_OK;
5317 MonoAssemblyName name;
5320 filename = mono_string_to_utf8 (fname);
5322 dirname = g_path_get_dirname (filename);
5323 replace_shadow_path (mono_domain_get (), dirname, &filename);
5326 image = mono_image_open (filename, &status);
5332 if (status == MONO_IMAGE_IMAGE_INVALID)
5333 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5335 exc = mono_get_exception_file_not_found2 (NULL, fname);
5336 mono_set_pending_exception (exc);
5340 res = mono_assembly_fill_assembly_name (image, &name);
5342 mono_image_close (image);
5344 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5348 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5349 mono_error_set_pending_exception (&error);
5351 mono_image_close (image);
5355 ICALL_EXPORT MonoBoolean
5356 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5357 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5359 MonoBoolean result = FALSE;
5360 MonoDeclSecurityEntry entry;
5362 /* SecurityAction.RequestMinimum */
5363 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5364 *minimum = entry.blob;
5365 *minLength = entry.size;
5368 /* SecurityAction.RequestOptional */
5369 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5370 *optional = entry.blob;
5371 *optLength = entry.size;
5374 /* SecurityAction.RequestRefuse */
5375 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5376 *refused = entry.blob;
5377 *refLength = entry.size;
5385 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5387 guint32 attrs, visibility;
5389 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5390 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5391 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5394 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5400 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5402 MonoReflectionType *rt;
5405 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5408 mono_error_init (error);
5410 /* we start the count from 1 because we skip the special type <Module> */
5413 for (i = 1; i < tdef->rows; ++i) {
5414 if (mono_module_type_is_visible (tdef, image, i + 1))
5418 count = tdef->rows - 1;
5420 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5421 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5423 for (i = 1; i < tdef->rows; ++i) {
5424 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5425 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5426 mono_loader_assert_no_error (); /* Plug any leaks */
5427 mono_error_assert_ok (error);
5430 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5431 return_val_if_nok (error, NULL);
5433 mono_array_setref (res, count, rt);
5435 MonoException *ex = mono_error_convert_to_exception (error);
5436 mono_array_setref (*exceptions, count, ex);
5445 ICALL_EXPORT MonoArray*
5446 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5449 MonoArray *res = NULL;
5450 MonoArray *exceptions = NULL;
5451 MonoImage *image = NULL;
5452 MonoTableInfo *table = NULL;
5455 int i, len, ex_count;
5457 domain = mono_object_domain (assembly);
5459 g_assert (!assembly_is_dynamic (assembly->assembly));
5460 image = assembly->assembly->image;
5461 table = &image->tables [MONO_TABLE_FILE];
5462 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5463 mono_error_raise_exception (&error);
5465 /* Append data from all modules in the assembly */
5466 for (i = 0; i < table->rows; ++i) {
5467 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5468 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5473 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5474 mono_error_raise_exception (&error);
5476 /* Append the new types to the end of the array */
5477 if (mono_array_length (res2) > 0) {
5479 MonoArray *res3, *ex3;
5481 len1 = mono_array_length (res);
5482 len2 = mono_array_length (res2);
5484 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5485 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5486 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5489 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5490 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5491 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5498 /* the ReflectionTypeLoadException must have all the types (Types property),
5499 * NULL replacing types which throws an exception. The LoaderException must
5500 * contain all exceptions for NULL items.
5503 len = mono_array_length (res);
5506 for (i = 0; i < len; i++) {
5507 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5511 klass = mono_type_get_class (t->type);
5512 if ((klass != NULL) && mono_class_has_failure (klass)) {
5513 /* keep the class in the list */
5514 list = g_list_append (list, klass);
5515 /* and replace Type with NULL */
5516 mono_array_setref (res, i, NULL);
5523 if (list || ex_count) {
5525 MonoException *exc = NULL;
5526 MonoArray *exl = NULL;
5527 int j, length = g_list_length (list) + ex_count;
5529 mono_loader_clear_error ();
5531 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5532 /* Types for which mono_class_get_checked () succeeded */
5533 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5534 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5535 mono_array_setref (exl, i, exc);
5537 /* Types for which it don't */
5538 for (j = 0; j < mono_array_length (exceptions); ++j) {
5539 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5541 g_assert (i < length);
5542 mono_array_setref (exl, i, exc);
5549 exc = mono_get_exception_reflection_type_load (res, exl);
5550 mono_loader_clear_error ();
5551 mono_set_pending_exception (exc);
5558 ICALL_EXPORT gboolean
5559 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5562 MonoAssemblyName aname;
5563 MonoDomain *domain = mono_object_domain (name);
5565 gboolean is_version_defined;
5566 gboolean is_token_defined;
5568 aname.public_key = NULL;
5569 val = mono_string_to_utf8 (assname);
5570 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5571 g_free ((guint8*) aname.public_key);
5576 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5577 mono_error_set_pending_exception (&error);
5579 mono_assembly_name_free (&aname);
5580 g_free ((guint8*) aname.public_key);
5586 ICALL_EXPORT MonoReflectionType*
5587 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5590 MonoReflectionType *ret;
5591 MonoDomain *domain = mono_object_domain (module);
5594 g_assert (module->image);
5596 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5597 /* These images do not have a global type */
5600 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5601 if (!mono_error_ok (&error)) {
5602 mono_error_set_pending_exception (&error);
5606 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5607 if (!mono_error_ok (&error)) {
5608 mono_error_set_pending_exception (&error);
5616 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5618 /*if (module->image)
5619 mono_image_close (module->image);*/
5622 ICALL_EXPORT MonoString*
5623 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5625 MonoDomain *domain = mono_object_domain (module);
5627 g_assert (module->image);
5628 return mono_string_new (domain, module->image->guid);
5631 ICALL_EXPORT gpointer
5632 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5635 if (module->image && module->image->is_module_handle)
5636 return module->image->raw_data;
5639 return (gpointer) (-1);
5643 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5645 if (image_is_dynamic (image)) {
5646 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5647 *pe_kind = dyn->pe_kind;
5648 *machine = dyn->machine;
5651 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5652 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5657 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5659 return (image->md_version_major << 16) | (image->md_version_minor);
5662 ICALL_EXPORT MonoArray*
5663 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5666 MonoArray *exceptions;
5670 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5674 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5675 mono_error_raise_exception (&error);
5677 for (i = 0; i < mono_array_length (exceptions); ++i) {
5678 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5680 mono_set_pending_exception (ex);
5689 mono_memberref_is_method (MonoImage *image, guint32 token)
5691 if (!image_is_dynamic (image)) {
5692 guint32 cols [MONO_MEMBERREF_SIZE];
5694 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5695 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5696 mono_metadata_decode_blob_size (sig, &sig);
5697 return (*sig != 0x6);
5699 MonoClass *handle_class;
5701 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5704 return mono_defaults.methodhandle_class == handle_class;
5709 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5712 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5713 mono_array_addr (type_args, MonoType*, 0));
5715 context->class_inst = NULL;
5717 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5718 mono_array_addr (method_args, MonoType*, 0));
5720 context->method_inst = NULL;
5723 ICALL_EXPORT MonoType*
5724 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5727 int table = mono_metadata_token_table (token);
5728 int index = mono_metadata_token_index (token);
5729 MonoGenericContext context;
5732 *resolve_error = ResolveTokenError_Other;
5734 /* Validate token */
5735 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5736 (table != MONO_TABLE_TYPESPEC)) {
5737 *resolve_error = ResolveTokenError_BadTable;
5741 if (image_is_dynamic (image)) {
5742 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5743 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5744 return klass ? &klass->byval_arg : NULL;
5747 init_generic_context_from_args (&context, type_args, method_args);
5748 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5749 return klass ? &klass->byval_arg : NULL;
5752 if ((index <= 0) || (index > image->tables [table].rows)) {
5753 *resolve_error = ResolveTokenError_OutOfRange;
5757 init_generic_context_from_args (&context, type_args, method_args);
5758 klass = mono_class_get_checked (image, token, &error);
5760 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5761 if (!mono_error_ok (&error)) {
5762 mono_error_set_pending_exception (&error);
5767 return &klass->byval_arg;
5772 ICALL_EXPORT MonoMethod*
5773 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5776 int table = mono_metadata_token_table (token);
5777 int index = mono_metadata_token_index (token);
5778 MonoGenericContext context;
5781 *resolve_error = ResolveTokenError_Other;
5783 /* Validate token */
5784 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5785 (table != MONO_TABLE_MEMBERREF)) {
5786 *resolve_error = ResolveTokenError_BadTable;
5790 if (image_is_dynamic (image)) {
5791 if (table == MONO_TABLE_METHOD)
5792 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5794 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5795 *resolve_error = ResolveTokenError_BadTable;
5799 init_generic_context_from_args (&context, type_args, method_args);
5800 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5803 if ((index <= 0) || (index > image->tables [table].rows)) {
5804 *resolve_error = ResolveTokenError_OutOfRange;
5807 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5808 *resolve_error = ResolveTokenError_BadTable;
5812 init_generic_context_from_args (&context, type_args, method_args);
5813 method = mono_get_method_checked (image, token, NULL, &context, &error);
5814 mono_error_set_pending_exception (&error);
5819 ICALL_EXPORT MonoString*
5820 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5822 int index = mono_metadata_token_index (token);
5824 *error = ResolveTokenError_Other;
5826 /* Validate token */
5827 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5828 *error = ResolveTokenError_BadTable;
5832 if (image_is_dynamic (image))
5833 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5835 if ((index <= 0) || (index >= image->heap_us.size)) {
5836 *error = ResolveTokenError_OutOfRange;
5840 /* FIXME: What to do if the index points into the middle of a string ? */
5842 return mono_ldstr (mono_domain_get (), image, index);
5845 ICALL_EXPORT MonoClassField*
5846 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5850 int table = mono_metadata_token_table (token);
5851 int index = mono_metadata_token_index (token);
5852 MonoGenericContext context;
5853 MonoClassField *field;
5855 *resolve_error = ResolveTokenError_Other;
5857 /* Validate token */
5858 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5859 *resolve_error = ResolveTokenError_BadTable;
5863 if (image_is_dynamic (image)) {
5864 if (table == MONO_TABLE_FIELD)
5865 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5867 if (mono_memberref_is_method (image, token)) {
5868 *resolve_error = ResolveTokenError_BadTable;
5872 init_generic_context_from_args (&context, type_args, method_args);
5873 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5876 if ((index <= 0) || (index > image->tables [table].rows)) {
5877 *resolve_error = ResolveTokenError_OutOfRange;
5880 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5881 *resolve_error = ResolveTokenError_BadTable;
5885 init_generic_context_from_args (&context, type_args, method_args);
5886 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5887 mono_error_set_pending_exception (&error);
5893 ICALL_EXPORT MonoObject*
5894 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5898 int table = mono_metadata_token_table (token);
5900 *error = ResolveTokenError_Other;
5903 case MONO_TABLE_TYPEDEF:
5904 case MONO_TABLE_TYPEREF:
5905 case MONO_TABLE_TYPESPEC: {
5906 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5908 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
5909 mono_error_raise_exception (&merror);
5916 case MONO_TABLE_METHOD:
5917 case MONO_TABLE_METHODSPEC: {
5918 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5920 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5921 mono_error_raise_exception (&merror);
5927 case MONO_TABLE_FIELD: {
5928 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5930 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5931 mono_error_raise_exception (&merror);
5937 case MONO_TABLE_MEMBERREF:
5938 if (mono_memberref_is_method (image, token)) {
5939 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5941 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5942 mono_error_raise_exception (&merror);
5949 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5951 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5952 mono_error_raise_exception (&merror);
5961 *error = ResolveTokenError_BadTable;
5967 ICALL_EXPORT MonoArray*
5968 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5970 int table = mono_metadata_token_table (token);
5971 int idx = mono_metadata_token_index (token);
5972 MonoTableInfo *tables = image->tables;
5977 *error = ResolveTokenError_OutOfRange;
5979 /* FIXME: Support other tables ? */
5980 if (table != MONO_TABLE_STANDALONESIG)
5983 if (image_is_dynamic (image))
5986 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5989 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5991 ptr = mono_metadata_blob_heap (image, sig);
5992 len = mono_metadata_decode_blob_size (ptr, &ptr);
5994 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5995 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5999 ICALL_EXPORT MonoReflectionType*
6000 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6003 MonoReflectionType *ret;
6005 int isbyref = 0, rank;
6006 char *str = mono_string_to_utf8 (smodifiers);
6009 klass = mono_class_from_mono_type (tb->type.type);
6011 /* logic taken from mono_reflection_parse_type(): keep in sync */
6015 if (isbyref) { /* only one level allowed by the spec */
6024 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6025 mono_error_raise_exception (&error);
6029 klass = mono_ptr_class_get (&klass->byval_arg);
6030 mono_class_init (klass);
6041 else if (*p != '*') { /* '*' means unknown lower bound */
6052 klass = mono_array_class_get (klass, rank);
6053 mono_class_init (klass);
6062 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6063 mono_error_raise_exception (&error);
6068 ICALL_EXPORT MonoBoolean
6069 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6075 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6081 check_for_invalid_type (MonoClass *klass)
6085 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6088 name = mono_type_get_full_name (klass);
6089 str = mono_string_new (mono_domain_get (), name);
6091 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
6094 ICALL_EXPORT MonoReflectionType *
6095 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6098 MonoReflectionType *ret;
6099 MonoClass *klass, *aklass;
6101 klass = mono_class_from_mono_type (type->type);
6102 check_for_invalid_type (klass);
6104 if (rank == 0) //single dimentional array
6105 aklass = mono_array_class_get (klass, 1);
6107 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6109 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6110 mono_error_raise_exception (&error);
6115 ICALL_EXPORT MonoReflectionType *
6116 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6119 MonoReflectionType *ret;
6122 klass = mono_class_from_mono_type (type->type);
6123 mono_class_init_or_throw (klass);
6124 check_for_invalid_type (klass);
6126 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6127 mono_error_raise_exception (&error);
6132 ICALL_EXPORT MonoReflectionType *
6133 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6136 MonoReflectionType *ret;
6137 MonoClass *klass, *pklass;
6139 klass = mono_class_from_mono_type (type->type);
6140 mono_class_init_or_throw (klass);
6141 check_for_invalid_type (klass);
6143 pklass = mono_ptr_class_get (type->type);
6145 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6146 mono_error_raise_exception (&error);
6151 ICALL_EXPORT MonoObject *
6152 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6153 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6156 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6157 MonoObject *delegate;
6159 MonoMethod *method = info->method;
6161 mono_class_init_or_throw (delegate_class);
6163 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
6165 if (mono_security_core_clr_enabled ()) {
6166 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6170 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6171 mono_error_raise_exception (&error);
6173 if (method_is_dynamic (method)) {
6174 /* Creating a trampoline would leak memory */
6175 func = mono_compile_method (method);
6177 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6178 method = mono_object_get_virtual_method (target, method);
6179 func = mono_create_ftnptr (mono_domain_get (),
6180 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6183 mono_delegate_ctor_with_method (delegate, target, func, method);
6188 ICALL_EXPORT MonoMulticastDelegate *
6189 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6192 MonoMulticastDelegate *ret;
6194 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6196 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6197 mono_error_raise_exception (&error);
6198 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6203 ICALL_EXPORT MonoReflectionMethod*
6204 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6206 MonoReflectionMethod *ret = NULL;
6208 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6209 mono_error_raise_exception (&error);
6215 static inline gint32
6216 mono_array_get_byte_length (MonoArray *array)
6222 klass = array->obj.vtable->klass;
6224 if (array->bounds == NULL)
6225 length = array->max_length;
6228 for (i = 0; i < klass->rank; ++ i)
6229 length *= array->bounds [i].length;
6232 switch (klass->element_class->byval_arg.type) {
6235 case MONO_TYPE_BOOLEAN:
6239 case MONO_TYPE_CHAR:
6247 return length * sizeof (gpointer);
6258 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6260 return mono_array_get_byte_length (array);
6264 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6266 return mono_array_get (array, gint8, idx);
6270 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6272 mono_array_set (array, gint8, idx, value);
6275 ICALL_EXPORT MonoBoolean
6276 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6278 guint8 *src_buf, *dest_buf;
6281 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6285 g_assert (count >= 0);
6287 /* This is called directly from the class libraries without going through the managed wrapper */
6288 MONO_CHECK_ARG_NULL (src, FALSE);
6289 MONO_CHECK_ARG_NULL (dest, FALSE);
6291 /* watch out for integer overflow */
6292 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6295 src_buf = (guint8 *)src->vector + src_offset;
6296 dest_buf = (guint8 *)dest->vector + dest_offset;
6299 memcpy (dest_buf, src_buf, count);
6301 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6306 #ifndef DISABLE_REMOTING
6307 ICALL_EXPORT MonoObject *
6308 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6311 MonoDomain *domain = mono_object_domain (this_obj);
6313 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6314 MonoTransparentProxy *tp;
6318 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6319 mono_error_raise_exception (&error);
6320 tp = (MonoTransparentProxy*) res;
6322 MONO_OBJECT_SETREF (tp, rp, rp);
6323 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6324 klass = mono_class_from_mono_type (type);
6326 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6327 mono_class_setup_vtable (klass);
6328 if (mono_class_has_failure (klass)) {
6329 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6333 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
6334 tp->remote_class = mono_remote_class (domain, class_name, klass);
6336 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6340 ICALL_EXPORT MonoReflectionType *
6341 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6344 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6345 mono_error_raise_exception (&error);
6351 /* System.Environment */
6354 ves_icall_System_Environment_get_UserName (void)
6356 /* using glib is more portable */
6357 return mono_string_new (mono_domain_get (), g_get_user_name ());
6361 ICALL_EXPORT MonoString *
6362 ves_icall_System_Environment_get_MachineName (void)
6364 #if defined (HOST_WIN32)
6369 len = MAX_COMPUTERNAME_LENGTH + 1;
6370 buf = g_new (gunichar2, len);
6373 if (GetComputerName (buf, (PDWORD) &len)) {
6375 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6376 mono_error_raise_exception (&error);
6381 #elif !defined(DISABLE_SOCKETS)
6385 #if defined _SC_HOST_NAME_MAX
6386 n = sysconf (_SC_HOST_NAME_MAX);
6390 buf = g_malloc (n+1);
6392 if (gethostname (buf, n) == 0){
6394 result = mono_string_new (mono_domain_get (), buf);
6401 return mono_string_new (mono_domain_get (), "mono");
6406 ves_icall_System_Environment_get_Platform (void)
6408 #if defined (TARGET_WIN32)
6411 #elif defined(__MACH__)
6414 // Notice that the value is hidden from user code, and only exposed
6415 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6416 // define and making assumptions based on Unix/128/4 values before there
6417 // was a MacOS define. Lots of code would assume that not-Unix meant
6418 // Windows, but in this case, it would be OSX.
6427 ICALL_EXPORT MonoString *
6428 ves_icall_System_Environment_get_NewLine (void)
6430 #if defined (HOST_WIN32)
6431 return mono_string_new (mono_domain_get (), "\r\n");
6433 return mono_string_new (mono_domain_get (), "\n");
6437 ICALL_EXPORT MonoBoolean
6438 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6440 #if SIZEOF_VOID_P == 8
6444 gboolean isWow64Process = FALSE;
6445 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6446 return (MonoBoolean)isWow64Process;
6448 #elif defined(HAVE_SYS_UTSNAME_H)
6449 struct utsname name;
6451 if (uname (&name) >= 0) {
6452 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6459 ICALL_EXPORT MonoString *
6460 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6468 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6469 value = g_getenv (utf8_name);
6476 return mono_string_new (mono_domain_get (), value);
6480 * There is no standard way to get at environ.
6483 #ifndef __MINGW32_VERSION
6484 #if defined(__APPLE__)
6485 #if defined (TARGET_OSX)
6486 /* Apple defines this in crt_externs.h but doesn't provide that header for
6487 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6488 * in fact exist on all implementations (so far)
6490 gchar ***_NSGetEnviron(void);
6491 #define environ (*_NSGetEnviron())
6493 static char *mono_environ[1] = { NULL };
6494 #define environ mono_environ
6495 #endif /* defined (TARGET_OSX) */
6503 ICALL_EXPORT MonoArray *
6504 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6515 env_strings = GetEnvironmentStrings();
6518 env_string = env_strings;
6519 while (*env_string != '\0') {
6520 /* weird case that MS seems to skip */
6521 if (*env_string != '=')
6523 while (*env_string != '\0')
6529 domain = mono_domain_get ();
6530 names = mono_array_new (domain, mono_defaults.string_class, n);
6534 env_string = env_strings;
6535 while (*env_string != '\0') {
6536 /* weird case that MS seems to skip */
6537 if (*env_string != '=') {
6538 equal_str = wcschr(env_string, '=');
6539 g_assert(equal_str);
6541 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6542 mono_error_raise_exception (&error);
6543 mono_array_setref (names, n, str);
6546 while (*env_string != '\0')
6551 FreeEnvironmentStrings (env_strings);
6564 for (e = environ; *e != 0; ++ e)
6567 domain = mono_domain_get ();
6568 names = mono_array_new (domain, mono_defaults.string_class, n);
6571 for (e = environ; *e != 0; ++ e) {
6572 parts = g_strsplit (*e, "=", 2);
6574 str = mono_string_new (domain, *parts);
6575 mono_array_setref (names, n, str);
6588 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6590 #if !GLIB_CHECK_VERSION(2,4,0)
6591 #define g_setenv(a,b,c) setenv(a,b,c)
6592 #define g_unsetenv(a) unsetenv(a)
6596 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6599 gunichar2 *utf16_name, *utf16_value;
6601 gchar *utf8_name, *utf8_value;
6606 utf16_name = mono_string_to_utf16 (name);
6607 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6608 SetEnvironmentVariable (utf16_name, NULL);
6609 g_free (utf16_name);
6613 utf16_value = mono_string_to_utf16 (value);
6615 SetEnvironmentVariable (utf16_name, utf16_value);
6617 g_free (utf16_name);
6618 g_free (utf16_value);
6620 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6622 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6623 g_unsetenv (utf8_name);
6628 utf8_value = mono_string_to_utf8_checked (value, &error);
6629 if (!mono_error_ok (&error)) {
6631 mono_error_set_pending_exception (&error);
6634 g_setenv (utf8_name, utf8_value, TRUE);
6637 g_free (utf8_value);
6642 ves_icall_System_Environment_Exit (int result)
6644 mono_environment_exitcode_set (result);
6646 /* FIXME: There are some cleanup hangs that should be worked out, but
6647 * if the program is going to exit, everything will be cleaned up when
6648 * NaCl exits anyway.
6650 #ifndef __native_client__
6651 if (!mono_runtime_try_shutdown ())
6652 mono_thread_exit ();
6654 /* Suspend all managed threads since the runtime is going away */
6655 mono_thread_suspend_all_other_threads ();
6657 mono_runtime_quit ();
6660 /* we may need to do some cleanup here... */
6664 ICALL_EXPORT MonoString*
6665 ves_icall_System_Environment_GetGacPath (void)
6667 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6670 ICALL_EXPORT MonoString*
6671 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6673 #if defined (HOST_WIN32)
6674 #ifndef CSIDL_FLAG_CREATE
6675 #define CSIDL_FLAG_CREATE 0x8000
6678 WCHAR path [MAX_PATH];
6679 /* Create directory if no existing */
6680 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6685 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6686 mono_error_raise_exception (&error);
6690 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6692 return mono_string_new (mono_domain_get (), "");
6695 ICALL_EXPORT MonoArray *
6696 ves_icall_System_Environment_GetLogicalDrives (void)
6699 gunichar2 buf [256], *ptr, *dname;
6701 guint initial_size = 127, size = 128;
6704 MonoString *drivestr;
6705 MonoDomain *domain = mono_domain_get ();
6711 while (size > initial_size) {
6712 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6713 if (size > initial_size) {
6716 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6717 initial_size = size;
6731 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6736 while (*u16) { u16++; len ++; }
6737 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6738 mono_error_raise_exception (&error);
6739 mono_array_setref (result, ndrives++, drivestr);
6749 ICALL_EXPORT MonoString *
6750 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6752 gunichar2 volume_name [MAX_PATH + 1];
6754 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6756 return mono_string_from_utf16 (volume_name);
6759 ICALL_EXPORT MonoString *
6760 ves_icall_System_Environment_InternalGetHome (void)
6762 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6765 static const char *encodings [] = {
6767 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6768 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6769 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6771 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6772 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6773 "x_unicode_2_0_utf_7",
6775 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6776 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6778 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6781 "unicodefffe", "utf_16be",
6788 * Returns the internal codepage, if the value of "int_code_page" is
6789 * 1 at entry, and we can not compute a suitable code page number,
6790 * returns the code page as a string
6792 ICALL_EXPORT MonoString*
6793 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6798 char *codepage = NULL;
6800 int want_name = *int_code_page;
6803 *int_code_page = -1;
6805 g_get_charset (&cset);
6806 c = codepage = strdup (cset);
6807 for (c = codepage; *c; c++){
6808 if (isascii (*c) && isalpha (*c))
6813 /* g_print ("charset: %s\n", cset); */
6815 /* handle some common aliases */
6818 for (i = 0; p != 0; ){
6821 p = encodings [++i];
6824 if (strcmp (p, codepage) == 0){
6825 *int_code_page = code;
6828 p = encodings [++i];
6831 if (strstr (codepage, "utf_8") != NULL)
6832 *int_code_page |= 0x10000000;
6835 if (want_name && *int_code_page == -1)
6836 return mono_string_new (mono_domain_get (), cset);
6841 ICALL_EXPORT MonoBoolean
6842 ves_icall_System_Environment_get_HasShutdownStarted (void)
6844 if (mono_runtime_is_shutting_down ())
6847 if (mono_domain_is_unloading (mono_domain_get ()))
6854 ves_icall_System_Environment_BroadcastSettingChange (void)
6857 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6862 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6868 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6869 MonoReflectionMethod *method,
6870 MonoArray *out_args)
6872 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6875 #ifndef DISABLE_REMOTING
6876 ICALL_EXPORT MonoBoolean
6877 ves_icall_IsTransparentProxy (MonoObject *proxy)
6882 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6888 ICALL_EXPORT MonoReflectionMethod *
6889 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6890 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6892 MonoReflectionMethod *ret = NULL;
6897 MonoMethod **vtable;
6898 MonoMethod *res = NULL;
6900 MONO_CHECK_ARG_NULL (rtype, NULL);
6901 MONO_CHECK_ARG_NULL (rmethod, NULL);
6903 method = rmethod->method;
6904 klass = mono_class_from_mono_type (rtype->type);
6905 mono_class_init_or_throw (klass);
6907 if (MONO_CLASS_IS_INTERFACE (klass))
6910 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6913 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6914 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6920 mono_class_setup_vtable (klass);
6921 vtable = klass->vtable;
6923 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6924 gboolean variance_used = FALSE;
6925 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6926 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6928 res = vtable [offs + method->slot];
6930 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6933 if (method->slot != -1)
6934 res = vtable [method->slot];
6940 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
6941 mono_error_raise_exception (&error);
6946 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6952 klass = mono_class_from_mono_type (type->type);
6953 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
6954 if (!is_ok (&error)) {
6955 mono_error_set_pending_exception (&error);
6959 mono_vtable_set_is_remote (vtable, enable);
6962 #else /* DISABLE_REMOTING */
6965 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6967 g_assert_not_reached ();
6972 ICALL_EXPORT MonoObject *
6973 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6980 domain = mono_object_domain (type);
6981 klass = mono_class_from_mono_type (type->type);
6982 mono_class_init_or_throw (klass);
6984 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
6985 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6989 if (klass->rank >= 1) {
6990 g_assert (klass->rank == 1);
6991 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6993 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
6994 if (!is_ok (&error)) {
6995 mono_error_set_pending_exception (&error);
6998 /* Bypass remoting object creation check */
6999 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7000 mono_error_set_pending_exception (&error);
7006 ICALL_EXPORT MonoString *
7007 ves_icall_System_IO_get_temp_path (void)
7009 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7012 #ifndef PLATFORM_NO_DRIVEINFO
7013 ICALL_EXPORT MonoBoolean
7014 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7015 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7019 ULARGE_INTEGER wapi_free_bytes_avail;
7020 ULARGE_INTEGER wapi_total_number_of_bytes;
7021 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7023 *error = ERROR_SUCCESS;
7024 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7025 &wapi_total_number_of_free_bytes);
7028 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7029 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7030 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7032 *free_bytes_avail = 0;
7033 *total_number_of_bytes = 0;
7034 *total_number_of_free_bytes = 0;
7035 *error = GetLastError ();
7041 ICALL_EXPORT guint32
7042 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7044 return GetDriveType (mono_string_chars (root_path_name));
7048 ICALL_EXPORT gpointer
7049 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7051 return mono_compile_method (method);
7054 ICALL_EXPORT MonoString *
7055 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7060 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7062 #if defined (HOST_WIN32)
7063 /* Avoid mixing '/' and '\\' */
7066 for (i = strlen (path) - 1; i >= 0; i--)
7067 if (path [i] == '/')
7071 mcpath = mono_string_new (mono_domain_get (), path);
7078 get_bundled_app_config (void)
7080 const gchar *app_config;
7083 gchar *config_file_name, *config_file_path;
7084 gsize len, config_file_path_length, config_ext_length;
7087 domain = mono_domain_get ();
7088 file = domain->setup->configuration_file;
7089 if (!file || file->length == 0)
7092 // Retrieve config file and remove the extension
7093 config_file_name = mono_string_to_utf8 (file);
7094 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7095 if (!config_file_path)
7096 config_file_path = config_file_name;
7098 config_file_path_length = strlen (config_file_path);
7099 config_ext_length = strlen (".config");
7100 if (config_file_path_length <= config_ext_length)
7103 len = config_file_path_length - config_ext_length;
7104 module = (gchar *)g_malloc0 (len + 1);
7105 memcpy (module, config_file_path, len);
7106 // Get the config file from the module name
7107 app_config = mono_config_string_for_assembly_file (module);
7110 if (config_file_name != config_file_path)
7111 g_free (config_file_name);
7112 g_free (config_file_path);
7117 return mono_string_new (mono_domain_get (), app_config);
7121 get_bundled_machine_config (void)
7123 const gchar *machine_config;
7125 machine_config = mono_get_machine_config ();
7127 if (!machine_config)
7130 return mono_string_new (mono_domain_get (), machine_config);
7133 ICALL_EXPORT MonoString *
7134 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7139 path = g_path_get_dirname (mono_get_config_dir ());
7141 #if defined (HOST_WIN32)
7142 /* Avoid mixing '/' and '\\' */
7145 for (i = strlen (path) - 1; i >= 0; i--)
7146 if (path [i] == '/')
7150 ipath = mono_string_new (mono_domain_get (), path);
7156 ICALL_EXPORT gboolean
7157 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7159 MonoPEResourceDataEntry *entry;
7162 if (!assembly || !result || !size)
7167 image = assembly->assembly->image;
7168 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7172 *result = mono_image_rva_map (image, entry->rde_data_offset);
7177 *size = entry->rde_size;
7182 ICALL_EXPORT MonoBoolean
7183 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7185 return mono_is_debugger_attached ();
7188 ICALL_EXPORT MonoBoolean
7189 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7191 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7192 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7198 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7200 if (mono_get_runtime_callbacks ()->debug_log)
7201 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7205 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7207 #if defined (HOST_WIN32)
7208 OutputDebugString (mono_string_chars (message));
7210 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7214 /* Only used for value types */
7215 ICALL_EXPORT MonoObject *
7216 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7223 domain = mono_object_domain (type);
7224 klass = mono_class_from_mono_type (type->type);
7225 mono_class_init_or_throw (klass);
7227 if (mono_class_is_nullable (klass))
7228 /* No arguments -> null */
7231 result = mono_object_new_checked (domain, klass, &error);
7232 mono_error_raise_exception (&error);
7236 ICALL_EXPORT MonoReflectionMethod *
7237 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7239 MonoReflectionMethod *ret = NULL;
7242 MonoClass *klass, *parent;
7243 MonoGenericContext *generic_inst = NULL;
7244 MonoMethod *method = m->method;
7245 MonoMethod *result = NULL;
7248 if (method->klass == NULL)
7251 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7252 MONO_CLASS_IS_INTERFACE (method->klass) ||
7253 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7256 slot = mono_method_get_vtable_slot (method);
7260 klass = method->klass;
7261 if (klass->generic_class) {
7262 generic_inst = mono_class_get_context (klass);
7263 klass = klass->generic_class->container_class;
7267 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7268 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7269 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7270 or klass is the generic container class and generic_inst is the instantiation.
7272 when we go to the parent, if the parent is an open constructed type, we need to
7273 replace the type parameters by the definitions from the generic_inst, and then take it
7274 apart again into the klass and the generic_inst.
7276 For cases like this:
7277 class C<T> : B<T, int> {
7278 public override void Foo () { ... }
7280 class B<U,V> : A<HashMap<U,V>> {
7281 public override void Foo () { ... }
7284 public virtual void Foo () { ... }
7287 if at each iteration the parent isn't open, we can skip inflating it. if at some
7288 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7291 MonoGenericContext *parent_inst = NULL;
7292 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7294 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7295 if (!mono_error_ok (&error)) {
7296 mono_error_set_pending_exception (&error);
7300 if (parent->generic_class) {
7301 parent_inst = mono_class_get_context (parent);
7302 parent = parent->generic_class->container_class;
7305 mono_class_setup_vtable (parent);
7306 if (parent->vtable_size <= slot)
7309 generic_inst = parent_inst;
7312 klass = klass->parent;
7315 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7316 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7317 if (!mono_error_ok (&error)) {
7318 mono_error_set_pending_exception (&error);
7322 generic_inst = NULL;
7324 if (klass->generic_class) {
7325 generic_inst = mono_class_get_context (klass);
7326 klass = klass->generic_class->container_class;
7332 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7333 if (!mono_error_ok (&error)) {
7334 mono_error_set_pending_exception (&error);
7339 if (klass == method->klass)
7342 /*This is possible if definition == FALSE.
7343 * Do it here to be really sure we don't read invalid memory.
7345 if (slot >= klass->vtable_size)
7348 mono_class_setup_vtable (klass);
7350 result = klass->vtable [slot];
7351 if (result == NULL) {
7352 /* It is an abstract method */
7353 gpointer iter = NULL;
7354 while ((result = mono_class_get_methods (klass, &iter)))
7355 if (result->slot == slot)
7362 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7363 mono_error_raise_exception (&error);
7367 ICALL_EXPORT MonoString*
7368 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7370 MonoMethod *method = m->method;
7372 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7377 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7379 iter->sig = *(MonoMethodSignature**)argsp;
7381 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7382 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7385 /* FIXME: it's not documented what start is exactly... */
7389 iter->args = argsp + sizeof (gpointer);
7391 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7393 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7396 ICALL_EXPORT MonoTypedRef
7397 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7399 guint32 i, arg_size;
7403 i = iter->sig->sentinelpos + iter->next_arg;
7405 g_assert (i < iter->sig->param_count);
7407 res.type = iter->sig->params [i];
7408 res.klass = mono_class_from_mono_type (res.type);
7409 arg_size = mono_type_stack_size (res.type, &align);
7410 #if defined(__arm__) || defined(__mips__)
7411 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7413 res.value = iter->args;
7414 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7415 /* Values are stored as 8 byte register sized objects, but 'value'
7416 * is dereferenced as a pointer in other routines.
7418 res.value = (char*)res.value + 4;
7420 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7421 if (arg_size <= sizeof (gpointer)) {
7423 int padding = arg_size - mono_type_size (res.type, &dummy);
7424 res.value = (guint8*)res.value + padding;
7427 iter->args = (char*)iter->args + arg_size;
7430 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7435 ICALL_EXPORT MonoTypedRef
7436 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7438 guint32 i, arg_size;
7442 i = iter->sig->sentinelpos + iter->next_arg;
7444 g_assert (i < iter->sig->param_count);
7446 while (i < iter->sig->param_count) {
7447 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7449 res.type = iter->sig->params [i];
7450 res.klass = mono_class_from_mono_type (res.type);
7451 /* FIXME: endianess issue... */
7452 arg_size = mono_type_stack_size (res.type, &align);
7453 #if defined(__arm__) || defined(__mips__)
7454 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7456 res.value = iter->args;
7457 iter->args = (char*)iter->args + arg_size;
7459 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7462 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7470 ICALL_EXPORT MonoType*
7471 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7475 i = iter->sig->sentinelpos + iter->next_arg;
7477 g_assert (i < iter->sig->param_count);
7479 return iter->sig->params [i];
7482 ICALL_EXPORT MonoObject*
7483 mono_TypedReference_ToObject (MonoTypedRef* tref)
7485 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7486 MonoObject** objp = (MonoObject **)tref->value;
7490 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
7493 ICALL_EXPORT MonoTypedRef
7494 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7497 MonoReflectionField *f;
7499 MonoType *ftype = NULL;
7503 memset (&res, 0, sizeof (res));
7506 g_assert (mono_array_length (fields) > 0);
7508 klass = target->vtable->klass;
7510 for (i = 0; i < mono_array_length (fields); ++i) {
7511 f = mono_array_get (fields, MonoReflectionField*, i);
7513 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7516 if (f->field->parent != klass) {
7517 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7521 p = (guint8*)target + f->field->offset;
7523 p += f->field->offset - sizeof (MonoObject);
7524 klass = mono_class_from_mono_type (f->field->type);
7525 ftype = f->field->type;
7529 res.klass = mono_class_from_mono_type (ftype);
7536 prelink_method (MonoMethod *method)
7538 const char *exc_class, *exc_arg;
7539 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7541 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7543 mono_raise_exception(
7544 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7546 /* create the wrapper, too? */
7550 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7552 prelink_method (method->method);
7556 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7558 MonoClass *klass = mono_class_from_mono_type (type->type);
7560 gpointer iter = NULL;
7562 mono_class_init_or_throw (klass);
7564 while ((m = mono_class_get_methods (klass, &iter)))
7568 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7570 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7571 gint32 const **exponents,
7572 gunichar2 const **digitLowerTable,
7573 gunichar2 const **digitUpperTable,
7574 gint64 const **tenPowersList,
7575 gint32 const **decHexDigits)
7577 *mantissas = Formatter_MantissaBitsTable;
7578 *exponents = Formatter_TensExponentTable;
7579 *digitLowerTable = Formatter_DigitLowerTable;
7580 *digitUpperTable = Formatter_DigitUpperTable;
7581 *tenPowersList = Formatter_TenPowersList;
7582 *decHexDigits = Formatter_DecHexDigits;
7586 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7587 * and avoid useless allocations.
7592 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7595 MonoReflectionType *rt;
7598 for (i = 0; i < type->num_mods; ++i) {
7599 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7604 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7606 for (i = 0; i < type->num_mods; ++i) {
7607 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7608 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
7609 mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */
7611 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, &error);
7612 mono_error_raise_exception (&error);
7614 mono_array_setref (res, count, rt);
7621 ICALL_EXPORT MonoArray*
7622 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7624 MonoType *type = param->ClassImpl->type;
7625 MonoClass *member_class = mono_object_class (param->MemberImpl);
7626 MonoMethod *method = NULL;
7629 MonoMethodSignature *sig;
7631 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7632 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7633 method = rmethod->method;
7634 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7635 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7636 if (!(method = prop->property->get))
7637 method = prop->property->set;
7640 char *type_name = mono_type_get_full_name (member_class);
7641 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7642 MonoException *ex = mono_get_exception_not_supported (msg);
7645 mono_set_pending_exception (ex);
7649 image = method->klass->image;
7650 pos = param->PositionImpl;
7651 sig = mono_method_signature (method);
7655 type = sig->params [pos];
7657 return type_array_from_modifiers (image, type, optional);
7661 get_property_type (MonoProperty *prop)
7663 MonoMethodSignature *sig;
7665 sig = mono_method_signature (prop->get);
7667 } else if (prop->set) {
7668 sig = mono_method_signature (prop->set);
7669 return sig->params [sig->param_count - 1];
7674 ICALL_EXPORT MonoArray*
7675 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7677 MonoType *type = get_property_type (property->property);
7678 MonoImage *image = property->klass->image;
7682 return type_array_from_modifiers (image, type, optional);
7686 *Construct a MonoType suited to be used to decode a constant blob object.
7688 * @type is the target type which will be constructed
7689 * @blob_type is the blob type, for example, that comes from the constant table
7690 * @real_type is the expected constructed type.
7693 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7695 type->type = blob_type;
7696 type->data.klass = NULL;
7697 if (blob_type == MONO_TYPE_CLASS)
7698 type->data.klass = mono_defaults.object_class;
7699 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7700 /* For enums, we need to use the base type */
7701 type->type = MONO_TYPE_VALUETYPE;
7702 type->data.klass = mono_class_from_mono_type (real_type);
7704 type->data.klass = mono_class_from_mono_type (real_type);
7707 ICALL_EXPORT MonoObject*
7708 property_info_get_default_value (MonoReflectionProperty *property)
7711 MonoProperty *prop = property->property;
7712 MonoType *type = get_property_type (prop);
7713 MonoDomain *domain = mono_object_domain (property);
7714 MonoTypeEnum def_type;
7715 const char *def_value;
7718 mono_class_init (prop->parent);
7720 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7721 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7725 def_value = mono_class_get_property_default_value (prop, &def_type);
7727 mono_type_from_blob_type (&blob_type, def_type, type);
7728 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7733 ICALL_EXPORT MonoBoolean
7734 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7737 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7738 MonoCustomAttrInfo *cinfo;
7741 mono_class_init_or_throw (attr_class);
7743 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7744 if (!is_ok (&error)) {
7745 mono_error_set_pending_exception (&error);
7750 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7752 mono_custom_attrs_free (cinfo);
7756 ICALL_EXPORT MonoArray*
7757 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7759 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7764 mono_class_init_or_throw (attr_class);
7766 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7767 if (!mono_error_ok (&error)) {
7768 mono_error_set_pending_exception (&error);
7772 if (mono_loader_get_last_error ()) {
7773 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7780 ICALL_EXPORT MonoArray*
7781 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7785 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7786 mono_error_set_pending_exception (&error);
7791 ICALL_EXPORT MonoString*
7792 ves_icall_Mono_Runtime_GetDisplayName (void)
7795 MonoString *display_name;
7797 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7798 display_name = mono_string_new (mono_domain_get (), info);
7800 return display_name;
7803 ICALL_EXPORT MonoString*
7804 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7807 MonoString *message;
7811 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7812 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7815 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7817 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7818 mono_error_raise_exception (&error);
7825 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7828 char *path_str = mono_string_to_utf8 (path);
7830 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7838 ICALL_EXPORT gpointer
7839 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
7841 return GetCurrentProcess ();
7844 ICALL_EXPORT MonoBoolean
7845 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
7847 return GetExitCodeProcess (handle, (guint32*) exitcode);
7850 ICALL_EXPORT MonoBoolean
7851 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
7853 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
7854 return CloseHandle (handle);
7856 return CloseProcess (handle);
7860 ICALL_EXPORT MonoBoolean
7861 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
7863 return TerminateProcess (handle, exitcode);
7867 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
7869 return WaitForInputIdle (handle, milliseconds);
7872 ICALL_EXPORT MonoBoolean
7873 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
7875 return GetProcessWorkingSetSize (handle, min, max);
7878 ICALL_EXPORT MonoBoolean
7879 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
7881 return SetProcessWorkingSetSize (handle, min, max);
7884 ICALL_EXPORT MonoBoolean
7885 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
7887 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
7891 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
7893 return mono_process_current_pid ();
7897 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
7899 return GetPriorityClass (handle);
7902 ICALL_EXPORT MonoBoolean
7903 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
7905 return SetPriorityClass (handle, priorityClass);
7908 #ifndef DISABLE_ICALL_TABLES
7910 #define ICALL_TYPE(id,name,first)
7911 #define ICALL(id,name,func) Icall_ ## id,
7914 #include "metadata/icall-def.h"
7920 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7921 #define ICALL(id,name,func)
7923 #include "metadata/icall-def.h"
7929 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7930 #define ICALL(id,name,func)
7932 guint16 first_icall;
7935 static const IcallTypeDesc
7936 icall_type_descs [] = {
7937 #include "metadata/icall-def.h"
7941 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7944 #define ICALL_TYPE(id,name,first)
7947 #ifdef HAVE_ARRAY_ELEM_INIT
7948 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7949 #define MSGSTRFIELD1(line) str##line
7951 static const struct msgstrtn_t {
7952 #define ICALL(id,name,func)
7954 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7955 #include "metadata/icall-def.h"
7957 } icall_type_names_str = {
7958 #define ICALL_TYPE(id,name,first) (name),
7959 #include "metadata/icall-def.h"
7962 static const guint16 icall_type_names_idx [] = {
7963 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7964 #include "metadata/icall-def.h"
7967 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7969 static const struct msgstr_t {
7971 #define ICALL_TYPE(id,name,first)
7972 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7973 #include "metadata/icall-def.h"
7975 } icall_names_str = {
7976 #define ICALL(id,name,func) (name),
7977 #include "metadata/icall-def.h"
7980 static const guint16 icall_names_idx [] = {
7981 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7982 #include "metadata/icall-def.h"
7985 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7991 #define ICALL_TYPE(id,name,first) name,
7992 #define ICALL(id,name,func)
7993 static const char* const
7994 icall_type_names [] = {
7995 #include "metadata/icall-def.h"
7999 #define icall_type_name_get(id) (icall_type_names [(id)])
8003 #define ICALL_TYPE(id,name,first)
8004 #define ICALL(id,name,func) name,
8005 static const char* const
8007 #include "metadata/icall-def.h"
8010 #define icall_name_get(id) icall_names [(id)]
8012 #endif /* !HAVE_ARRAY_ELEM_INIT */
8016 #define ICALL_TYPE(id,name,first)
8017 #define ICALL(id,name,func) func,
8018 static const gconstpointer
8019 icall_functions [] = {
8020 #include "metadata/icall-def.h"
8024 #ifdef ENABLE_ICALL_SYMBOL_MAP
8027 #define ICALL_TYPE(id,name,first)
8028 #define ICALL(id,name,func) #func,
8029 static const gconstpointer
8030 icall_symbols [] = {
8031 #include "metadata/icall-def.h"
8036 #endif /* DISABLE_ICALL_TABLES */
8038 static mono_mutex_t icall_mutex;
8039 static GHashTable *icall_hash = NULL;
8040 static GHashTable *jit_icall_hash_name = NULL;
8041 static GHashTable *jit_icall_hash_addr = NULL;
8044 mono_icall_init (void)
8046 #ifndef DISABLE_ICALL_TABLES
8049 /* check that tables are sorted: disable in release */
8052 const char *prev_class = NULL;
8053 const char *prev_method;
8055 for (i = 0; i < Icall_type_num; ++i) {
8056 const IcallTypeDesc *desc;
8059 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8060 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8061 prev_class = icall_type_name_get (i);
8062 desc = &icall_type_descs [i];
8063 num_icalls = icall_desc_num_icalls (desc);
8064 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8065 for (j = 0; j < num_icalls; ++j) {
8066 const char *methodn = icall_name_get (desc->first_icall + j);
8067 if (prev_method && strcmp (prev_method, methodn) >= 0)
8068 g_print ("method %s should come before method %s\n", methodn, prev_method);
8069 prev_method = methodn;
8075 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8076 mono_os_mutex_init (&icall_mutex);
8080 mono_icall_lock (void)
8082 mono_locks_os_acquire (&icall_mutex, IcallLock);
8086 mono_icall_unlock (void)
8088 mono_locks_os_release (&icall_mutex, IcallLock);
8092 mono_icall_cleanup (void)
8094 g_hash_table_destroy (icall_hash);
8095 g_hash_table_destroy (jit_icall_hash_name);
8096 g_hash_table_destroy (jit_icall_hash_addr);
8097 mono_os_mutex_destroy (&icall_mutex);
8101 * mono_add_internal_call:
8102 * @name: method specification to surface to the managed world
8103 * @method: pointer to a C method to invoke when the method is called
8105 * This method surfaces the C function pointed by @method as a method
8106 * that has been surfaced in managed code with the method specified in
8107 * @name as an internal call.
8109 * Internal calls are surfaced to all app domains loaded and they are
8110 * accessibly by a type with the specified name.
8112 * You must provide a fully qualified type name, that is namespaces
8113 * and type name, followed by a colon and the method name, with an
8114 * optional signature to bind.
8116 * For example, the following are all valid declarations:
8118 * "MyApp.Services.ScriptService:Accelerate"
8119 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8121 * You use method parameters in cases where there might be more than
8122 * one surface method to managed code. That way you can register different
8123 * internal calls for different method overloads.
8125 * The internal calls are invoked with no marshalling. This means that .NET
8126 * types like System.String are exposed as `MonoString *` parameters. This is
8127 * different than the way that strings are surfaced in P/Invoke.
8129 * For more information on how the parameters are marshalled, see the
8130 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8133 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8134 * reference for more information on the format of method descriptions.
8137 mono_add_internal_call (const char *name, gconstpointer method)
8141 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8143 mono_icall_unlock ();
8146 #ifndef DISABLE_ICALL_TABLES
8148 #ifdef HAVE_ARRAY_ELEM_INIT
8150 compare_method_imap (const void *key, const void *elem)
8152 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8153 return strcmp (key, method_name);
8157 find_method_icall (const IcallTypeDesc *imap, const char *name)
8159 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);
8162 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8166 compare_class_imap (const void *key, const void *elem)
8168 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8169 return strcmp (key, class_name);
8172 static const IcallTypeDesc*
8173 find_class_icalls (const char *name)
8175 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);
8178 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8181 #else /* HAVE_ARRAY_ELEM_INIT */
8184 compare_method_imap (const void *key, const void *elem)
8186 const char** method_name = (const char**)elem;
8187 return strcmp (key, *method_name);
8191 find_method_icall (const IcallTypeDesc *imap, const char *name)
8193 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8196 return (gpointer)icall_functions [(nameslot - icall_names)];
8200 compare_class_imap (const void *key, const void *elem)
8202 const char** class_name = (const char**)elem;
8203 return strcmp (key, *class_name);
8206 static const IcallTypeDesc*
8207 find_class_icalls (const char *name)
8209 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8212 return &icall_type_descs [nameslot - icall_type_names];
8215 #endif /* HAVE_ARRAY_ELEM_INIT */
8217 #endif /* DISABLE_ICALL_TABLES */
8220 * we should probably export this as an helper (handle nested types).
8221 * Returns the number of chars written in buf.
8224 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8226 int nspacelen, cnamelen;
8227 nspacelen = strlen (klass->name_space);
8228 cnamelen = strlen (klass->name);
8229 if (nspacelen + cnamelen + 2 > bufsize)
8232 memcpy (buf, klass->name_space, nspacelen);
8233 buf [nspacelen ++] = '.';
8235 memcpy (buf + nspacelen, klass->name, cnamelen);
8236 buf [nspacelen + cnamelen] = 0;
8237 return nspacelen + cnamelen;
8240 #ifdef DISABLE_ICALL_TABLES
8242 no_icall_table (void)
8244 g_assert_not_reached ();
8249 mono_lookup_internal_call (MonoMethod *method)
8254 int typelen = 0, mlen, siglen;
8256 #ifndef DISABLE_ICALL_TABLES
8257 const IcallTypeDesc *imap = NULL;
8260 g_assert (method != NULL);
8262 if (method->is_inflated)
8263 method = ((MonoMethodInflated *) method)->declaring;
8265 if (method->klass->nested_in) {
8266 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8270 mname [pos++] = '/';
8273 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8279 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8284 #ifndef DISABLE_ICALL_TABLES
8285 imap = find_class_icalls (mname);
8288 mname [typelen] = ':';
8289 mname [typelen + 1] = ':';
8291 mlen = strlen (method->name);
8292 memcpy (mname + typelen + 2, method->name, mlen);
8293 sigstart = mname + typelen + 2 + mlen;
8296 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8297 siglen = strlen (tmpsig);
8298 if (typelen + mlen + siglen + 6 > sizeof (mname))
8301 memcpy (sigstart + 1, tmpsig, siglen);
8302 sigstart [siglen + 1] = ')';
8303 sigstart [siglen + 2] = 0;
8308 res = g_hash_table_lookup (icall_hash, mname);
8310 mono_icall_unlock ();;
8313 /* try without signature */
8315 res = g_hash_table_lookup (icall_hash, mname);
8317 mono_icall_unlock ();
8321 #ifdef DISABLE_ICALL_TABLES
8322 mono_icall_unlock ();
8323 /* Fail only when the result is actually used */
8324 /* mono_marshal_get_native_wrapper () depends on this */
8325 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8326 return ves_icall_System_String_ctor_RedirectToCreateString;
8328 return no_icall_table;
8330 /* it wasn't found in the static call tables */
8332 mono_icall_unlock ();
8335 res = find_method_icall (imap, sigstart - mlen);
8337 mono_icall_unlock ();
8340 /* try _with_ signature */
8342 res = find_method_icall (imap, sigstart - mlen);
8344 mono_icall_unlock ();
8348 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8349 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8350 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8351 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8352 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");
8353 g_print ("If you see other errors or faults after this message they are probably related\n");
8354 g_print ("and you need to fix your mono install first.\n");
8356 mono_icall_unlock ();
8362 #ifdef ENABLE_ICALL_SYMBOL_MAP
8364 func_cmp (gconstpointer key, gconstpointer p)
8366 return (gsize)key - (gsize)*(gsize*)p;
8371 * mono_lookup_icall_symbol:
8373 * Given the icall METHOD, returns its C symbol.
8376 mono_lookup_icall_symbol (MonoMethod *m)
8378 #ifdef DISABLE_ICALL_TABLES
8379 g_assert_not_reached ();
8382 #ifdef ENABLE_ICALL_SYMBOL_MAP
8386 static gconstpointer *functions_sorted;
8387 static const char**symbols_sorted;
8388 static gboolean inited;
8393 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8394 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8395 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8396 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8397 /* Bubble sort the two arrays */
8401 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8402 if (functions_sorted [i] > functions_sorted [i + 1]) {
8405 tmp = functions_sorted [i];
8406 functions_sorted [i] = functions_sorted [i + 1];
8407 functions_sorted [i + 1] = tmp;
8408 tmp = symbols_sorted [i];
8409 symbols_sorted [i] = symbols_sorted [i + 1];
8410 symbols_sorted [i + 1] = tmp;
8417 func = mono_lookup_internal_call (m);
8420 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8424 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8426 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8427 g_assert_not_reached ();
8434 type_from_typename (char *type_name)
8436 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8438 if (!strcmp (type_name, "int"))
8439 klass = mono_defaults.int_class;
8440 else if (!strcmp (type_name, "ptr"))
8441 klass = mono_defaults.int_class;
8442 else if (!strcmp (type_name, "void"))
8443 klass = mono_defaults.void_class;
8444 else if (!strcmp (type_name, "int32"))
8445 klass = mono_defaults.int32_class;
8446 else if (!strcmp (type_name, "uint32"))
8447 klass = mono_defaults.uint32_class;
8448 else if (!strcmp (type_name, "int8"))
8449 klass = mono_defaults.sbyte_class;
8450 else if (!strcmp (type_name, "uint8"))
8451 klass = mono_defaults.byte_class;
8452 else if (!strcmp (type_name, "int16"))
8453 klass = mono_defaults.int16_class;
8454 else if (!strcmp (type_name, "uint16"))
8455 klass = mono_defaults.uint16_class;
8456 else if (!strcmp (type_name, "long"))
8457 klass = mono_defaults.int64_class;
8458 else if (!strcmp (type_name, "ulong"))
8459 klass = mono_defaults.uint64_class;
8460 else if (!strcmp (type_name, "float"))
8461 klass = mono_defaults.single_class;
8462 else if (!strcmp (type_name, "double"))
8463 klass = mono_defaults.double_class;
8464 else if (!strcmp (type_name, "object"))
8465 klass = mono_defaults.object_class;
8466 else if (!strcmp (type_name, "obj"))
8467 klass = mono_defaults.object_class;
8468 else if (!strcmp (type_name, "string"))
8469 klass = mono_defaults.string_class;
8470 else if (!strcmp (type_name, "bool"))
8471 klass = mono_defaults.boolean_class;
8472 else if (!strcmp (type_name, "boolean"))
8473 klass = mono_defaults.boolean_class;
8475 g_error ("%s", type_name);
8476 g_assert_not_reached ();
8478 return &klass->byval_arg;
8482 * LOCKING: Take the corlib image lock.
8484 MonoMethodSignature*
8485 mono_create_icall_signature (const char *sigstr)
8490 MonoMethodSignature *res, *res2;
8491 MonoImage *corlib = mono_defaults.corlib;
8493 mono_image_lock (corlib);
8494 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8495 mono_image_unlock (corlib);
8500 parts = g_strsplit (sigstr, " ", 256);
8509 res = mono_metadata_signature_alloc (corlib, len - 1);
8514 * Under windows, the default pinvoke calling convention is STDCALL but
8517 res->call_convention = MONO_CALL_C;
8520 res->ret = type_from_typename (parts [0]);
8521 for (i = 1; i < len; ++i) {
8522 res->params [i - 1] = type_from_typename (parts [i]);
8527 mono_image_lock (corlib);
8528 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8530 res = res2; /*Value is allocated in the image pool*/
8532 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8533 mono_image_unlock (corlib);
8539 mono_find_jit_icall_by_name (const char *name)
8541 MonoJitICallInfo *info;
8542 g_assert (jit_icall_hash_name);
8545 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8546 mono_icall_unlock ();
8551 mono_find_jit_icall_by_addr (gconstpointer addr)
8553 MonoJitICallInfo *info;
8554 g_assert (jit_icall_hash_addr);
8557 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8558 mono_icall_unlock ();
8564 * mono_get_jit_icall_info:
8566 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8567 * caller should access it while holding the icall lock.
8570 mono_get_jit_icall_info (void)
8572 return jit_icall_hash_name;
8576 * mono_lookup_jit_icall_symbol:
8578 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8581 mono_lookup_jit_icall_symbol (const char *name)
8583 MonoJitICallInfo *info;
8584 const char *res = NULL;
8587 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8589 res = info->c_symbol;
8590 mono_icall_unlock ();
8595 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8598 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8599 mono_icall_unlock ();
8603 * 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
8604 * icalls without wrappers in some cases.
8607 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8609 MonoJitICallInfo *info;
8616 if (!jit_icall_hash_name) {
8617 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8618 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8621 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8622 g_warning ("jit icall already defined \"%s\"\n", name);
8623 g_assert_not_reached ();
8626 info = g_new0 (MonoJitICallInfo, 1);
8631 info->c_symbol = c_symbol;
8632 info->no_raise = no_raise;
8635 info->wrapper = func;
8637 info->wrapper = NULL;
8640 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8641 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8643 mono_icall_unlock ();
8648 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8650 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);