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/exception-internals.h>
49 #include <mono/metadata/file-io.h>
50 #include <mono/metadata/console-io.h>
51 #include <mono/metadata/mono-route.h>
52 #include <mono/metadata/socket-io.h>
53 #include <mono/metadata/mono-endian.h>
54 #include <mono/metadata/tokentype.h>
55 #include <mono/metadata/domain-internals.h>
56 #include <mono/metadata/metadata-internals.h>
57 #include <mono/metadata/class-internals.h>
58 #include <mono/metadata/reflection-internals.h>
59 #include <mono/metadata/marshal.h>
60 #include <mono/metadata/gc-internals.h>
61 #include <mono/metadata/mono-gc.h>
62 #include <mono/metadata/rand.h>
63 #include <mono/metadata/sysmath.h>
64 #include <mono/metadata/string-icalls.h>
65 #include <mono/metadata/debug-helpers.h>
66 #include <mono/metadata/process.h>
67 #include <mono/metadata/environment.h>
68 #include <mono/metadata/profiler-private.h>
69 #include <mono/metadata/locales.h>
70 #include <mono/metadata/filewatcher.h>
71 #include <mono/metadata/security.h>
72 #include <mono/metadata/mono-config.h>
73 #include <mono/metadata/cil-coff.h>
74 #include <mono/metadata/number-formatter.h>
75 #include <mono/metadata/security-manager.h>
76 #include <mono/metadata/security-core-clr.h>
77 #include <mono/metadata/mono-perfcounters.h>
78 #include <mono/metadata/mono-debug.h>
79 #include <mono/metadata/mono-ptr-array.h>
80 #include <mono/metadata/verify-internals.h>
81 #include <mono/metadata/runtime.h>
82 #include <mono/metadata/file-mmap.h>
83 #include <mono/metadata/seq-points-data.h>
84 #include <mono/io-layer/io-layer.h>
85 #include <mono/utils/monobitset.h>
86 #include <mono/utils/mono-time.h>
87 #include <mono/utils/mono-proclib.h>
88 #include <mono/utils/mono-string.h>
89 #include <mono/utils/mono-error-internals.h>
90 #include <mono/utils/mono-mmap.h>
91 #include <mono/utils/mono-io-portability.h>
92 #include <mono/utils/mono-digest.h>
93 #include <mono/utils/bsearch.h>
94 #include <mono/utils/mono-os-mutex.h>
95 #include <mono/utils/mono-threads.h>
97 #if defined (HOST_WIN32)
101 #include "decimal-ms.h"
102 #include "number-ms.h"
104 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
105 #include <sys/utsname.h>
108 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
110 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
112 /* Lazy class loading functions */
113 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
114 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
115 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
116 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
121 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
123 static inline MonoBoolean
124 is_generic_parameter (MonoType *type)
126 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
130 mono_class_init_checked (MonoClass *klass, MonoError *error)
132 mono_error_init (error);
134 if (!mono_class_init (klass))
135 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
138 ICALL_EXPORT MonoObject *
139 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
145 MonoObject *result = NULL;
147 ac = (MonoClass *)arr->obj.vtable->klass;
149 esize = mono_array_element_size (ac);
150 ea = (gpointer*)((char*)arr->vector + (pos * esize));
152 if (ac->element_class->valuetype) {
153 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
154 mono_error_set_pending_exception (&error);
156 result = (MonoObject *)*ea;
160 ICALL_EXPORT MonoObject *
161 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
167 MONO_CHECK_ARG_NULL (idxs, NULL);
170 ic = (MonoClass *)io->obj.vtable->klass;
172 ac = (MonoClass *)arr->obj.vtable->klass;
174 g_assert (ic->rank == 1);
175 if (io->bounds != NULL || io->max_length != ac->rank) {
176 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
180 ind = (gint32 *)io->vector;
182 if (arr->bounds == NULL) {
183 if (*ind < 0 || *ind >= arr->max_length) {
184 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
188 return ves_icall_System_Array_GetValueImpl (arr, *ind);
191 for (i = 0; i < ac->rank; i++) {
192 if ((ind [i] < arr->bounds [i].lower_bound) ||
193 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
194 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
199 pos = ind [0] - arr->bounds [0].lower_bound;
200 for (i = 1; i < ac->rank; i++)
201 pos = pos * arr->bounds [i].length + ind [i] -
202 arr->bounds [i].lower_bound;
204 return ves_icall_System_Array_GetValueImpl (arr, pos);
208 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
211 MonoClass *ac, *vc, *ec;
220 mono_error_init (&error);
223 vc = value->vtable->klass;
227 ac = arr->obj.vtable->klass;
228 ec = ac->element_class;
230 esize = mono_array_element_size (ac);
231 ea = (gpointer*)((char*)arr->vector + (pos * esize));
232 va = (gpointer*)((char*)value + sizeof (MonoObject));
234 if (mono_class_is_nullable (ec)) {
235 mono_nullable_init ((guint8*)ea, value, ec);
240 mono_gc_bzero_atomic (ea, esize);
244 #define NO_WIDENING_CONVERSION G_STMT_START{\
245 mono_set_pending_exception (mono_get_exception_argument ( \
246 "value", "not a widening conversion")); \
250 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
251 if (esize < vsize + (extra)) { \
252 mono_set_pending_exception (mono_get_exception_argument ( \
253 "value", "not a widening conversion")); \
258 #define INVALID_CAST G_STMT_START{ \
259 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
260 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
264 /* Check element (destination) type. */
265 switch (ec->byval_arg.type) {
266 case MONO_TYPE_STRING:
267 switch (vc->byval_arg.type) {
268 case MONO_TYPE_STRING:
274 case MONO_TYPE_BOOLEAN:
275 switch (vc->byval_arg.type) {
276 case MONO_TYPE_BOOLEAN:
289 NO_WIDENING_CONVERSION;
298 if (!ec->valuetype) {
299 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
300 if (mono_error_set_pending_exception (&error))
304 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
308 if (mono_object_isinst_checked (value, ec, &error)) {
309 if (ec->has_references)
310 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
312 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
315 if (mono_error_set_pending_exception (&error))
321 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
323 et = ec->byval_arg.type;
324 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
325 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
327 vt = vc->byval_arg.type;
328 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
329 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
331 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
337 case MONO_TYPE_CHAR: \
338 CHECK_WIDENING_CONVERSION(0); \
339 *(etype *) ea = (etype) u64; \
341 /* You can't assign a signed value to an unsigned array. */ \
346 /* You can't assign a floating point number to an integer array. */ \
349 NO_WIDENING_CONVERSION; \
353 #define ASSIGN_SIGNED(etype) G_STMT_START{\
359 CHECK_WIDENING_CONVERSION(0); \
360 *(etype *) ea = (etype) i64; \
362 /* You can assign an unsigned value to a signed array if the array's */ \
363 /* element size is larger than the value size. */ \
368 case MONO_TYPE_CHAR: \
369 CHECK_WIDENING_CONVERSION(1); \
370 *(etype *) ea = (etype) u64; \
372 /* You can't assign a floating point number to an integer array. */ \
375 NO_WIDENING_CONVERSION; \
379 #define ASSIGN_REAL(etype) G_STMT_START{\
383 CHECK_WIDENING_CONVERSION(0); \
384 *(etype *) ea = (etype) r64; \
386 /* All integer values fit into a floating point array, so we don't */ \
387 /* need to CHECK_WIDENING_CONVERSION here. */ \
392 *(etype *) ea = (etype) i64; \
398 case MONO_TYPE_CHAR: \
399 *(etype *) ea = (etype) u64; \
406 u64 = *(guint8 *) va;
409 u64 = *(guint16 *) va;
412 u64 = *(guint32 *) va;
415 u64 = *(guint64 *) va;
421 i64 = *(gint16 *) va;
424 i64 = *(gint32 *) va;
427 i64 = *(gint64 *) va;
430 r64 = *(gfloat *) va;
433 r64 = *(gdouble *) va;
436 u64 = *(guint16 *) va;
438 case MONO_TYPE_BOOLEAN:
439 /* Boolean is only compatible with itself. */
452 NO_WIDENING_CONVERSION;
459 /* If we can't do a direct copy, let's try a widening conversion. */
462 ASSIGN_UNSIGNED (guint16);
464 ASSIGN_UNSIGNED (guint8);
466 ASSIGN_UNSIGNED (guint16);
468 ASSIGN_UNSIGNED (guint32);
470 ASSIGN_UNSIGNED (guint64);
472 ASSIGN_SIGNED (gint8);
474 ASSIGN_SIGNED (gint16);
476 ASSIGN_SIGNED (gint32);
478 ASSIGN_SIGNED (gint64);
480 ASSIGN_REAL (gfloat);
482 ASSIGN_REAL (gdouble);
486 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
490 #undef NO_WIDENING_CONVERSION
491 #undef CHECK_WIDENING_CONVERSION
492 #undef ASSIGN_UNSIGNED
498 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
504 MONO_CHECK_ARG_NULL (idxs,);
506 ic = idxs->obj.vtable->klass;
507 ac = arr->obj.vtable->klass;
509 g_assert (ic->rank == 1);
510 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
511 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
515 ind = (gint32 *)idxs->vector;
517 if (arr->bounds == NULL) {
518 if (*ind < 0 || *ind >= arr->max_length) {
519 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
523 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
527 for (i = 0; i < ac->rank; i++)
528 if ((ind [i] < arr->bounds [i].lower_bound) ||
529 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
530 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
534 pos = ind [0] - arr->bounds [0].lower_bound;
535 for (i = 1; i < ac->rank; i++)
536 pos = pos * arr->bounds [i].length + ind [i] -
537 arr->bounds [i].lower_bound;
539 ves_icall_System_Array_SetValueImpl (arr, value, pos);
542 ICALL_EXPORT MonoArray *
543 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
546 MonoClass *aklass, *klass;
549 gboolean bounded = FALSE;
551 MONO_CHECK_ARG_NULL (type, NULL);
552 MONO_CHECK_ARG_NULL (lengths, NULL);
554 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
556 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
558 for (i = 0; i < mono_array_length (lengths); i++) {
559 if (mono_array_get (lengths, gint32, i) < 0) {
560 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
565 klass = mono_class_from_mono_type (type->type);
566 mono_class_init_checked (klass, &error);
567 mono_error_raise_exception (&error);
569 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
570 /* vectors are not the same as one dimensional arrays with no-zero bounds */
575 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
577 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
578 for (i = 0; i < aklass->rank; ++i) {
579 sizes [i] = mono_array_get (lengths, guint32, i);
581 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
583 sizes [i + aklass->rank] = 0;
586 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
587 mono_error_set_pending_exception (&error);
592 ICALL_EXPORT MonoArray *
593 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
596 MonoClass *aklass, *klass;
599 gboolean bounded = FALSE;
601 MONO_CHECK_ARG_NULL (type, NULL);
602 MONO_CHECK_ARG_NULL (lengths, NULL);
604 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
606 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
608 for (i = 0; i < mono_array_length (lengths); i++) {
609 if ((mono_array_get (lengths, gint64, i) < 0) ||
610 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
611 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
616 klass = mono_class_from_mono_type (type->type);
617 mono_class_init_checked (klass, &error);
618 mono_error_raise_exception (&error);
620 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
621 /* vectors are not the same as one dimensional arrays with no-zero bounds */
626 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
628 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
629 for (i = 0; i < aklass->rank; ++i) {
630 sizes [i] = mono_array_get (lengths, guint64, i);
632 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
634 sizes [i + aklass->rank] = 0;
637 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
638 mono_error_set_pending_exception (&error);
644 ves_icall_System_Array_GetRank (MonoObject *arr)
646 return arr->vtable->klass->rank;
650 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
652 gint32 rank = arr->obj.vtable->klass->rank;
655 if ((dimension < 0) || (dimension >= rank)) {
656 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
660 if (arr->bounds == NULL)
661 length = arr->max_length;
663 length = arr->bounds [dimension].length;
665 #ifdef MONO_BIG_ARRAYS
666 if (length > G_MAXINT32) {
667 mono_set_pending_exception (mono_get_exception_overflow ());
675 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
677 gint32 rank = arr->obj.vtable->klass->rank;
679 if ((dimension < 0) || (dimension >= rank)) {
680 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
684 if (arr->bounds == NULL)
685 return arr->max_length;
687 return arr->bounds [dimension].length;
691 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
693 gint32 rank = arr->obj.vtable->klass->rank;
695 if ((dimension < 0) || (dimension >= rank)) {
696 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
700 if (arr->bounds == NULL)
703 return arr->bounds [dimension].lower_bound;
707 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
709 int sz = mono_array_element_size (mono_object_class (arr));
710 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
713 ICALL_EXPORT gboolean
714 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
719 MonoVTable *src_vtable;
720 MonoVTable *dest_vtable;
721 MonoClass *src_class;
722 MonoClass *dest_class;
724 src_vtable = source->obj.vtable;
725 dest_vtable = dest->obj.vtable;
727 if (src_vtable->rank != dest_vtable->rank)
730 if (source->bounds || dest->bounds)
733 /* there's no integer overflow since mono_array_length returns an unsigned integer */
734 if ((dest_idx + length > mono_array_length_fast (dest)) ||
735 (source_idx + length > mono_array_length_fast (source)))
738 src_class = src_vtable->klass->element_class;
739 dest_class = dest_vtable->klass->element_class;
742 * Handle common cases.
745 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
746 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
748 if (src_class == mono_defaults.object_class && dest_class->valuetype)
751 /* Check if we're copying a char[] <==> (u)short[] */
752 if (src_class != dest_class) {
753 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
756 /* 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. */
757 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
761 if (dest_class->valuetype) {
762 element_size = mono_array_element_size (source->obj.vtable->klass);
763 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
764 if (dest_class->has_references) {
765 mono_value_copy_array (dest, dest_idx, source_addr, length);
767 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
768 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
771 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
778 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
784 ac = (MonoClass *)arr->obj.vtable->klass;
786 esize = mono_array_element_size (ac);
787 ea = (gpointer*)((char*)arr->vector + (pos * esize));
789 mono_gc_memmove_atomic (value, ea, esize);
793 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
799 ac = (MonoClass *)arr->obj.vtable->klass;
800 ec = ac->element_class;
802 esize = mono_array_element_size (ac);
803 ea = (gpointer*)((char*)arr->vector + (pos * esize));
805 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
806 g_assert (esize == sizeof (gpointer));
807 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
809 g_assert (ec->inited);
810 g_assert (esize == mono_class_value_size (ec, NULL));
811 if (ec->has_references)
812 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
814 mono_gc_memmove_atomic (ea, value, esize);
819 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
821 MonoClass *klass = array->obj.vtable->klass;
822 guint32 size = mono_array_element_size (klass);
823 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
825 const char *field_data;
827 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
828 MonoException *exc = mono_get_exception_argument("array",
829 "Cannot initialize array of non-primitive type.");
830 mono_set_pending_exception (exc);
834 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
835 MonoException *exc = mono_get_exception_argument("field_handle",
836 "Field doesn't have an RVA");
837 mono_set_pending_exception (exc);
841 size *= array->max_length;
842 field_data = mono_field_get_data (field_handle);
844 if (size > mono_type_size (field_handle->type, &align)) {
845 MonoException *exc = mono_get_exception_argument("field_handle",
846 "Field not large enough to fill array");
847 mono_set_pending_exception (exc);
851 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
853 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
854 guint ## n *src = (guint ## n *) field_data; \
856 nEnt = (size / sizeof(guint ## n)); \
858 for (i = 0; i < nEnt; i++) { \
859 data[i] = read ## n (&src[i]); \
863 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
865 switch (type->type) {
882 memcpy (mono_array_addr (array, char, 0), field_data, size);
886 memcpy (mono_array_addr (array, char, 0), field_data, size);
891 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
893 return offsetof (MonoString, chars);
896 ICALL_EXPORT MonoObject *
897 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
899 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
903 MonoObject *ret = mono_object_clone_checked (obj, &error);
904 mono_error_set_pending_exception (&error);
911 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
917 MONO_CHECK_ARG_NULL (handle,);
919 klass = mono_class_from_mono_type (handle);
920 MONO_CHECK_ARG (handle, klass,);
922 if (klass->generic_container)
925 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
926 if (!is_ok (&error)) {
927 mono_error_set_pending_exception (&error);
931 /* This will call the type constructor */
932 if (!mono_runtime_class_init_full (vtable, &error))
933 mono_error_set_pending_exception (&error);
937 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
941 mono_image_check_for_module_cctor (image);
942 if (image->has_module_cctor) {
943 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
944 if (!mono_error_ok (&error)) {
945 mono_error_set_pending_exception (&error);
948 /*It's fine to raise the exception here*/
949 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
950 if (!is_ok (&error)) {
951 mono_error_set_pending_exception (&error);
954 if (!mono_runtime_class_init_full (vtable, &error))
955 mono_error_set_pending_exception (&error);
959 ICALL_EXPORT MonoBoolean
960 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
965 /* later make this configurable and per-arch */
966 int min_size = 4096 * 4 * sizeof (void*);
967 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
968 /* if we have no info we are optimistic and assume there is enough room */
972 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
976 current = (guint8 *)&stack_addr;
977 if (current > stack_addr) {
978 if ((current - stack_addr) < min_size)
981 if (current - (stack_addr - stack_size) < min_size)
987 ICALL_EXPORT MonoObject *
988 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
991 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
992 mono_error_set_pending_exception (&error);
998 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1002 MonoObject **values = NULL;
1005 gint32 result = (int)(gsize)mono_defaults.int32_class;
1006 MonoClassField* field;
1009 klass = mono_object_class (this_obj);
1011 if (mono_class_num_fields (klass) == 0)
1015 * Compute the starting value of the hashcode for fields of primitive
1016 * types, and return the remaining fields in an array to the managed side.
1017 * This way, we can avoid costly reflection operations in managed code.
1020 while ((field = mono_class_get_fields (klass, &iter))) {
1021 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1023 if (mono_field_is_deleted (field))
1025 /* FIXME: Add more types */
1026 switch (field->type->type) {
1028 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1030 case MONO_TYPE_STRING: {
1032 s = *(MonoString**)((guint8*)this_obj + field->offset);
1034 result ^= mono_string_hash (s);
1039 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1040 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1041 if (!is_ok (&error)) {
1042 mono_error_set_pending_exception (&error);
1045 values [count++] = o;
1051 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1052 for (i = 0; i < count; ++i)
1053 mono_array_setref (*fields, i, values [i]);
1060 ICALL_EXPORT MonoBoolean
1061 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1065 MonoObject **values = NULL;
1067 MonoClassField* field;
1071 MONO_CHECK_ARG_NULL (that, FALSE);
1073 if (this_obj->vtable != that->vtable)
1076 klass = mono_object_class (this_obj);
1078 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1079 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1082 * Do the comparison for fields of primitive type and return a result if
1083 * possible. Otherwise, return the remaining fields in an array to the
1084 * managed side. This way, we can avoid costly reflection operations in
1089 while ((field = mono_class_get_fields (klass, &iter))) {
1090 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1092 if (mono_field_is_deleted (field))
1094 /* FIXME: Add more types */
1095 switch (field->type->type) {
1098 case MONO_TYPE_BOOLEAN:
1099 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1104 case MONO_TYPE_CHAR:
1105 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1110 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1115 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1119 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1123 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1128 case MONO_TYPE_STRING: {
1129 MonoString *s1, *s2;
1130 guint32 s1len, s2len;
1131 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1132 s2 = *(MonoString**)((guint8*)that + field->offset);
1135 if ((s1 == NULL) || (s2 == NULL))
1137 s1len = mono_string_length (s1);
1138 s2len = mono_string_length (s2);
1142 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1148 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1149 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1150 if (!is_ok (&error)) {
1151 mono_error_set_pending_exception (&error);
1154 values [count++] = o;
1155 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1156 if (!is_ok (&error)) {
1157 mono_error_set_pending_exception (&error);
1160 values [count++] = o;
1163 if (klass->enumtype)
1164 /* enums only have one non-static field */
1170 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1171 for (i = 0; i < count; ++i)
1172 mono_array_setref_fast (*fields, i, values [i]);
1179 ICALL_EXPORT MonoReflectionType *
1180 ves_icall_System_Object_GetType (MonoObject *obj)
1183 MonoReflectionType *ret;
1184 #ifndef DISABLE_REMOTING
1185 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1186 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1189 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1191 mono_error_raise_exception (&error);
1197 ves_icall_MonoType_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1199 mtype->type = &obj->vtable->klass->byval_arg;
1200 g_assert (mtype->type->type);
1204 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1206 MONO_CHECK_ARG_NULL (obj, 0);
1209 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1210 mono_error_raise_exception (&error);
1215 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1216 MonoReflectionMethod *method,
1217 MonoArray *opt_param_types)
1219 MONO_CHECK_ARG_NULL (method, 0);
1222 gint32 result = mono_image_create_method_token (
1223 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1224 mono_error_raise_exception (&error);
1229 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1232 mono_image_create_pefile (mb, file, &error);
1233 mono_error_raise_exception (&error);
1237 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1240 if (!mono_image_build_metadata (mb, &error))
1241 mono_error_raise_exception (&error);
1245 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1247 mono_image_register_token (mb->dynamic_image, token, obj);
1250 ICALL_EXPORT MonoObject*
1251 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1255 mono_loader_lock ();
1256 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1257 mono_loader_unlock ();
1262 ICALL_EXPORT MonoReflectionModule*
1263 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1266 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1267 mono_error_set_pending_exception (&error);
1271 ICALL_EXPORT MonoArray*
1272 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
1275 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
1276 mono_error_set_pending_exception (&error);
1281 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1283 MonoMethod **dest = (MonoMethod **)data;
1285 /* skip unmanaged frames */
1301 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1303 MonoMethod **dest = (MonoMethod **)data;
1305 /* skip unmanaged frames */
1310 if (!strcmp (m->klass->name_space, "System.Reflection"))
1319 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1321 MonoMethod **dest = (MonoMethod **)data;
1323 /* skip unmanaged frames */
1327 if (m->wrapper_type != MONO_WRAPPER_NONE)
1330 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1344 static MonoReflectionType *
1345 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1347 MonoMethod *m, *dest;
1349 MonoType *type = NULL;
1350 MonoAssembly *assembly = NULL;
1351 gboolean type_resolve = FALSE;
1353 mono_error_init (error);
1356 * We must compute the calling assembly as type loading must happen under a metadata context.
1357 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1358 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1360 m = mono_method_get_last_managed ();
1363 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1368 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1369 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1370 * to crash. This only seems to happen in some strange remoting
1371 * scenarios and I was unable to figure out what's happening there.
1372 * Dec 10, 2005 - Martin.
1376 assembly = dest->klass->image->assembly;
1377 type_resolve = TRUE;
1379 g_warning (G_STRLOC);
1382 if (info->assembly.name)
1383 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1387 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1388 type = mono_reflection_get_type_checked (assembly->image, info, ignoreCase, &type_resolve, error);
1389 return_val_if_nok (error, NULL);
1392 if (!info->assembly.name && !type) {
1394 type = mono_reflection_get_type_checked (NULL, info, ignoreCase, &type_resolve, error);
1395 return_val_if_nok (error, NULL);
1397 if (assembly && !type && type_resolve) {
1398 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1399 type = mono_reflection_get_type_checked (assembly->image, info, ignoreCase, &type_resolve, error);
1400 return_val_if_nok (error, NULL);
1406 return mono_type_get_object_checked (mono_domain_get (), type, error);
1409 ICALL_EXPORT MonoReflectionType*
1410 ves_icall_System_Type_internal_from_name (MonoString *name,
1411 MonoBoolean throwOnError,
1412 MonoBoolean ignoreCase)
1415 char *str = mono_string_to_utf8 (name);
1416 MonoTypeNameParse info;
1417 MonoReflectionType *type;
1420 parsedOk = mono_reflection_parse_type (str, &info);
1422 /* mono_reflection_parse_type() mangles the string */
1424 mono_reflection_free_type_info (&info);
1427 mono_set_pending_exception (mono_get_exception_argument("typeName", "failed parse"));
1432 type = type_from_parsed_name (&info, ignoreCase, &error);
1434 mono_reflection_free_type_info (&info);
1437 if (!mono_error_ok (&error)) {
1439 mono_error_set_pending_exception (&error);
1441 mono_error_cleanup (&error);
1446 MonoException *e = NULL;
1449 e = mono_get_exception_type_load (name, NULL);
1451 mono_loader_clear_error ();
1453 mono_set_pending_exception (e);
1462 ICALL_EXPORT MonoReflectionType*
1463 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1466 MonoReflectionType *ret;
1467 MonoDomain *domain = mono_domain_get ();
1469 ret = mono_type_get_object_checked (domain, handle, &error);
1470 mono_error_raise_exception (&error);
1475 /* System.TypeCode */
1494 TYPECODE_STRING = 18
1497 ICALL_EXPORT guint32
1498 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1500 int t = type->type->type;
1502 if (type->type->byref)
1503 return TYPECODE_OBJECT;
1507 case MONO_TYPE_VOID:
1508 return TYPECODE_OBJECT;
1509 case MONO_TYPE_BOOLEAN:
1510 return TYPECODE_BOOLEAN;
1512 return TYPECODE_BYTE;
1514 return TYPECODE_SBYTE;
1516 return TYPECODE_UINT16;
1518 return TYPECODE_INT16;
1519 case MONO_TYPE_CHAR:
1520 return TYPECODE_CHAR;
1524 return TYPECODE_OBJECT;
1526 return TYPECODE_UINT32;
1528 return TYPECODE_INT32;
1530 return TYPECODE_UINT64;
1532 return TYPECODE_INT64;
1534 return TYPECODE_SINGLE;
1536 return TYPECODE_DOUBLE;
1537 case MONO_TYPE_VALUETYPE: {
1538 MonoClass *klass = type->type->data.klass;
1540 if (klass->enumtype) {
1541 t = mono_class_enum_basetype (klass)->type;
1543 } else if (mono_is_corlib_image (klass->image)) {
1544 if (strcmp (klass->name_space, "System") == 0) {
1545 if (strcmp (klass->name, "Decimal") == 0)
1546 return TYPECODE_DECIMAL;
1547 else if (strcmp (klass->name, "DateTime") == 0)
1548 return TYPECODE_DATETIME;
1551 return TYPECODE_OBJECT;
1553 case MONO_TYPE_STRING:
1554 return TYPECODE_STRING;
1555 case MONO_TYPE_SZARRAY:
1556 case MONO_TYPE_ARRAY:
1557 case MONO_TYPE_OBJECT:
1559 case MONO_TYPE_MVAR:
1560 case MONO_TYPE_TYPEDBYREF:
1561 return TYPECODE_OBJECT;
1562 case MONO_TYPE_CLASS:
1564 MonoClass *klass = type->type->data.klass;
1565 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1566 if (strcmp (klass->name, "DBNull") == 0)
1567 return TYPECODE_DBNULL;
1570 return TYPECODE_OBJECT;
1571 case MONO_TYPE_GENERICINST:
1572 return TYPECODE_OBJECT;
1574 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1580 mono_type_is_primitive (MonoType *type)
1582 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1583 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1587 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1589 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1590 return mono_class_enum_basetype (type->data.klass);
1591 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1592 return mono_class_enum_basetype (type->data.generic_class->container_class);
1596 ICALL_EXPORT guint32
1597 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1602 g_assert (type != NULL);
1604 klass = mono_class_from_mono_type (type->type);
1605 klassc = mono_class_from_mono_type (c->type);
1607 if (type->type->byref ^ c->type->byref)
1610 if (type->type->byref) {
1611 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1612 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1614 klass = mono_class_from_mono_type (t);
1615 klassc = mono_class_from_mono_type (ot);
1617 if (mono_type_is_primitive (t)) {
1618 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1619 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1620 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1621 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1622 return t->type == ot->type;
1624 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1627 if (klass->valuetype)
1628 return klass == klassc;
1629 return klass->valuetype == klassc->valuetype;
1632 return mono_class_is_assignable_from (klass, klassc);
1635 ICALL_EXPORT guint32
1636 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1639 MonoClass *klass = mono_class_from_mono_type (type->type);
1640 mono_class_init_checked (klass, &error);
1641 if (!is_ok (&error)) {
1642 mono_error_set_pending_exception (&error);
1645 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1646 mono_error_set_pending_exception (&error);
1650 ICALL_EXPORT guint32
1651 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1653 MonoClass *klass = mono_class_from_mono_type (type->type);
1654 return klass->flags;
1657 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1658 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1661 MonoClass *klass = field->field->parent;
1662 MonoMarshalType *info;
1666 if (klass->generic_container ||
1667 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1670 ftype = mono_field_get_type (field->field);
1671 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1674 info = mono_marshal_load_type_info (klass);
1676 for (i = 0; i < info->num_fields; ++i) {
1677 if (info->fields [i].field == field->field) {
1678 if (!info->fields [i].mspec)
1681 MonoReflectionMarshalAsAttribute* obj;
1682 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1683 if (!mono_error_ok (&error))
1684 mono_error_set_pending_exception (&error);
1693 ICALL_EXPORT MonoReflectionField*
1694 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1697 gboolean found = FALSE;
1704 klass = handle->parent;
1706 klass = mono_class_from_mono_type (type);
1708 /* Check that the field belongs to the class */
1709 for (k = klass; k; k = k->parent) {
1710 if (k == handle->parent) {
1717 /* The managed code will throw the exception */
1721 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1722 mono_error_raise_exception (&error);
1726 ICALL_EXPORT MonoArray*
1727 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1730 MonoType *type = mono_field_get_type_checked (field->field, &error);
1733 if (!mono_error_ok (&error)) {
1734 mono_error_set_pending_exception (&error);
1738 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1739 mono_error_raise_exception (&error);
1744 vell_icall_get_method_attributes (MonoMethod *method)
1746 return method->flags;
1750 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1753 MonoReflectionType *rt;
1754 MonoDomain *domain = mono_domain_get ();
1755 MonoMethodSignature* sig;
1757 sig = mono_method_signature_checked (method, &error);
1758 if (!mono_error_ok (&error)) {
1759 mono_error_set_pending_exception (&error);
1763 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1764 if (!mono_error_ok (&error)) {
1765 mono_error_set_pending_exception (&error);
1769 MONO_STRUCT_SETREF (info, parent, rt);
1771 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1772 if (!mono_error_ok (&error)) {
1773 mono_error_set_pending_exception (&error);
1777 MONO_STRUCT_SETREF (info, ret, rt);
1779 info->attrs = method->flags;
1780 info->implattrs = method->iflags;
1781 if (sig->call_convention == MONO_CALL_DEFAULT)
1782 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1784 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1789 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1792 ICALL_EXPORT MonoArray*
1793 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1796 MonoDomain *domain = mono_domain_get ();
1798 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1799 mono_error_set_pending_exception (&error);
1803 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1804 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1807 MonoDomain *domain = mono_domain_get ();
1808 MonoReflectionMarshalAsAttribute* res = NULL;
1809 MonoMarshalSpec **mspecs;
1812 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1813 mono_method_get_marshal_info (method, mspecs);
1816 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1817 if (!mono_error_ok (&error)) {
1818 mono_error_set_pending_exception (&error);
1823 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1825 mono_metadata_free_marshal_spec (mspecs [i]);
1832 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1834 MonoClass *parent = field->field->parent;
1835 if (!parent->size_inited)
1836 mono_class_init (parent);
1837 mono_class_setup_fields_locking (parent);
1839 return field->field->offset - sizeof (MonoObject);
1842 ICALL_EXPORT MonoReflectionType*
1843 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1846 MonoReflectionType *ret;
1849 parent = declaring? field->field->parent: field->klass;
1851 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1852 mono_error_raise_exception (&error);
1858 ICALL_EXPORT MonoObject *
1859 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1862 MonoClass *fklass = field->klass;
1863 MonoClassField *cf = field->field;
1864 MonoDomain *domain = mono_object_domain (field);
1866 if (fklass->image->assembly->ref_only) {
1867 mono_set_pending_exception (mono_get_exception_invalid_operation (
1868 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1872 if (mono_security_core_clr_enabled () &&
1873 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1874 mono_error_set_pending_exception (&error);
1878 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1879 mono_error_set_pending_exception (&error);
1884 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1887 MonoClassField *cf = field->field;
1891 if (field->klass->image->assembly->ref_only) {
1892 mono_set_pending_exception (mono_get_exception_invalid_operation (
1893 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1897 if (mono_security_core_clr_enabled () &&
1898 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1899 mono_error_set_pending_exception (&error);
1903 type = mono_field_get_type_checked (cf, &error);
1904 if (!mono_error_ok (&error)) {
1905 mono_error_set_pending_exception (&error);
1909 v = (gchar *) value;
1911 switch (type->type) {
1914 case MONO_TYPE_BOOLEAN:
1917 case MONO_TYPE_CHAR:
1926 case MONO_TYPE_VALUETYPE:
1929 v += sizeof (MonoObject);
1931 case MONO_TYPE_STRING:
1932 case MONO_TYPE_OBJECT:
1933 case MONO_TYPE_CLASS:
1934 case MONO_TYPE_ARRAY:
1935 case MONO_TYPE_SZARRAY:
1938 case MONO_TYPE_GENERICINST: {
1939 MonoGenericClass *gclass = type->data.generic_class;
1940 g_assert (!gclass->context.class_inst->is_open);
1942 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1943 MonoClass *nklass = mono_class_from_mono_type (type);
1944 MonoObject *nullable;
1947 * Convert the boxed vtype into a Nullable structure.
1948 * This is complicated by the fact that Nullables have
1949 * a variable structure.
1951 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1952 if (!mono_error_ok (&error)) {
1953 mono_error_set_pending_exception (&error);
1957 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1959 v = (gchar *)mono_object_unbox (nullable);
1962 if (gclass->container_class->valuetype && (v != NULL))
1963 v += sizeof (MonoObject);
1967 g_error ("type 0x%x not handled in "
1968 "ves_icall_FieldInfo_SetValueInternal", type->type);
1973 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1974 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
1975 if (!is_ok (&error)) {
1976 mono_error_set_pending_exception (&error);
1979 if (!vtable->initialized) {
1980 if (!mono_runtime_class_init_full (vtable, &error)) {
1981 mono_error_set_pending_exception (&error);
1985 mono_field_static_set_value (vtable, cf, v);
1987 mono_field_set_value (obj, cf, v);
1992 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2001 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2002 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2006 if (MONO_TYPE_IS_REFERENCE (f->type))
2007 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2009 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2012 ICALL_EXPORT MonoObject *
2013 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2015 MonoObject *o = NULL;
2016 MonoClassField *field = rfield->field;
2018 MonoDomain *domain = mono_object_domain (rfield);
2020 MonoTypeEnum def_type;
2021 const char *def_value;
2025 mono_class_init (field->parent);
2027 t = mono_field_get_type_checked (field, &error);
2028 if (!mono_error_ok (&error)) {
2029 mono_error_set_pending_exception (&error);
2033 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2034 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2038 if (image_is_dynamic (field->parent->image)) {
2039 MonoClass *klass = field->parent;
2040 int fidx = field - klass->fields;
2042 g_assert (fidx >= 0 && fidx < klass->field.count);
2043 g_assert (klass->ext);
2044 g_assert (klass->ext->field_def_values);
2045 def_type = klass->ext->field_def_values [fidx].def_type;
2046 def_value = klass->ext->field_def_values [fidx].data;
2047 if (def_type == MONO_TYPE_END) {
2048 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2052 def_value = mono_class_get_field_default_value (field, &def_type);
2053 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2055 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2060 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2064 case MONO_TYPE_BOOLEAN:
2067 case MONO_TYPE_CHAR:
2075 case MONO_TYPE_R8: {
2078 /* boxed value type */
2079 t = g_new0 (MonoType, 1);
2081 klass = mono_class_from_mono_type (t);
2083 o = mono_object_new_checked (domain, klass, &error);
2084 if (!mono_error_ok (&error)) {
2085 mono_error_set_pending_exception (&error);
2088 v = ((gchar *) o) + sizeof (MonoObject);
2089 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2092 case MONO_TYPE_STRING:
2093 case MONO_TYPE_CLASS:
2094 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2097 g_assert_not_reached ();
2103 ICALL_EXPORT MonoReflectionType*
2104 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2107 MonoReflectionType *ret;
2110 type = mono_field_get_type_checked (ref_field->field, &error);
2111 if (!mono_error_ok (&error)) {
2112 mono_error_set_pending_exception (&error);
2116 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2117 if (!mono_error_ok (&error)) {
2118 mono_error_set_pending_exception (&error);
2125 /* From MonoProperty.cs */
2127 PInfo_Attributes = 1,
2128 PInfo_GetMethod = 1 << 1,
2129 PInfo_SetMethod = 1 << 2,
2130 PInfo_ReflectedType = 1 << 3,
2131 PInfo_DeclaringType = 1 << 4,
2136 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2139 MonoReflectionType *rt;
2140 MonoReflectionMethod *rm;
2141 MonoDomain *domain = mono_object_domain (property);
2142 const MonoProperty *pproperty = property->property;
2144 if ((req_info & PInfo_ReflectedType) != 0) {
2145 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2146 mono_error_raise_exception (&error);
2148 MONO_STRUCT_SETREF (info, parent, rt);
2150 if ((req_info & PInfo_DeclaringType) != 0) {
2151 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2152 mono_error_raise_exception (&error);
2154 MONO_STRUCT_SETREF (info, declaring_type, rt);
2157 if ((req_info & PInfo_Name) != 0)
2158 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2160 if ((req_info & PInfo_Attributes) != 0)
2161 info->attrs = pproperty->attrs;
2163 if ((req_info & PInfo_GetMethod) != 0) {
2164 if (pproperty->get &&
2165 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2166 pproperty->get->klass == property->klass)) {
2167 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2168 mono_error_raise_exception (&error);
2173 MONO_STRUCT_SETREF (info, get, rm);
2175 if ((req_info & PInfo_SetMethod) != 0) {
2176 if (pproperty->set &&
2177 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2178 pproperty->set->klass == property->klass)) {
2179 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2180 mono_error_raise_exception (&error);
2185 MONO_STRUCT_SETREF (info, set, rm);
2188 * There may be other methods defined for properties, though, it seems they are not exposed
2189 * in the reflection API
2194 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2197 MonoReflectionType *rt;
2198 MonoReflectionMethod *rm;
2199 MonoDomain *domain = mono_object_domain (event);
2201 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2202 mono_error_raise_exception (&error);
2204 MONO_STRUCT_SETREF (info, reflected_type, rt);
2206 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2207 mono_error_raise_exception (&error);
2209 MONO_STRUCT_SETREF (info, declaring_type, rt);
2211 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2212 info->attrs = event->event->attrs;
2214 if (event->event->add) {
2215 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2216 mono_error_raise_exception (&error);
2221 MONO_STRUCT_SETREF (info, add_method, rm);
2223 if (event->event->remove) {
2224 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2225 mono_error_raise_exception (&error);
2230 MONO_STRUCT_SETREF (info, remove_method, rm);
2232 if (event->event->raise) {
2233 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2234 mono_error_raise_exception (&error);
2239 MONO_STRUCT_SETREF (info, raise_method, rm);
2241 #ifndef MONO_SMALL_CONFIG
2242 if (event->event->other) {
2244 while (event->event->other [n])
2246 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2248 for (i = 0; i < n; i++) {
2249 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2250 mono_error_raise_exception (&error);
2251 mono_array_setref (info->other_methods, i, rm);
2258 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2263 mono_class_setup_interfaces (klass, error);
2264 if (!mono_error_ok (error))
2267 for (i = 0; i < klass->interface_count; i++) {
2268 ic = klass->interfaces [i];
2269 g_hash_table_insert (ifaces, ic, ic);
2271 collect_interfaces (ic, ifaces, error);
2272 if (!mono_error_ok (error))
2278 MonoArray *iface_array;
2279 MonoGenericContext *context;
2283 } FillIfaceArrayData;
2286 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2288 MonoReflectionType *rt;
2289 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2290 MonoClass *ic = (MonoClass *)key;
2291 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2293 if (!mono_error_ok (data->error))
2296 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2297 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2298 if (!mono_error_ok (data->error))
2302 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2303 if (!mono_error_ok (data->error))
2306 mono_array_setref (data->iface_array, data->next_idx++, rt);
2309 mono_metadata_free_type (inflated);
2313 get_interfaces_hash (gconstpointer v1)
2315 MonoClass *k = (MonoClass*)v1;
2317 return k->type_token;
2320 ICALL_EXPORT MonoArray*
2321 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2324 MonoClass *klass = mono_class_from_mono_type (type->type);
2326 FillIfaceArrayData data = { 0 };
2329 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2331 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2332 data.context = mono_class_get_context (klass);
2333 klass = klass->generic_class->container_class;
2336 for (parent = klass; parent; parent = parent->parent) {
2337 mono_class_setup_interfaces (parent, &error);
2338 if (!mono_error_ok (&error))
2340 collect_interfaces (parent, iface_hash, &error);
2341 if (!mono_error_ok (&error))
2345 data.error = &error;
2346 data.domain = mono_object_domain (type);
2348 len = g_hash_table_size (iface_hash);
2350 g_hash_table_destroy (iface_hash);
2351 if (!data.domain->empty_types)
2352 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2353 return data.domain->empty_types;
2356 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2357 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2358 if (!mono_error_ok (&error))
2361 g_hash_table_destroy (iface_hash);
2362 return data.iface_array;
2365 g_hash_table_destroy (iface_hash);
2366 mono_error_set_pending_exception (&error);
2371 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2373 gboolean variance_used;
2374 MonoClass *klass = mono_class_from_mono_type (type->type);
2375 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2376 MonoReflectionMethod *member;
2379 int i = 0, len, ioffset;
2383 mono_class_init_checked (klass, &error);
2384 mono_error_raise_exception (&error);
2385 mono_class_init_checked (iclass, &error);
2386 mono_error_raise_exception (&error);
2388 mono_class_setup_vtable (klass);
2390 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2394 len = mono_class_num_methods (iclass);
2395 domain = mono_object_domain (type);
2396 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2397 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2399 while ((method = mono_class_get_methods (iclass, &iter))) {
2400 member = mono_method_get_object_checked (domain, method, iclass, &error);
2401 mono_error_raise_exception (&error);
2402 mono_array_setref (*methods, i, member);
2403 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2404 mono_error_raise_exception (&error);
2405 mono_array_setref (*targets, i, member);
2412 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2415 MonoClass *klass = mono_class_from_mono_type (type->type);
2417 mono_class_init_checked (klass, &error);
2418 mono_error_raise_exception (&error);
2420 if (image_is_dynamic (klass->image)) {
2421 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2422 *packing = tb->packing_size;
2423 *size = tb->class_size;
2425 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2429 ICALL_EXPORT MonoReflectionType*
2430 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2433 MonoReflectionType *ret;
2436 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2437 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2438 mono_error_raise_exception (&error);
2443 klass = mono_class_from_mono_type (type->type);
2444 mono_class_init_checked (klass, &error);
2445 mono_error_raise_exception (&error);
2447 // GetElementType should only return a type for:
2448 // Array Pointer PassedByRef
2449 if (type->type->byref)
2450 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2451 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2452 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2453 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2454 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2458 mono_error_raise_exception (&error);
2463 ICALL_EXPORT MonoReflectionType*
2464 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2467 MonoReflectionType *ret;
2469 if (type->type->byref)
2472 MonoClass *klass = mono_class_from_mono_type (type->type);
2476 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2477 mono_error_raise_exception (&error);
2482 ICALL_EXPORT MonoBoolean
2483 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2485 return type->type->type == MONO_TYPE_PTR;
2488 ICALL_EXPORT MonoBoolean
2489 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2491 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)));
2494 ICALL_EXPORT MonoBoolean
2495 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2497 return type->type->byref;
2500 ICALL_EXPORT MonoBoolean
2501 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2504 MonoClass *klass = mono_class_from_mono_type (type->type);
2505 mono_class_init_checked (klass, &error);
2506 mono_error_raise_exception (&error);
2508 return mono_class_is_com_object (klass);
2511 ICALL_EXPORT guint32
2512 ves_icall_reflection_get_token (MonoObject* obj)
2515 guint32 result = mono_reflection_get_token_checked (obj, &error);
2516 mono_error_set_pending_exception (&error);
2520 ICALL_EXPORT MonoReflectionModule*
2521 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2524 MonoReflectionModule *result = NULL;
2525 MonoClass *klass = mono_class_from_mono_type (type->type);
2526 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2527 if (!mono_error_ok (&error))
2528 mono_error_set_pending_exception (&error);
2532 ICALL_EXPORT MonoReflectionAssembly*
2533 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2536 MonoDomain *domain = mono_domain_get ();
2537 MonoClass *klass = mono_class_from_mono_type (type->type);
2538 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2540 mono_error_set_pending_exception (&error);
2544 ICALL_EXPORT MonoReflectionType*
2545 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2548 MonoReflectionType *ret;
2549 MonoDomain *domain = mono_domain_get ();
2552 if (type->type->byref)
2554 if (type->type->type == MONO_TYPE_VAR) {
2555 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2556 klass = param ? param->owner.klass : NULL;
2557 } else if (type->type->type == MONO_TYPE_MVAR) {
2558 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2559 klass = param ? param->owner.method->klass : NULL;
2561 klass = mono_class_from_mono_type (type->type)->nested_in;
2567 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2568 mono_error_raise_exception (&error);
2573 ICALL_EXPORT MonoString*
2574 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2576 MonoDomain *domain = mono_domain_get ();
2577 MonoClass *klass = mono_class_from_mono_type (type->type);
2579 if (type->type->byref) {
2580 char *n = g_strdup_printf ("%s&", klass->name);
2581 MonoString *res = mono_string_new (domain, n);
2587 return mono_string_new (domain, klass->name);
2591 ICALL_EXPORT MonoString*
2592 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2594 MonoDomain *domain = mono_domain_get ();
2595 MonoClass *klass = mono_class_from_mono_type (type->type);
2597 while (klass->nested_in)
2598 klass = klass->nested_in;
2600 if (klass->name_space [0] == '\0')
2603 return mono_string_new (domain, klass->name_space);
2607 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2611 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2612 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2616 klass = mono_class_from_mono_type (type->type);
2622 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2625 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2629 ICALL_EXPORT MonoArray*
2630 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2633 MonoReflectionType *rt;
2635 MonoClass *klass, *pklass;
2636 MonoDomain *domain = mono_object_domain (type);
2639 klass = mono_class_from_mono_type (type->type);
2641 if (klass->generic_container) {
2642 MonoGenericContainer *container = klass->generic_container;
2643 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2644 for (i = 0; i < container->type_argc; ++i) {
2645 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2647 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2648 mono_error_raise_exception (&error);
2650 mono_array_setref (res, i, rt);
2652 } else if (klass->generic_class) {
2653 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2654 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2655 for (i = 0; i < inst->type_argc; ++i) {
2656 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2657 mono_error_raise_exception (&error);
2659 mono_array_setref (res, i, rt);
2667 ICALL_EXPORT gboolean
2668 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (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_container != NULL;
2682 ICALL_EXPORT MonoReflectionType*
2683 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2686 MonoReflectionType *ret;
2689 if (type->type->byref)
2692 klass = mono_class_from_mono_type (type->type);
2694 if (klass->generic_container) {
2695 return type; /* check this one */
2697 if (klass->generic_class) {
2698 MonoClass *generic_class = klass->generic_class->container_class;
2701 tb = mono_class_get_ref_info (generic_class);
2703 if (generic_class->wastypebuilder && tb)
2704 return (MonoReflectionType *)tb;
2706 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2707 mono_error_raise_exception (&error);
2715 ICALL_EXPORT MonoReflectionType*
2716 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2719 MonoReflectionType *ret;
2721 MonoType *geninst, **types;
2724 g_assert (IS_MONOTYPE (type));
2725 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2726 mono_error_raise_exception (&error);
2728 count = mono_array_length (type_array);
2729 types = g_new0 (MonoType *, count);
2731 for (i = 0; i < count; i++) {
2732 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2733 types [i] = t->type;
2736 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2739 mono_error_set_pending_exception (&error);
2743 klass = mono_class_from_mono_type (geninst);
2745 /*we might inflate to the GTD*/
2746 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2747 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2751 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2752 mono_error_raise_exception (&error);
2757 ICALL_EXPORT gboolean
2758 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2762 if (!IS_MONOTYPE (type))
2765 if (type->type->byref)
2768 klass = mono_class_from_mono_type (type->type);
2769 return klass->generic_class != NULL || klass->generic_container != NULL;
2773 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2775 if (!IS_MONOTYPE (type))
2778 if (is_generic_parameter (type->type))
2779 return mono_type_get_generic_param_num (type->type);
2783 ICALL_EXPORT GenericParameterAttributes
2784 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2786 g_assert (IS_MONOTYPE (type));
2787 g_assert (is_generic_parameter (type->type));
2788 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2791 ICALL_EXPORT MonoArray *
2792 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2795 MonoReflectionType *rt;
2796 MonoGenericParamInfo *param_info;
2802 g_assert (IS_MONOTYPE (type));
2804 domain = mono_object_domain (type);
2805 param_info = mono_generic_param_info (type->type->data.generic_param);
2806 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2809 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2810 for (i = 0; i < count; i++) {
2811 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2812 mono_error_raise_exception (&error);
2814 mono_array_setref (res, i, rt);
2821 ICALL_EXPORT MonoBoolean
2822 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2824 return is_generic_parameter (type->type);
2827 ICALL_EXPORT MonoBoolean
2828 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2830 return is_generic_parameter (tb->type.type);
2834 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2835 MonoReflectionType *t)
2837 enumtype->type = t->type;
2840 ICALL_EXPORT MonoReflectionMethod*
2841 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2842 MonoReflectionMethod* generic)
2849 MonoReflectionMethod *ret = NULL;
2851 domain = ((MonoObject *)type)->vtable->domain;
2853 klass = mono_class_from_mono_type (type->type);
2854 mono_class_init_checked (klass, &error);
2855 mono_error_raise_exception (&error);
2858 while ((method = mono_class_get_methods (klass, &iter))) {
2859 if (method->token == generic->method->token) {
2860 ret = mono_method_get_object_checked (domain, method, klass, &error);
2861 mono_error_raise_exception (&error);
2868 ICALL_EXPORT MonoReflectionMethod *
2869 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2872 MonoType *type = ref_type->type;
2874 MonoReflectionMethod *ret = NULL;
2876 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2877 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2880 if (type->type == MONO_TYPE_VAR)
2883 method = mono_type_get_generic_param_owner (type)->owner.method;
2886 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2887 if (!mono_error_ok (&error))
2888 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2892 ICALL_EXPORT MonoBoolean
2893 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2895 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2899 ICALL_EXPORT MonoBoolean
2900 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2902 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2907 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2909 MonoDomain *domain = mono_domain_get ();
2910 MonoImage *image = method->method->klass->image;
2911 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2912 MonoTableInfo *tables = image->tables;
2913 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2914 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2915 guint32 im_cols [MONO_IMPLMAP_SIZE];
2916 guint32 scope_token;
2917 const char *import = NULL;
2918 const char *scope = NULL;
2920 if (image_is_dynamic (image)) {
2921 MonoReflectionMethodAux *method_aux =
2922 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2924 import = method_aux->dllentry;
2925 scope = method_aux->dll;
2928 if (!import || !scope) {
2929 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2934 if (piinfo->implmap_idx) {
2935 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2937 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2938 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2939 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2940 scope = mono_metadata_string_heap (image, scope_token);
2944 *flags = piinfo->piflags;
2945 *entry_point = mono_string_new (domain, import);
2946 *dll_name = mono_string_new (domain, scope);
2949 ICALL_EXPORT MonoReflectionMethod *
2950 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2952 MonoMethodInflated *imethod;
2954 MonoReflectionMethod *ret = NULL;
2957 if (method->method->is_generic)
2960 if (!method->method->is_inflated)
2963 imethod = (MonoMethodInflated *) method->method;
2965 result = imethod->declaring;
2966 /* Not a generic method. */
2967 if (!result->is_generic)
2970 if (image_is_dynamic (method->method->klass->image)) {
2971 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2972 MonoReflectionMethod *res;
2975 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2976 * the dynamic case as well ?
2978 mono_image_lock ((MonoImage*)image);
2979 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2980 mono_image_unlock ((MonoImage*)image);
2986 if (imethod->context.class_inst) {
2987 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2988 /*Generic methods gets the context of the GTD.*/
2989 if (mono_class_get_context (klass)) {
2990 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2991 if (!mono_error_ok (&error))
2996 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2998 if (!mono_error_ok (&error))
2999 mono_error_set_pending_exception (&error);
3003 ICALL_EXPORT gboolean
3004 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3006 return mono_method_signature (method->method)->generic_param_count != 0;
3009 ICALL_EXPORT gboolean
3010 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3012 return method->method->is_generic;
3015 ICALL_EXPORT MonoArray*
3016 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3019 MonoReflectionType *rt;
3024 domain = mono_object_domain (method);
3026 if (method->method->is_inflated) {
3027 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3030 count = inst->type_argc;
3031 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3033 for (i = 0; i < count; i++) {
3034 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3035 mono_error_raise_exception (&error);
3037 mono_array_setref (res, i, rt);
3044 count = mono_method_signature (method->method)->generic_param_count;
3045 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3047 for (i = 0; i < count; i++) {
3048 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3049 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3050 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3052 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3053 mono_error_raise_exception (&error);
3055 mono_array_setref (res, i, rt);
3061 ICALL_EXPORT MonoObject *
3062 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3066 * Invoke from reflection is supposed to always be a virtual call (the API
3067 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3068 * greater flexibility.
3070 MonoMethod *m = method->method;
3071 MonoMethodSignature *sig = mono_method_signature (m);
3074 void *obj = this_arg;
3078 if (mono_security_core_clr_enabled ())
3079 mono_security_core_clr_ensure_reflection_access_method (m);
3081 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3082 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3083 mono_error_cleanup (&error); /* FIXME does this make sense? */
3084 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3089 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3090 if (!is_ok (&error)) {
3091 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3094 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3095 char *target_name = mono_type_get_full_name (m->klass);
3096 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3097 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3099 g_free (target_name);
3103 m = mono_object_get_virtual_method (this_arg, m);
3104 /* must pass the pointer to the value for valuetype methods */
3105 if (m->klass->valuetype)
3106 obj = mono_object_unbox (this_arg);
3107 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3108 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3113 if (sig->ret->byref) {
3114 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"));
3118 pcount = params? mono_array_length (params): 0;
3119 if (pcount != sig->param_count) {
3120 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3124 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3125 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."));
3129 image = m->klass->image;
3130 if (image->assembly->ref_only) {
3131 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."));
3135 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3136 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3140 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3144 intptr_t *lower_bounds;
3145 pcount = mono_array_length (params);
3146 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3147 /* Note: the synthetized array .ctors have int32 as argument type */
3148 for (i = 0; i < pcount; ++i)
3149 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3151 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3152 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3153 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3154 if (!mono_error_ok (&error)) {
3155 mono_error_set_pending_exception (&error);
3159 for (i = 0; i < mono_array_length (arr); ++i) {
3160 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3161 if (!mono_error_ok (&error)) {
3162 mono_error_set_pending_exception (&error);
3165 mono_array_setref_fast (arr, i, subarray);
3167 return (MonoObject*)arr;
3170 if (m->klass->rank == pcount) {
3171 /* Only lengths provided. */
3172 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3173 if (!mono_error_ok (&error)) {
3174 mono_error_set_pending_exception (&error);
3178 return (MonoObject*)arr;
3180 g_assert (pcount == (m->klass->rank * 2));
3181 /* The arguments are lower-bound-length pairs */
3182 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3184 for (i = 0; i < pcount / 2; ++i) {
3185 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3186 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3189 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3190 if (!mono_error_ok (&error)) {
3191 mono_error_set_pending_exception (&error);
3195 return (MonoObject*)arr;
3198 return mono_runtime_invoke_array (m, obj, params, NULL);
3201 #ifndef DISABLE_REMOTING
3202 ICALL_EXPORT MonoObject *
3203 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3206 MonoDomain *domain = mono_object_domain (method);
3207 MonoMethod *m = method->method;
3208 MonoMethodSignature *sig = mono_method_signature (m);
3209 MonoArray *out_args;
3211 int i, j, outarg_count = 0;
3213 if (m->klass == mono_defaults.object_class) {
3214 if (!strcmp (m->name, "FieldGetter")) {
3215 MonoClass *k = this_arg->vtable->klass;
3219 /* If this is a proxy, then it must be a CBO */
3220 if (k == mono_defaults.transparent_proxy_class) {
3221 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3222 this_arg = tp->rp->unwrapped_server;
3223 g_assert (this_arg);
3224 k = this_arg->vtable->klass;
3227 name = mono_array_get (params, MonoString *, 1);
3228 str = mono_string_to_utf8 (name);
3231 MonoClassField* field = mono_class_get_field_from_name (k, str);
3233 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3234 if (field_klass->valuetype) {
3235 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3236 mono_error_set_pending_exception (&error);
3237 /* fallthru to cleanup */
3239 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3241 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3242 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3243 mono_array_setref (out_args, 0, result);
3251 g_assert_not_reached ();
3253 } else if (!strcmp (m->name, "FieldSetter")) {
3254 MonoClass *k = this_arg->vtable->klass;
3260 /* If this is a proxy, then it must be a CBO */
3261 if (k == mono_defaults.transparent_proxy_class) {
3262 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3263 this_arg = tp->rp->unwrapped_server;
3264 g_assert (this_arg);
3265 k = this_arg->vtable->klass;
3268 name = mono_array_get (params, MonoString *, 1);
3269 str = mono_string_to_utf8 (name);
3272 MonoClassField* field = mono_class_get_field_from_name (k, str);
3274 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3275 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3277 if (field_klass->valuetype) {
3278 size = mono_type_size (field->type, &align);
3279 g_assert (size == mono_class_value_size (field_klass, NULL));
3280 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3282 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3285 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3286 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3296 g_assert_not_reached ();
3301 for (i = 0; i < mono_array_length (params); i++) {
3302 if (sig->params [i]->byref)
3306 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3308 /* handle constructors only for objects already allocated */
3309 if (!strcmp (method->method->name, ".ctor"))
3310 g_assert (this_arg);
3312 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3313 g_assert (!method->method->klass->valuetype);
3314 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3316 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3317 if (sig->params [i]->byref) {
3319 arg = mono_array_get (params, gpointer, i);
3320 mono_array_setref (out_args, j, arg);
3325 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3332 read_enum_value (const char *mem, int type)
3335 case MONO_TYPE_BOOLEAN:
3337 return *(guint8*)mem;
3339 return *(gint8*)mem;
3340 case MONO_TYPE_CHAR:
3342 return read16 (mem);
3344 return (gint16) read16 (mem);
3346 return read32 (mem);
3348 return (gint32) read32 (mem);
3351 return read64 (mem);
3353 g_assert_not_reached ();
3359 write_enum_value (char *mem, int type, guint64 value)
3363 case MONO_TYPE_I1: {
3364 guint8 *p = (guint8*)mem;
3369 case MONO_TYPE_I2: {
3370 guint16 *p = (guint16 *)mem;
3375 case MONO_TYPE_I4: {
3376 guint32 *p = (guint32 *)mem;
3381 case MONO_TYPE_I8: {
3382 guint64 *p = (guint64 *)mem;
3387 g_assert_not_reached ();
3392 ICALL_EXPORT MonoObject *
3393 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3401 domain = mono_object_domain (enumType);
3402 enumc = mono_class_from_mono_type (enumType->type);
3404 mono_class_init_checked (enumc, &error);
3405 mono_error_raise_exception (&error);
3407 etype = mono_class_enum_basetype (enumc);
3409 res = mono_object_new_checked (domain, enumc, &error);
3410 mono_error_raise_exception (&error);
3411 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3416 ICALL_EXPORT MonoBoolean
3417 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3419 int size = mono_class_value_size (a->vtable->klass, NULL);
3420 guint64 a_val = 0, b_val = 0;
3422 memcpy (&a_val, mono_object_unbox (a), size);
3423 memcpy (&b_val, mono_object_unbox (b), size);
3425 return (a_val & b_val) == b_val;
3428 ICALL_EXPORT MonoObject *
3429 ves_icall_System_Enum_get_value (MonoObject *eobj)
3441 g_assert (eobj->vtable->klass->enumtype);
3443 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3444 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3445 mono_error_raise_exception (&error);
3446 dst = (char *)res + sizeof (MonoObject);
3447 src = (char *)eobj + sizeof (MonoObject);
3448 size = mono_class_value_size (enumc, NULL);
3450 memcpy (dst, src, size);
3455 ICALL_EXPORT MonoReflectionType *
3456 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3459 MonoReflectionType *ret;
3463 klass = mono_class_from_mono_type (type->type);
3464 mono_class_init_checked (klass, &error);
3465 mono_error_raise_exception (&error);
3467 etype = mono_class_enum_basetype (klass);
3469 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3473 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3474 mono_error_raise_exception (&error);
3480 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3482 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3483 gpointer odata = (char *)other + sizeof (MonoObject);
3484 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3485 g_assert (basetype);
3490 if (eobj->vtable->klass != other->vtable->klass)
3493 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3494 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3495 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3498 return me > other ? 1 : -1; \
3501 switch (basetype->type) {
3503 COMPARE_ENUM_VALUES (guint8);
3505 COMPARE_ENUM_VALUES (gint8);
3506 case MONO_TYPE_CHAR:
3508 COMPARE_ENUM_VALUES (guint16);
3510 COMPARE_ENUM_VALUES (gint16);
3512 COMPARE_ENUM_VALUES (guint32);
3514 COMPARE_ENUM_VALUES (gint32);
3516 COMPARE_ENUM_VALUES (guint64);
3518 COMPARE_ENUM_VALUES (gint64);
3522 #undef COMPARE_ENUM_VALUES
3523 /* indicates that the enum was of an unsupported unerlying type */
3528 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3530 gpointer data = (char *)eobj + sizeof (MonoObject);
3531 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3532 g_assert (basetype);
3534 switch (basetype->type) {
3535 case MONO_TYPE_I1: {
3536 gint8 value = *((gint8*)data);
3537 return ((int)value ^ (int)value << 8);
3540 return *((guint8*)data);
3541 case MONO_TYPE_CHAR:
3543 return *((guint16*)data);
3545 case MONO_TYPE_I2: {
3546 gint16 value = *((gint16*)data);
3547 return ((int)(guint16)value | (((int)value) << 16));
3550 return *((guint32*)data);
3552 return *((gint32*)data);
3554 case MONO_TYPE_I8: {
3555 gint64 value = *((gint64*)data);
3556 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3559 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3564 ICALL_EXPORT MonoBoolean
3565 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3568 MonoDomain *domain = mono_object_domain (type);
3569 MonoClass *enumc = mono_class_from_mono_type (type->type);
3570 guint j = 0, nvalues;
3572 MonoClassField *field;
3574 guint64 field_value, previous_value = 0;
3575 gboolean sorted = TRUE;
3577 mono_class_init_checked (enumc, &error);
3578 mono_error_raise_exception (&error);
3580 if (!enumc->enumtype) {
3581 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3585 base_type = mono_class_enum_basetype (enumc)->type;
3587 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3588 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3589 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3592 while ((field = mono_class_get_fields (enumc, &iter))) {
3594 MonoTypeEnum def_type;
3596 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3598 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3600 if (mono_field_is_deleted (field))
3602 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3604 p = mono_class_get_field_default_value (field, &def_type);
3605 /* len = */ mono_metadata_decode_blob_size (p, &p);
3607 field_value = read_enum_value (p, base_type);
3608 mono_array_set (*values, guint64, j, field_value);
3610 if (previous_value > field_value)
3613 previous_value = field_value;
3621 BFLAGS_IgnoreCase = 1,
3622 BFLAGS_DeclaredOnly = 2,
3623 BFLAGS_Instance = 4,
3625 BFLAGS_Public = 0x10,
3626 BFLAGS_NonPublic = 0x20,
3627 BFLAGS_FlattenHierarchy = 0x40,
3628 BFLAGS_InvokeMethod = 0x100,
3629 BFLAGS_CreateInstance = 0x200,
3630 BFLAGS_GetField = 0x400,
3631 BFLAGS_SetField = 0x800,
3632 BFLAGS_GetProperty = 0x1000,
3633 BFLAGS_SetProperty = 0x2000,
3634 BFLAGS_ExactBinding = 0x10000,
3635 BFLAGS_SuppressChangeType = 0x20000,
3636 BFLAGS_OptionalParamBinding = 0x40000
3639 ICALL_EXPORT MonoArray*
3640 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3644 MonoClass *startklass, *klass, *refklass;
3649 char *utf8_name = NULL;
3650 int (*compare_func) (const char *s1, const char *s2) = NULL;
3651 MonoClassField *field;
3652 MonoPtrArray tmp_array;
3654 domain = ((MonoObject *)type)->vtable->domain;
3655 if (type->type->byref)
3656 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3658 klass = startklass = mono_class_from_mono_type (type->type);
3659 refklass = mono_class_from_mono_type (reftype->type);
3661 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3664 if (mono_class_has_failure (klass)) {
3665 mono_ptr_array_destroy (tmp_array);
3666 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3671 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3672 guint32 flags = mono_field_get_flags (field);
3674 if (mono_field_is_deleted_with_flags (field, flags))
3676 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3677 if (bflags & BFLAGS_Public)
3679 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3680 if (bflags & BFLAGS_NonPublic) {
3687 if (flags & FIELD_ATTRIBUTE_STATIC) {
3688 if (bflags & BFLAGS_Static)
3689 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3692 if (bflags & BFLAGS_Instance)
3700 if (utf8_name == NULL) {
3701 utf8_name = mono_string_to_utf8 (name);
3702 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3705 if (compare_func (mono_field_get_name (field), utf8_name))
3709 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3710 if (!mono_error_ok (&error))
3712 mono_ptr_array_append (tmp_array, member);
3714 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3717 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3719 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3720 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3722 mono_ptr_array_destroy (tmp_array);
3724 if (utf8_name != NULL)
3729 mono_ptr_array_destroy (tmp_array);
3730 mono_error_raise_exception (&error);
3731 g_assert_not_reached ();
3735 method_nonpublic (MonoMethod* method, gboolean start_klass)
3737 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3738 case METHOD_ATTRIBUTE_ASSEM:
3739 return (start_klass || mono_defaults.generic_ilist_class);
3740 case METHOD_ATTRIBUTE_PRIVATE:
3742 case METHOD_ATTRIBUTE_PUBLIC:
3750 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3753 MonoClass *startklass;
3757 /*FIXME, use MonoBitSet*/
3758 guint32 method_slots_default [8];
3759 guint32 *method_slots = NULL;
3760 int (*compare_func) (const char *s1, const char *s2) = NULL;
3762 array = g_ptr_array_new ();
3767 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3769 /* An optimization for calls made from Delegate:CreateDelegate () */
3770 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3771 method = mono_get_delegate_invoke (klass);
3772 if (mono_loader_get_last_error ())
3775 g_ptr_array_add (array, method);
3779 mono_class_setup_methods (klass);
3780 mono_class_setup_vtable (klass);
3781 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3784 if (is_generic_parameter (&klass->byval_arg))
3785 nslots = mono_class_get_vtable_size (klass->parent);
3787 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3788 if (nslots >= sizeof (method_slots_default) * 8) {
3789 method_slots = g_new0 (guint32, nslots / 32 + 1);
3791 method_slots = method_slots_default;
3792 memset (method_slots, 0, sizeof (method_slots_default));
3795 mono_class_setup_methods (klass);
3796 mono_class_setup_vtable (klass);
3797 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3801 while ((method = mono_class_get_methods (klass, &iter))) {
3803 if (method->slot != -1) {
3804 g_assert (method->slot < nslots);
3805 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3807 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3808 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3811 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3813 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3814 if (bflags & BFLAGS_Public)
3816 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3822 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3823 if (bflags & BFLAGS_Static)
3824 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3827 if (bflags & BFLAGS_Instance)
3835 if (compare_func (name, method->name))
3840 g_ptr_array_add (array, method);
3842 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3844 if (method_slots != method_slots_default)
3845 g_free (method_slots);
3850 if (method_slots != method_slots_default)
3851 g_free (method_slots);
3852 g_ptr_array_free (array, TRUE);
3854 if (mono_class_has_failure (klass)) {
3855 *ex = mono_class_get_exception_for_failure (klass);
3857 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3858 mono_loader_clear_error ();
3863 ICALL_EXPORT MonoArray*
3864 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3866 static MonoClass *MethodInfo_array;
3870 MonoVTable *array_vtable;
3871 MonoException *ex = NULL;
3872 const char *mname = NULL;
3873 GPtrArray *method_array;
3874 MonoClass *klass, *refklass;
3877 mono_error_init (&error);
3879 if (!MethodInfo_array) {
3880 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3881 mono_memory_barrier ();
3882 MethodInfo_array = klass;
3885 klass = mono_class_from_mono_type (type->type);
3886 refklass = mono_class_from_mono_type (reftype->type);
3887 domain = ((MonoObject *)type)->vtable->domain;
3888 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3889 if (!is_ok (&error)) {
3890 mono_error_set_pending_exception (&error);
3893 if (type->type->byref) {
3894 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3895 mono_error_set_pending_exception (&error);
3901 mname = mono_string_to_utf8 (name);
3903 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3904 g_free ((char*)mname);
3906 mono_set_pending_exception (ex);
3910 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3911 if (!mono_error_ok (&error)) {
3912 mono_error_set_pending_exception (&error);
3916 for (i = 0; i < method_array->len; ++i) {
3917 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3918 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3919 if (!mono_error_ok (&error))
3921 mono_array_setref (res, i, rm);
3925 g_ptr_array_free (method_array, TRUE);
3926 if (!mono_error_ok (&error))
3927 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3931 ICALL_EXPORT MonoArray*
3932 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3935 MonoClass *startklass, *klass, *refklass;
3940 gpointer iter = NULL;
3941 MonoPtrArray tmp_array;
3944 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3946 domain = ((MonoObject *)type)->vtable->domain;
3947 if (type->type->byref)
3948 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3949 klass = startklass = mono_class_from_mono_type (type->type);
3950 refklass = mono_class_from_mono_type (reftype->type);
3952 mono_class_setup_methods (klass);
3953 if (mono_class_has_failure (klass)) {
3954 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3959 while ((method = mono_class_get_methods (klass, &iter))) {
3961 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3963 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3964 if (bflags & BFLAGS_Public)
3967 if (bflags & BFLAGS_NonPublic)
3973 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3974 if (bflags & BFLAGS_Static)
3975 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3978 if (bflags & BFLAGS_Instance)
3984 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3985 if (!mono_error_ok (&error)) {
3986 mono_error_set_pending_exception (&error);
3990 mono_ptr_array_append (tmp_array, member);
3993 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
3995 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3996 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3998 mono_ptr_array_destroy (tmp_array);
4004 property_hash (gconstpointer data)
4006 MonoProperty *prop = (MonoProperty*)data;
4008 return g_str_hash (prop->name);
4012 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
4014 if (method1->is_inflated)
4015 method1 = ((MonoMethodInflated*) method1)->declaring;
4016 if (method2->is_inflated)
4017 method2 = ((MonoMethodInflated*) method2)->declaring;
4019 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4023 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4025 // Properties are hide-by-name-and-signature
4026 if (!g_str_equal (prop1->name, prop2->name))
4029 /* If we see a property in a generic method, we want to
4030 compare the generic signatures, not the inflated signatures
4031 because we might conflate two properties that were
4035 public T this[T t] { getter { return t; } } // method 1
4036 public U this[U u] { getter { return u; } } // method 2
4039 If we see int Foo<int,int>::Item[int] we need to know if
4040 the indexer came from method 1 or from method 2, and we
4041 shouldn't conflate them. (Bugzilla 36283)
4043 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
4046 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4053 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4058 return method_nonpublic (accessor, start_klass);
4061 ICALL_EXPORT MonoArray*
4062 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4066 MonoClass *startklass, *klass;
4072 gchar *propname = NULL;
4073 int (*compare_func) (const char *s1, const char *s2) = NULL;
4075 GHashTable *properties = NULL;
4076 MonoPtrArray tmp_array;
4078 mono_error_init (&error);
4080 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4082 domain = ((MonoObject *)type)->vtable->domain;
4083 if (type->type->byref)
4084 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
4085 klass = startklass = mono_class_from_mono_type (type->type);
4088 propname = mono_string_to_utf8 (name);
4089 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4092 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4094 mono_class_setup_methods (klass);
4095 mono_class_setup_vtable (klass);
4096 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4100 while ((prop = mono_class_get_properties (klass, &iter))) {
4106 flags = method->flags;
4109 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4110 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4111 if (bflags & BFLAGS_Public)
4113 } else if (bflags & BFLAGS_NonPublic) {
4114 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4115 property_accessor_nonpublic(prop->set, startklass == klass)) {
4122 if (flags & METHOD_ATTRIBUTE_STATIC) {
4123 if (bflags & BFLAGS_Static)
4124 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4127 if (bflags & BFLAGS_Instance)
4136 if (compare_func (propname, prop->name))
4140 if (g_hash_table_lookup (properties, prop))
4143 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4146 mono_ptr_array_append (tmp_array, pr);
4148 g_hash_table_insert (properties, prop, prop);
4150 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4153 g_hash_table_destroy (properties);
4156 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4157 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4158 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4160 mono_ptr_array_destroy (tmp_array);
4167 if (mono_class_has_failure (klass)) {
4168 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4170 mono_error_set_from_loader_error (&error);
4171 mono_loader_clear_error ();
4176 g_hash_table_destroy (properties);
4179 mono_ptr_array_destroy (tmp_array);
4181 mono_error_set_pending_exception (&error);
4187 event_hash (gconstpointer data)
4189 MonoEvent *event = (MonoEvent*)data;
4191 return g_str_hash (event->name);
4195 event_equal (MonoEvent *event1, MonoEvent *event2)
4197 // Events are hide-by-name
4198 return g_str_equal (event1->name, event2->name);
4201 ICALL_EXPORT MonoArray*
4202 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4206 MonoClass *startklass, *klass;
4212 char *utf8_name = NULL;
4213 int (*compare_func) (const char *s1, const char *s2) = NULL;
4214 GHashTable *events = NULL;
4215 MonoPtrArray tmp_array;
4217 mono_error_init (&error);
4219 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4221 domain = mono_object_domain (type);
4222 if (type->type->byref)
4223 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4224 klass = startklass = mono_class_from_mono_type (type->type);
4226 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4228 mono_class_setup_methods (klass);
4229 mono_class_setup_vtable (klass);
4230 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4234 while ((event = mono_class_get_events (klass, &iter))) {
4236 method = event->add;
4238 method = event->remove;
4240 method = event->raise;
4242 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4243 if (bflags & BFLAGS_Public)
4245 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4246 if (bflags & BFLAGS_NonPublic)
4251 if (bflags & BFLAGS_NonPublic)
4257 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4258 if (bflags & BFLAGS_Static)
4259 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4262 if (bflags & BFLAGS_Instance)
4267 if (bflags & BFLAGS_Instance)
4273 if (utf8_name == NULL) {
4274 utf8_name = mono_string_to_utf8 (name);
4275 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4278 if (compare_func (event->name, utf8_name))
4282 if (g_hash_table_lookup (events, event))
4285 MonoReflectionEvent *ev_obj;
4286 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4289 mono_ptr_array_append (tmp_array, ev_obj);
4291 g_hash_table_insert (events, event, event);
4293 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4296 g_hash_table_destroy (events);
4298 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4300 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4301 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4303 mono_ptr_array_destroy (tmp_array);
4305 if (utf8_name != NULL)
4311 if (mono_class_has_failure (klass)) {
4312 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4314 mono_error_set_from_loader_error (&error);
4315 mono_loader_clear_error ();
4321 g_hash_table_destroy (events);
4322 if (utf8_name != NULL)
4325 mono_ptr_array_destroy (tmp_array);
4327 mono_error_set_pending_exception (&error);
4331 ICALL_EXPORT MonoArray*
4332 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4335 MonoReflectionType *rt;
4343 MonoPtrArray tmp_array;
4345 domain = ((MonoObject *)type)->vtable->domain;
4346 if (type->type->byref)
4347 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4348 klass = mono_class_from_mono_type (type->type);
4351 * If a nested type is generic, return its generic type definition.
4352 * Note that this means that the return value is essentially the set
4353 * of nested types of the generic type definition of @klass.
4355 * A note in MSDN claims that a generic type definition can have
4356 * nested types that aren't generic. In any case, the container of that
4357 * nested type would be the generic type definition.
4359 if (klass->generic_class)
4360 klass = klass->generic_class->container_class;
4362 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4364 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4366 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4367 if (bflags & BFLAGS_Public)
4370 if (bflags & BFLAGS_NonPublic)
4378 str = mono_string_to_utf8 (name);
4379 mono_identifier_unescape_type_name_chars (str);
4382 if (strcmp (nested->name, str))
4386 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4387 mono_error_raise_exception (&error);
4389 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4392 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4394 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4395 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4397 mono_ptr_array_destroy (tmp_array);
4404 ICALL_EXPORT MonoReflectionType*
4405 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4408 MonoReflectionType *ret;
4410 MonoType *type = NULL;
4411 MonoTypeNameParse info;
4412 gboolean type_resolve;
4414 /* On MS.NET, this does not fire a TypeResolve event */
4415 type_resolve = TRUE;
4416 str = mono_string_to_utf8 (name);
4417 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4418 if (!mono_reflection_parse_type (str, &info)) {
4420 mono_reflection_free_type_info (&info);
4422 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4425 /*g_print ("failed parse\n");*/
4429 if (info.assembly.name) {
4431 mono_reflection_free_type_info (&info);
4433 /* 1.0 and 2.0 throw different exceptions */
4434 if (mono_defaults.generic_ilist_class)
4435 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4437 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4443 if (module != NULL) {
4444 if (module->image) {
4445 type = mono_reflection_get_type_checked (module->image, &info, ignoreCase, &type_resolve, &error);
4446 if (!is_ok (&error)) {
4448 mono_reflection_free_type_info (&info);
4449 mono_error_set_pending_exception (&error);
4456 if (assembly_is_dynamic (assembly->assembly)) {
4457 /* Enumerate all modules */
4458 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4462 if (abuilder->modules) {
4463 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4464 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4465 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4466 if (!is_ok (&error)) {
4468 mono_reflection_free_type_info (&info);
4469 mono_error_set_pending_exception (&error);
4477 if (!type && abuilder->loaded_modules) {
4478 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4479 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4480 type = mono_reflection_get_type_checked (mod->image, &info, ignoreCase, &type_resolve, &error);
4481 if (!is_ok (&error)) {
4483 mono_reflection_free_type_info (&info);
4484 mono_error_set_pending_exception (&error);
4493 type = mono_reflection_get_type_checked (assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4494 if (!is_ok (&error)) {
4496 mono_reflection_free_type_info (&info);
4497 mono_error_set_pending_exception (&error);
4502 mono_reflection_free_type_info (&info);
4504 MonoException *e = NULL;
4507 e = mono_get_exception_type_load (name, NULL);
4509 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4510 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4512 mono_loader_clear_error ();
4515 mono_set_pending_exception (e);
4517 } else if (mono_loader_get_last_error ()) {
4519 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4522 mono_loader_clear_error ();
4525 if (type->type == MONO_TYPE_CLASS) {
4526 MonoClass *klass = mono_type_get_class (type);
4528 /* need to report exceptions ? */
4529 if (throwOnError && mono_class_has_failure (klass)) {
4530 /* report SecurityException (or others) that occured when loading the assembly */
4531 MonoException *exc = mono_class_get_exception_for_failure (klass);
4532 mono_loader_clear_error ();
4533 mono_set_pending_exception (exc);
4538 /* g_print ("got it\n"); */
4539 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4540 mono_error_set_pending_exception (&error);
4546 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4549 gchar *shadow_ini_file;
4552 /* Check for shadow-copied assembly */
4553 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4554 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4556 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4557 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4563 g_free (shadow_ini_file);
4564 if (content != NULL) {
4567 *filename = content;
4574 ICALL_EXPORT MonoString *
4575 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4577 MonoDomain *domain = mono_object_domain (assembly);
4578 MonoAssembly *mass = assembly->assembly;
4579 MonoString *res = NULL;
4584 if (g_path_is_absolute (mass->image->name)) {
4585 absolute = g_strdup (mass->image->name);
4586 dirname = g_path_get_dirname (absolute);
4588 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4589 dirname = g_strdup (mass->basedir);
4592 replace_shadow_path (domain, dirname, &absolute);
4597 for (i = strlen (absolute) - 1; i >= 0; i--)
4598 if (absolute [i] == '\\')
4603 uri = g_filename_to_uri (absolute, NULL, NULL);
4605 const char *prepend = "file://";
4607 if (*absolute == '/' && *(absolute + 1) == '/') {
4610 prepend = "file:///";
4613 uri = g_strconcat (prepend, absolute, NULL);
4617 res = mono_string_new (domain, uri);
4624 ICALL_EXPORT MonoBoolean
4625 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4627 MonoAssembly *mass = assembly->assembly;
4629 return mass->in_gac;
4632 ICALL_EXPORT MonoReflectionAssembly*
4633 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4638 MonoImageOpenStatus status;
4639 MonoReflectionAssembly* result = NULL;
4641 name = mono_string_to_utf8 (mname);
4642 res = mono_assembly_load_with_partial_name (name, &status);
4648 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4650 mono_error_set_pending_exception (&error);
4654 ICALL_EXPORT MonoString *
4655 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4657 MonoDomain *domain = mono_object_domain (assembly);
4660 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4665 ICALL_EXPORT MonoBoolean
4666 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4668 return assembly->assembly->ref_only;
4671 ICALL_EXPORT MonoString *
4672 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4674 MonoDomain *domain = mono_object_domain (assembly);
4676 return mono_string_new (domain, assembly->assembly->image->version);
4679 ICALL_EXPORT MonoReflectionMethod*
4680 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4683 MonoReflectionMethod *res = NULL;
4686 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4690 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4691 if (!mono_error_ok (&error))
4694 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4697 if (!mono_error_ok (&error))
4698 mono_error_set_pending_exception (&error);
4702 ICALL_EXPORT MonoReflectionModule*
4703 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4706 MonoReflectionModule *result = NULL;
4707 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4708 if (!mono_error_ok (&error))
4709 mono_error_set_pending_exception (&error);
4713 ICALL_EXPORT MonoArray*
4714 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4716 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4717 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4721 for (i = 0; i < table->rows; ++i) {
4722 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4723 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4729 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4731 static MonoMethod *create_version = NULL;
4735 mono_error_init (error);
4738 if (!create_version) {
4739 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4740 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4741 g_assert (create_version);
4742 mono_method_desc_free (desc);
4748 args [3] = &revision;
4749 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4750 return_val_if_nok (error, NULL);
4752 mono_runtime_invoke_checked (create_version, result, args, error);
4753 return_val_if_nok (error, NULL);
4758 ICALL_EXPORT MonoArray*
4759 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4763 MonoDomain *domain = mono_object_domain (assembly);
4765 static MonoMethod *create_culture = NULL;
4766 MonoImage *image = assembly->assembly->image;
4770 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4773 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4775 if (count > 0 && !create_culture) {
4776 MonoMethodDesc *desc = mono_method_desc_new (
4777 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4778 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4779 g_assert (create_culture);
4780 mono_method_desc_free (desc);
4783 for (i = 0; i < count; i++) {
4784 MonoObject *version;
4785 MonoReflectionAssemblyName *aname;
4786 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4788 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4790 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4791 domain, mono_class_get_assembly_name_class (), &error);
4792 mono_error_raise_exception (&error);
4794 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4796 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4797 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4798 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4799 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4800 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4801 aname->versioncompat = 1; /* SameMachine (default) */
4802 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4804 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4805 mono_error_raise_exception (&error);
4807 MONO_OBJECT_SETREF (aname, version, version);
4809 if (create_culture) {
4811 MonoBoolean assembly_ref = 1;
4812 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4813 args [1] = &assembly_ref;
4815 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4816 mono_error_raise_exception (&error);
4818 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4821 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4822 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4823 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4825 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4826 /* public key token isn't copied - the class library will
4827 automatically generate it from the public key if required */
4828 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4829 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4831 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4832 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4835 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4838 /* note: this function doesn't return the codebase on purpose (i.e. it can
4839 be used under partial trust as path information isn't present). */
4841 mono_array_setref (result, i, aname);
4846 /* move this in some file in mono/util/ */
4848 g_concat_dir_and_file (const char *dir, const char *file)
4850 g_return_val_if_fail (dir != NULL, NULL);
4851 g_return_val_if_fail (file != NULL, NULL);
4854 * If the directory name doesn't have a / on the end, we need
4855 * to add one so we get a proper path to the file
4857 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4858 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4860 return g_strconcat (dir, file, NULL);
4864 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4867 char *n = mono_string_to_utf8 (name);
4868 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4870 guint32 cols [MONO_MANIFEST_SIZE];
4871 guint32 impl, file_idx;
4875 for (i = 0; i < table->rows; ++i) {
4876 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4877 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4878 if (strcmp (val, n) == 0)
4882 if (i == table->rows)
4885 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4888 * this code should only be called after obtaining the
4889 * ResourceInfo and handling the other cases.
4891 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4892 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4894 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4899 module = assembly->assembly->image;
4902 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4903 mono_error_raise_exception (&error);
4904 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4906 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4909 ICALL_EXPORT gboolean
4910 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4913 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4915 guint32 cols [MONO_MANIFEST_SIZE];
4916 guint32 file_cols [MONO_FILE_SIZE];
4920 n = mono_string_to_utf8 (name);
4921 for (i = 0; i < table->rows; ++i) {
4922 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4923 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4924 if (strcmp (val, n) == 0)
4928 if (i == table->rows)
4931 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4932 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4935 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4936 case MONO_IMPLEMENTATION_FILE:
4937 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4938 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4939 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4940 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4941 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4942 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4945 info->location = RESOURCE_LOCATION_EMBEDDED;
4948 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4949 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4950 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4951 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4952 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4953 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4955 mono_set_pending_exception (ex);
4958 MonoReflectionAssembly *assm_obj;
4959 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4961 mono_error_set_pending_exception (&error);
4964 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4966 /* Obtain info recursively */
4967 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4968 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4971 case MONO_IMPLEMENTATION_EXP_TYPE:
4972 g_assert_not_reached ();
4980 ICALL_EXPORT MonoObject*
4981 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4983 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4984 MonoArray *result = NULL;
4989 /* check hash if needed */
4991 n = mono_string_to_utf8 (name);
4992 for (i = 0; i < table->rows; ++i) {
4993 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4994 if (strcmp (val, n) == 0) {
4997 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4998 fn = mono_string_new (mono_object_domain (assembly), n);
5000 return (MonoObject*)fn;
5008 for (i = 0; i < table->rows; ++i) {
5009 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5013 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
5016 for (i = 0; i < table->rows; ++i) {
5017 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5018 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5019 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5020 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5025 return (MonoObject*)result;
5028 ICALL_EXPORT MonoArray*
5029 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5032 MonoDomain *domain = mono_domain_get();
5035 int i, j, file_count = 0;
5036 MonoImage **modules;
5037 guint32 module_count, real_module_count;
5038 MonoTableInfo *table;
5039 guint32 cols [MONO_FILE_SIZE];
5040 MonoImage *image = assembly->assembly->image;
5042 g_assert (image != NULL);
5043 g_assert (!assembly_is_dynamic (assembly->assembly));
5045 table = &image->tables [MONO_TABLE_FILE];
5046 file_count = table->rows;
5048 modules = image->modules;
5049 module_count = image->module_count;
5051 real_module_count = 0;
5052 for (i = 0; i < module_count; ++i)
5054 real_module_count ++;
5056 klass = mono_class_get_module_class ();
5057 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
5059 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5060 mono_error_raise_exception (&error);
5061 mono_array_setref (res, 0, image_obj);
5063 for (i = 0; i < module_count; ++i)
5065 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5066 mono_error_raise_exception (&error);
5067 mono_array_setref (res, j, rm);
5071 for (i = 0; i < file_count; ++i, ++j) {
5072 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5073 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5074 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5075 mono_error_raise_exception (&error);
5076 mono_array_setref (res, j, rm);
5079 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5081 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5082 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5085 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5086 mono_error_raise_exception (&error);
5087 mono_array_setref (res, j, rm);
5094 ICALL_EXPORT MonoReflectionMethod*
5095 ves_icall_GetCurrentMethod (void)
5097 MonoReflectionMethod *res = NULL;
5100 MonoMethod *m = mono_method_get_last_managed ();
5103 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5107 while (m->is_inflated)
5108 m = ((MonoMethodInflated*)m)->declaring;
5110 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5111 mono_error_raise_exception (&error);
5117 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5120 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5123 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5124 //method is inflated, we should inflate it on the other class
5125 MonoGenericContext ctx;
5126 ctx.method_inst = inflated->context.method_inst;
5127 ctx.class_inst = inflated->context.class_inst;
5128 if (klass->generic_class)
5129 ctx.class_inst = klass->generic_class->context.class_inst;
5130 else if (klass->generic_container)
5131 ctx.class_inst = klass->generic_container->context.class_inst;
5132 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5133 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5137 mono_class_setup_methods (method->klass);
5138 if (mono_class_has_failure (method->klass))
5140 for (i = 0; i < method->klass->method.count; ++i) {
5141 if (method->klass->methods [i] == method) {
5146 mono_class_setup_methods (klass);
5147 if (mono_class_has_failure (klass))
5149 g_assert (offset >= 0 && offset < klass->method.count);
5150 return klass->methods [offset];
5153 ICALL_EXPORT MonoReflectionMethod*
5154 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5156 MonoReflectionMethod *res = NULL;
5160 klass = mono_class_from_mono_type (type);
5161 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5163 if (method->klass != klass) {
5164 method = mono_method_get_equivalent_method (method, klass);
5169 klass = method->klass;
5170 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5171 mono_error_raise_exception (&error);
5175 ICALL_EXPORT MonoReflectionMethodBody*
5176 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5179 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5180 mono_error_set_pending_exception (&error);
5184 ICALL_EXPORT MonoReflectionAssembly*
5185 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5188 MonoReflectionAssembly *result;
5189 MonoMethod *dest = NULL;
5191 mono_stack_walk_no_il (get_executing, &dest);
5193 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5195 mono_error_set_pending_exception (&error);
5200 ICALL_EXPORT MonoReflectionAssembly*
5201 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5204 MonoReflectionAssembly *result;
5205 MonoDomain* domain = mono_domain_get ();
5207 if (!domain->entry_assembly)
5210 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5212 mono_error_set_pending_exception (&error);
5216 ICALL_EXPORT MonoReflectionAssembly*
5217 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5222 MonoReflectionAssembly *result;
5225 mono_stack_walk_no_il (get_executing, &dest);
5227 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5231 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5234 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5236 mono_error_set_pending_exception (&error);
5240 ICALL_EXPORT MonoString *
5241 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5242 gboolean assembly_qualified)
5244 MonoDomain *domain = mono_object_domain (object);
5245 MonoTypeNameFormat format;
5250 format = assembly_qualified ?
5251 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5252 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5254 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5256 name = mono_type_get_name_full (object->type, format);
5260 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5265 res = mono_string_new (domain, name);
5272 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5275 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5277 mono_class_init_checked (klass, &error);
5278 mono_error_raise_exception (&error);
5279 return mono_security_core_clr_class_level (klass);
5283 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5285 MonoClassField *field = rfield->field;
5286 return mono_security_core_clr_field_level (field, TRUE);
5290 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5292 MonoMethod *method = rfield->method;
5293 return mono_security_core_clr_method_level (method, TRUE);
5297 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)
5299 static MonoMethod *create_culture = NULL;
5303 const char *pkey_ptr;
5305 MonoBoolean assembly_ref = 0;
5307 mono_error_init (error);
5309 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5310 aname->major = name->major;
5311 aname->minor = name->minor;
5312 aname->build = name->build;
5313 aname->flags = name->flags;
5314 aname->revision = name->revision;
5315 aname->hashalg = name->hash_alg;
5316 aname->versioncompat = 1; /* SameMachine (default) */
5317 aname->processor_architecture = name->arch;
5319 if (by_default_version) {
5320 MonoObject *version;
5322 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5323 return_if_nok (error);
5325 MONO_OBJECT_SETREF (aname, version, version);
5329 if (absolute != NULL && *absolute != '\0') {
5330 const gchar *prepend = "file://";
5333 codebase = g_strdup (absolute);
5338 for (i = strlen (codebase) - 1; i >= 0; i--)
5339 if (codebase [i] == '\\')
5342 if (*codebase == '/' && *(codebase + 1) == '/') {
5345 prepend = "file:///";
5349 result = g_strconcat (prepend, codebase, NULL);
5355 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5359 if (!create_culture) {
5360 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5361 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5362 g_assert (create_culture);
5363 mono_method_desc_free (desc);
5366 if (name->culture) {
5367 args [0] = mono_string_new (domain, name->culture);
5368 args [1] = &assembly_ref;
5370 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5371 return_if_nok (error);
5373 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5376 if (name->public_key) {
5377 pkey_ptr = (char*)name->public_key;
5378 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5380 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5381 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5382 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5383 } else if (default_publickey) {
5384 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5385 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5388 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5389 if (name->public_key_token [0]) {
5393 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5394 p = mono_array_addr (aname->keyToken, char, 0);
5396 for (i = 0, j = 0; i < 8; i++) {
5397 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5398 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5401 } else if (default_token) {
5402 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5406 ICALL_EXPORT MonoString *
5407 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5409 MonoDomain *domain = mono_object_domain (assembly);
5410 MonoAssembly *mass = assembly->assembly;
5414 name = mono_stringify_assembly_name (&mass->aname);
5415 res = mono_string_new (domain, name);
5422 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5426 MonoAssembly *mass = assembly->assembly;
5428 if (g_path_is_absolute (mass->image->name)) {
5429 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5430 mono_error_set_pending_exception (&error);
5433 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5435 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5436 mono_error_set_pending_exception (&error);
5442 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5446 MonoImageOpenStatus status = MONO_IMAGE_OK;
5449 MonoAssemblyName name;
5452 filename = mono_string_to_utf8 (fname);
5454 dirname = g_path_get_dirname (filename);
5455 replace_shadow_path (mono_domain_get (), dirname, &filename);
5458 image = mono_image_open (filename, &status);
5464 if (status == MONO_IMAGE_IMAGE_INVALID)
5465 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5467 exc = mono_get_exception_file_not_found2 (NULL, fname);
5468 mono_set_pending_exception (exc);
5472 res = mono_assembly_fill_assembly_name (image, &name);
5474 mono_image_close (image);
5476 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5480 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5481 mono_error_set_pending_exception (&error);
5483 mono_image_close (image);
5487 ICALL_EXPORT MonoBoolean
5488 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5489 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5491 MonoBoolean result = FALSE;
5492 MonoDeclSecurityEntry entry;
5494 /* SecurityAction.RequestMinimum */
5495 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5496 *minimum = entry.blob;
5497 *minLength = entry.size;
5500 /* SecurityAction.RequestOptional */
5501 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5502 *optional = entry.blob;
5503 *optLength = entry.size;
5506 /* SecurityAction.RequestRefuse */
5507 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5508 *refused = entry.blob;
5509 *refLength = entry.size;
5517 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5519 guint32 attrs, visibility;
5521 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5522 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5523 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5526 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5532 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5534 MonoReflectionType *rt;
5537 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5540 mono_error_init (error);
5542 /* we start the count from 1 because we skip the special type <Module> */
5545 for (i = 1; i < tdef->rows; ++i) {
5546 if (mono_module_type_is_visible (tdef, image, i + 1))
5550 count = tdef->rows - 1;
5552 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5553 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5555 for (i = 1; i < tdef->rows; ++i) {
5556 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5557 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5558 mono_loader_assert_no_error (); /* Plug any leaks */
5561 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5562 return_val_if_nok (error, NULL);
5564 mono_array_setref (res, count, rt);
5566 MonoException *ex = mono_error_convert_to_exception (error);
5567 mono_array_setref (*exceptions, count, ex);
5576 ICALL_EXPORT MonoArray*
5577 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5580 MonoArray *res = NULL;
5581 MonoArray *exceptions = NULL;
5582 MonoImage *image = NULL;
5583 MonoTableInfo *table = NULL;
5586 int i, len, ex_count;
5588 domain = mono_object_domain (assembly);
5590 g_assert (!assembly_is_dynamic (assembly->assembly));
5591 image = assembly->assembly->image;
5592 table = &image->tables [MONO_TABLE_FILE];
5593 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5594 mono_error_raise_exception (&error);
5596 /* Append data from all modules in the assembly */
5597 for (i = 0; i < table->rows; ++i) {
5598 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5599 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5604 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5605 mono_error_raise_exception (&error);
5607 /* Append the new types to the end of the array */
5608 if (mono_array_length (res2) > 0) {
5610 MonoArray *res3, *ex3;
5612 len1 = mono_array_length (res);
5613 len2 = mono_array_length (res2);
5615 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5616 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5617 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5620 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5621 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5622 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5629 /* the ReflectionTypeLoadException must have all the types (Types property),
5630 * NULL replacing types which throws an exception. The LoaderException must
5631 * contain all exceptions for NULL items.
5634 len = mono_array_length (res);
5637 for (i = 0; i < len; i++) {
5638 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5642 klass = mono_type_get_class (t->type);
5643 if ((klass != NULL) && mono_class_has_failure (klass)) {
5644 /* keep the class in the list */
5645 list = g_list_append (list, klass);
5646 /* and replace Type with NULL */
5647 mono_array_setref (res, i, NULL);
5654 if (list || ex_count) {
5656 MonoException *exc = NULL;
5657 MonoArray *exl = NULL;
5658 int j, length = g_list_length (list) + ex_count;
5660 mono_loader_clear_error ();
5662 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5663 /* Types for which mono_class_get_checked () succeeded */
5664 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5665 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5666 mono_array_setref (exl, i, exc);
5668 /* Types for which it don't */
5669 for (j = 0; j < mono_array_length (exceptions); ++j) {
5670 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5672 g_assert (i < length);
5673 mono_array_setref (exl, i, exc);
5680 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5681 if (!is_ok (&error)) {
5682 mono_error_set_pending_exception (&error);
5685 mono_loader_clear_error ();
5686 mono_set_pending_exception (exc);
5693 ICALL_EXPORT gboolean
5694 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5697 MonoAssemblyName aname;
5698 MonoDomain *domain = mono_object_domain (name);
5700 gboolean is_version_defined;
5701 gboolean is_token_defined;
5703 aname.public_key = NULL;
5704 val = mono_string_to_utf8 (assname);
5705 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5706 g_free ((guint8*) aname.public_key);
5711 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5712 mono_error_set_pending_exception (&error);
5714 mono_assembly_name_free (&aname);
5715 g_free ((guint8*) aname.public_key);
5721 ICALL_EXPORT MonoReflectionType*
5722 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5725 MonoReflectionType *ret;
5726 MonoDomain *domain = mono_object_domain (module);
5729 g_assert (module->image);
5731 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5732 /* These images do not have a global type */
5735 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5736 if (!mono_error_ok (&error)) {
5737 mono_error_set_pending_exception (&error);
5741 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5742 if (!mono_error_ok (&error)) {
5743 mono_error_set_pending_exception (&error);
5751 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5753 /*if (module->image)
5754 mono_image_close (module->image);*/
5757 ICALL_EXPORT MonoString*
5758 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5760 MonoDomain *domain = mono_object_domain (module);
5762 g_assert (module->image);
5763 return mono_string_new (domain, module->image->guid);
5766 ICALL_EXPORT gpointer
5767 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5770 if (module->image && module->image->is_module_handle)
5771 return module->image->raw_data;
5774 return (gpointer) (-1);
5778 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5780 if (image_is_dynamic (image)) {
5781 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5782 *pe_kind = dyn->pe_kind;
5783 *machine = dyn->machine;
5786 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5787 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5792 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5794 return (image->md_version_major << 16) | (image->md_version_minor);
5797 ICALL_EXPORT MonoArray*
5798 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5801 MonoArray *exceptions;
5805 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5809 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5810 mono_error_raise_exception (&error);
5812 for (i = 0; i < mono_array_length (exceptions); ++i) {
5813 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5815 mono_set_pending_exception (ex);
5824 mono_memberref_is_method (MonoImage *image, guint32 token)
5826 if (!image_is_dynamic (image)) {
5827 guint32 cols [MONO_MEMBERREF_SIZE];
5829 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5830 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5831 mono_metadata_decode_blob_size (sig, &sig);
5832 return (*sig != 0x6);
5835 MonoClass *handle_class;
5837 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5838 mono_error_cleanup (&error); /* just probing, ignore error */
5842 return mono_defaults.methodhandle_class == handle_class;
5847 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5850 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5851 mono_array_addr (type_args, MonoType*, 0));
5853 context->class_inst = NULL;
5855 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5856 mono_array_addr (method_args, MonoType*, 0));
5858 context->method_inst = NULL;
5861 ICALL_EXPORT MonoType*
5862 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5865 int table = mono_metadata_token_table (token);
5866 int index = mono_metadata_token_index (token);
5867 MonoGenericContext context;
5870 *resolve_error = ResolveTokenError_Other;
5872 /* Validate token */
5873 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5874 (table != MONO_TABLE_TYPESPEC)) {
5875 *resolve_error = ResolveTokenError_BadTable;
5879 if (image_is_dynamic (image)) {
5880 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5881 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5882 mono_error_cleanup (&error);
5883 return klass ? &klass->byval_arg : NULL;
5886 init_generic_context_from_args (&context, type_args, method_args);
5887 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5888 mono_error_cleanup (&error);
5889 return klass ? &klass->byval_arg : NULL;
5892 if ((index <= 0) || (index > image->tables [table].rows)) {
5893 *resolve_error = ResolveTokenError_OutOfRange;
5897 init_generic_context_from_args (&context, type_args, method_args);
5898 klass = mono_class_get_checked (image, token, &error);
5900 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5901 if (!mono_error_ok (&error)) {
5902 mono_error_set_pending_exception (&error);
5907 return &klass->byval_arg;
5912 ICALL_EXPORT MonoMethod*
5913 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5916 int table = mono_metadata_token_table (token);
5917 int index = mono_metadata_token_index (token);
5918 MonoGenericContext context;
5921 *resolve_error = ResolveTokenError_Other;
5923 /* Validate token */
5924 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5925 (table != MONO_TABLE_MEMBERREF)) {
5926 *resolve_error = ResolveTokenError_BadTable;
5930 if (image_is_dynamic (image)) {
5931 if (table == MONO_TABLE_METHOD) {
5932 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5933 mono_error_cleanup (&error);
5937 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5938 *resolve_error = ResolveTokenError_BadTable;
5942 init_generic_context_from_args (&context, type_args, method_args);
5943 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5944 mono_error_cleanup (&error);
5948 if ((index <= 0) || (index > image->tables [table].rows)) {
5949 *resolve_error = ResolveTokenError_OutOfRange;
5952 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5953 *resolve_error = ResolveTokenError_BadTable;
5957 init_generic_context_from_args (&context, type_args, method_args);
5958 method = mono_get_method_checked (image, token, NULL, &context, &error);
5959 mono_error_set_pending_exception (&error);
5964 ICALL_EXPORT MonoString*
5965 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5968 int index = mono_metadata_token_index (token);
5970 *resolve_error = ResolveTokenError_Other;
5972 /* Validate token */
5973 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5974 *resolve_error = ResolveTokenError_BadTable;
5978 if (image_is_dynamic (image)) {
5979 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5980 mono_error_cleanup (&error);
5984 if ((index <= 0) || (index >= image->heap_us.size)) {
5985 *resolve_error = ResolveTokenError_OutOfRange;
5989 /* FIXME: What to do if the index points into the middle of a string ? */
5991 return mono_ldstr (mono_domain_get (), image, index);
5994 ICALL_EXPORT MonoClassField*
5995 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5999 int table = mono_metadata_token_table (token);
6000 int index = mono_metadata_token_index (token);
6001 MonoGenericContext context;
6002 MonoClassField *field;
6004 *resolve_error = ResolveTokenError_Other;
6006 /* Validate token */
6007 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6008 *resolve_error = ResolveTokenError_BadTable;
6012 if (image_is_dynamic (image)) {
6013 if (table == MONO_TABLE_FIELD) {
6014 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6015 mono_error_cleanup (&error);
6019 if (mono_memberref_is_method (image, token)) {
6020 *resolve_error = ResolveTokenError_BadTable;
6024 init_generic_context_from_args (&context, type_args, method_args);
6025 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6026 mono_error_cleanup (&error);
6030 if ((index <= 0) || (index > image->tables [table].rows)) {
6031 *resolve_error = ResolveTokenError_OutOfRange;
6034 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6035 *resolve_error = ResolveTokenError_BadTable;
6039 init_generic_context_from_args (&context, type_args, method_args);
6040 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6041 mono_error_set_pending_exception (&error);
6047 ICALL_EXPORT MonoObject*
6048 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6052 int table = mono_metadata_token_table (token);
6054 *error = ResolveTokenError_Other;
6057 case MONO_TABLE_TYPEDEF:
6058 case MONO_TABLE_TYPEREF:
6059 case MONO_TABLE_TYPESPEC: {
6060 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6062 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6063 mono_error_raise_exception (&merror);
6070 case MONO_TABLE_METHOD:
6071 case MONO_TABLE_METHODSPEC: {
6072 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6074 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6075 mono_error_raise_exception (&merror);
6081 case MONO_TABLE_FIELD: {
6082 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6084 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6085 mono_error_raise_exception (&merror);
6091 case MONO_TABLE_MEMBERREF:
6092 if (mono_memberref_is_method (image, token)) {
6093 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6095 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6096 mono_error_raise_exception (&merror);
6103 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6105 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6106 mono_error_raise_exception (&merror);
6115 *error = ResolveTokenError_BadTable;
6121 ICALL_EXPORT MonoArray*
6122 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
6124 int table = mono_metadata_token_table (token);
6125 int idx = mono_metadata_token_index (token);
6126 MonoTableInfo *tables = image->tables;
6131 *error = ResolveTokenError_OutOfRange;
6133 /* FIXME: Support other tables ? */
6134 if (table != MONO_TABLE_STANDALONESIG)
6137 if (image_is_dynamic (image))
6140 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6143 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6145 ptr = mono_metadata_blob_heap (image, sig);
6146 len = mono_metadata_decode_blob_size (ptr, &ptr);
6148 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
6149 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6153 ICALL_EXPORT MonoReflectionType*
6154 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6157 MonoReflectionType *ret;
6159 int isbyref = 0, rank;
6160 char *str = mono_string_to_utf8 (smodifiers);
6163 klass = mono_class_from_mono_type (tb->type.type);
6165 /* logic taken from mono_reflection_parse_type(): keep in sync */
6169 if (isbyref) { /* only one level allowed by the spec */
6178 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6179 mono_error_raise_exception (&error);
6183 klass = mono_ptr_class_get (&klass->byval_arg);
6184 mono_class_init (klass);
6195 else if (*p != '*') { /* '*' means unknown lower bound */
6206 klass = mono_array_class_get (klass, rank);
6207 mono_class_init (klass);
6216 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6217 mono_error_raise_exception (&error);
6222 ICALL_EXPORT MonoBoolean
6223 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6229 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6235 check_for_invalid_type (MonoClass *klass, MonoError *error)
6240 mono_error_init (error);
6242 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6245 name = mono_type_get_full_name (klass);
6246 str = mono_string_new (mono_domain_get (), name);
6248 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6251 ICALL_EXPORT MonoReflectionType *
6252 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6255 MonoReflectionType *ret;
6256 MonoClass *klass, *aklass;
6258 klass = mono_class_from_mono_type (type->type);
6259 check_for_invalid_type (klass, &error);
6260 mono_error_raise_exception (&error);
6262 if (rank == 0) //single dimentional array
6263 aklass = mono_array_class_get (klass, 1);
6265 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6267 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6268 mono_error_raise_exception (&error);
6273 ICALL_EXPORT MonoReflectionType *
6274 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6277 MonoReflectionType *ret;
6280 klass = mono_class_from_mono_type (type->type);
6281 mono_class_init_checked (klass, &error);
6282 mono_error_raise_exception (&error);
6283 check_for_invalid_type (klass, &error);
6284 mono_error_raise_exception (&error);
6286 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6287 mono_error_raise_exception (&error);
6292 ICALL_EXPORT MonoReflectionType *
6293 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6296 MonoReflectionType *ret;
6297 MonoClass *klass, *pklass;
6299 klass = mono_class_from_mono_type (type->type);
6300 mono_class_init_checked (klass, &error);
6301 mono_error_raise_exception (&error);
6302 check_for_invalid_type (klass, &error);
6303 mono_error_raise_exception (&error);
6305 pklass = mono_ptr_class_get (type->type);
6307 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6308 mono_error_raise_exception (&error);
6313 ICALL_EXPORT MonoObject *
6314 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6315 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6318 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6319 MonoObject *delegate;
6321 MonoMethod *method = info->method;
6323 mono_class_init_checked (delegate_class, &error);
6324 mono_error_raise_exception (&error);
6326 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6327 /* FIXME improve this exception message */
6328 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6330 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6331 mono_error_set_pending_exception (&error);
6335 if (mono_security_core_clr_enabled ()) {
6336 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6340 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6341 mono_error_raise_exception (&error);
6343 if (method_is_dynamic (method)) {
6344 /* Creating a trampoline would leak memory */
6345 func = mono_compile_method (method);
6347 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6348 method = mono_object_get_virtual_method (target, method);
6349 func = mono_create_ftnptr (mono_domain_get (),
6350 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6353 mono_delegate_ctor_with_method (delegate, target, func, method);
6358 ICALL_EXPORT MonoMulticastDelegate *
6359 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6362 MonoMulticastDelegate *ret;
6364 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6366 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6367 mono_error_raise_exception (&error);
6368 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6373 ICALL_EXPORT MonoReflectionMethod*
6374 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6376 MonoReflectionMethod *ret = NULL;
6378 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6379 mono_error_raise_exception (&error);
6385 static inline gint32
6386 mono_array_get_byte_length (MonoArray *array)
6392 klass = array->obj.vtable->klass;
6394 if (array->bounds == NULL)
6395 length = array->max_length;
6398 for (i = 0; i < klass->rank; ++ i)
6399 length *= array->bounds [i].length;
6402 switch (klass->element_class->byval_arg.type) {
6405 case MONO_TYPE_BOOLEAN:
6409 case MONO_TYPE_CHAR:
6417 return length * sizeof (gpointer);
6428 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6430 return mono_array_get_byte_length (array);
6434 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6436 return mono_array_get (array, gint8, idx);
6440 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6442 mono_array_set (array, gint8, idx, value);
6445 ICALL_EXPORT MonoBoolean
6446 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6448 guint8 *src_buf, *dest_buf;
6451 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6455 g_assert (count >= 0);
6457 /* This is called directly from the class libraries without going through the managed wrapper */
6458 MONO_CHECK_ARG_NULL (src, FALSE);
6459 MONO_CHECK_ARG_NULL (dest, FALSE);
6461 /* watch out for integer overflow */
6462 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6465 src_buf = (guint8 *)src->vector + src_offset;
6466 dest_buf = (guint8 *)dest->vector + dest_offset;
6469 memcpy (dest_buf, src_buf, count);
6471 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6476 #ifndef DISABLE_REMOTING
6477 ICALL_EXPORT MonoObject *
6478 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6481 MonoDomain *domain = mono_object_domain (this_obj);
6483 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6484 MonoTransparentProxy *tp;
6488 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6489 mono_error_raise_exception (&error);
6490 tp = (MonoTransparentProxy*) res;
6492 MONO_OBJECT_SETREF (tp, rp, rp);
6493 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6494 klass = mono_class_from_mono_type (type);
6496 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6497 mono_class_setup_vtable (klass);
6498 if (mono_class_has_failure (klass)) {
6499 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6503 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6504 if (!is_ok (&error)) {
6505 mono_error_set_pending_exception (&error);
6508 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6509 if (!is_ok (&error)) {
6510 mono_error_set_pending_exception (&error);
6514 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6518 ICALL_EXPORT MonoReflectionType *
6519 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6522 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6523 mono_error_raise_exception (&error);
6529 /* System.Environment */
6532 ves_icall_System_Environment_get_UserName (void)
6534 /* using glib is more portable */
6535 return mono_string_new (mono_domain_get (), g_get_user_name ());
6539 ICALL_EXPORT MonoString *
6540 ves_icall_System_Environment_get_MachineName (void)
6542 #if defined (HOST_WIN32)
6547 len = MAX_COMPUTERNAME_LENGTH + 1;
6548 buf = g_new (gunichar2, len);
6551 if (GetComputerName (buf, (PDWORD) &len)) {
6553 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6554 mono_error_raise_exception (&error);
6559 #elif !defined(DISABLE_SOCKETS)
6563 #if defined _SC_HOST_NAME_MAX
6564 n = sysconf (_SC_HOST_NAME_MAX);
6568 buf = g_malloc (n+1);
6570 if (gethostname (buf, n) == 0){
6572 result = mono_string_new (mono_domain_get (), buf);
6579 return mono_string_new (mono_domain_get (), "mono");
6584 ves_icall_System_Environment_get_Platform (void)
6586 #if defined (TARGET_WIN32)
6589 #elif defined(__MACH__)
6592 // Notice that the value is hidden from user code, and only exposed
6593 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6594 // define and making assumptions based on Unix/128/4 values before there
6595 // was a MacOS define. Lots of code would assume that not-Unix meant
6596 // Windows, but in this case, it would be OSX.
6605 ICALL_EXPORT MonoString *
6606 ves_icall_System_Environment_get_NewLine (void)
6608 #if defined (HOST_WIN32)
6609 return mono_string_new (mono_domain_get (), "\r\n");
6611 return mono_string_new (mono_domain_get (), "\n");
6615 ICALL_EXPORT MonoBoolean
6616 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6618 #if SIZEOF_VOID_P == 8
6622 gboolean isWow64Process = FALSE;
6623 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6624 return (MonoBoolean)isWow64Process;
6626 #elif defined(HAVE_SYS_UTSNAME_H)
6627 struct utsname name;
6629 if (uname (&name) >= 0) {
6630 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6637 ICALL_EXPORT MonoString *
6638 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6646 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6647 value = g_getenv (utf8_name);
6654 return mono_string_new (mono_domain_get (), value);
6658 * There is no standard way to get at environ.
6661 #ifndef __MINGW32_VERSION
6662 #if defined(__APPLE__)
6663 #if defined (TARGET_OSX)
6664 /* Apple defines this in crt_externs.h but doesn't provide that header for
6665 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6666 * in fact exist on all implementations (so far)
6668 gchar ***_NSGetEnviron(void);
6669 #define environ (*_NSGetEnviron())
6671 static char *mono_environ[1] = { NULL };
6672 #define environ mono_environ
6673 #endif /* defined (TARGET_OSX) */
6681 ICALL_EXPORT MonoArray *
6682 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6693 env_strings = GetEnvironmentStrings();
6696 env_string = env_strings;
6697 while (*env_string != '\0') {
6698 /* weird case that MS seems to skip */
6699 if (*env_string != '=')
6701 while (*env_string != '\0')
6707 domain = mono_domain_get ();
6708 names = mono_array_new (domain, mono_defaults.string_class, n);
6712 env_string = env_strings;
6713 while (*env_string != '\0') {
6714 /* weird case that MS seems to skip */
6715 if (*env_string != '=') {
6716 equal_str = wcschr(env_string, '=');
6717 g_assert(equal_str);
6719 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6720 mono_error_raise_exception (&error);
6721 mono_array_setref (names, n, str);
6724 while (*env_string != '\0')
6729 FreeEnvironmentStrings (env_strings);
6742 for (e = environ; *e != 0; ++ e)
6745 domain = mono_domain_get ();
6746 names = mono_array_new (domain, mono_defaults.string_class, n);
6749 for (e = environ; *e != 0; ++ e) {
6750 parts = g_strsplit (*e, "=", 2);
6752 str = mono_string_new (domain, *parts);
6753 mono_array_setref (names, n, str);
6766 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6768 #if !GLIB_CHECK_VERSION(2,4,0)
6769 #define g_setenv(a,b,c) setenv(a,b,c)
6770 #define g_unsetenv(a) unsetenv(a)
6774 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6777 gunichar2 *utf16_name, *utf16_value;
6779 gchar *utf8_name, *utf8_value;
6784 utf16_name = mono_string_to_utf16 (name);
6785 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6786 SetEnvironmentVariable (utf16_name, NULL);
6787 g_free (utf16_name);
6791 utf16_value = mono_string_to_utf16 (value);
6793 SetEnvironmentVariable (utf16_name, utf16_value);
6795 g_free (utf16_name);
6796 g_free (utf16_value);
6798 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6800 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6801 g_unsetenv (utf8_name);
6806 utf8_value = mono_string_to_utf8_checked (value, &error);
6807 if (!mono_error_ok (&error)) {
6809 mono_error_set_pending_exception (&error);
6812 g_setenv (utf8_name, utf8_value, TRUE);
6815 g_free (utf8_value);
6820 ves_icall_System_Environment_Exit (int result)
6822 mono_environment_exitcode_set (result);
6824 /* FIXME: There are some cleanup hangs that should be worked out, but
6825 * if the program is going to exit, everything will be cleaned up when
6826 * NaCl exits anyway.
6828 #ifndef __native_client__
6829 if (!mono_runtime_try_shutdown ())
6830 mono_thread_exit ();
6832 /* Suspend all managed threads since the runtime is going away */
6833 mono_thread_suspend_all_other_threads ();
6835 mono_runtime_quit ();
6838 /* we may need to do some cleanup here... */
6842 ICALL_EXPORT MonoString*
6843 ves_icall_System_Environment_GetGacPath (void)
6845 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6848 ICALL_EXPORT MonoString*
6849 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6851 #if defined (HOST_WIN32)
6852 #ifndef CSIDL_FLAG_CREATE
6853 #define CSIDL_FLAG_CREATE 0x8000
6856 WCHAR path [MAX_PATH];
6857 /* Create directory if no existing */
6858 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6863 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6864 mono_error_raise_exception (&error);
6868 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6870 return mono_string_new (mono_domain_get (), "");
6873 ICALL_EXPORT MonoArray *
6874 ves_icall_System_Environment_GetLogicalDrives (void)
6877 gunichar2 buf [256], *ptr, *dname;
6879 guint initial_size = 127, size = 128;
6882 MonoString *drivestr;
6883 MonoDomain *domain = mono_domain_get ();
6889 while (size > initial_size) {
6890 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6891 if (size > initial_size) {
6894 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6895 initial_size = size;
6909 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6914 while (*u16) { u16++; len ++; }
6915 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6916 mono_error_raise_exception (&error);
6917 mono_array_setref (result, ndrives++, drivestr);
6927 ICALL_EXPORT MonoString *
6928 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6930 gunichar2 volume_name [MAX_PATH + 1];
6932 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6934 return mono_string_from_utf16 (volume_name);
6937 ICALL_EXPORT MonoString *
6938 ves_icall_System_Environment_InternalGetHome (void)
6940 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6943 static const char *encodings [] = {
6945 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6946 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6947 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6949 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6950 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6951 "x_unicode_2_0_utf_7",
6953 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6954 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6956 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6959 "unicodefffe", "utf_16be",
6966 * Returns the internal codepage, if the value of "int_code_page" is
6967 * 1 at entry, and we can not compute a suitable code page number,
6968 * returns the code page as a string
6970 ICALL_EXPORT MonoString*
6971 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6976 char *codepage = NULL;
6978 int want_name = *int_code_page;
6981 *int_code_page = -1;
6983 g_get_charset (&cset);
6984 c = codepage = strdup (cset);
6985 for (c = codepage; *c; c++){
6986 if (isascii (*c) && isalpha (*c))
6991 /* g_print ("charset: %s\n", cset); */
6993 /* handle some common aliases */
6996 for (i = 0; p != 0; ){
6999 p = encodings [++i];
7002 if (strcmp (p, codepage) == 0){
7003 *int_code_page = code;
7006 p = encodings [++i];
7009 if (strstr (codepage, "utf_8") != NULL)
7010 *int_code_page |= 0x10000000;
7013 if (want_name && *int_code_page == -1)
7014 return mono_string_new (mono_domain_get (), cset);
7019 ICALL_EXPORT MonoBoolean
7020 ves_icall_System_Environment_get_HasShutdownStarted (void)
7022 if (mono_runtime_is_shutting_down ())
7025 if (mono_domain_is_unloading (mono_domain_get ()))
7032 ves_icall_System_Environment_BroadcastSettingChange (void)
7035 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7040 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7046 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
7047 MonoReflectionMethod *method,
7048 MonoArray *out_args)
7050 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
7053 #ifndef DISABLE_REMOTING
7054 ICALL_EXPORT MonoBoolean
7055 ves_icall_IsTransparentProxy (MonoObject *proxy)
7060 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7066 ICALL_EXPORT MonoReflectionMethod *
7067 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7068 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7070 MonoReflectionMethod *ret = NULL;
7075 MonoMethod **vtable;
7076 MonoMethod *res = NULL;
7078 MONO_CHECK_ARG_NULL (rtype, NULL);
7079 MONO_CHECK_ARG_NULL (rmethod, NULL);
7081 method = rmethod->method;
7082 klass = mono_class_from_mono_type (rtype->type);
7083 mono_class_init_checked (klass, &error);
7084 mono_error_raise_exception (&error);
7086 if (MONO_CLASS_IS_INTERFACE (klass))
7089 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7092 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7093 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7099 mono_class_setup_vtable (klass);
7100 vtable = klass->vtable;
7102 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7103 gboolean variance_used = FALSE;
7104 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7105 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7107 res = vtable [offs + method->slot];
7109 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7112 if (method->slot != -1)
7113 res = vtable [method->slot];
7119 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7120 mono_error_raise_exception (&error);
7125 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7131 klass = mono_class_from_mono_type (type->type);
7132 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7133 if (!is_ok (&error)) {
7134 mono_error_set_pending_exception (&error);
7138 mono_vtable_set_is_remote (vtable, enable);
7141 #else /* DISABLE_REMOTING */
7144 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7146 g_assert_not_reached ();
7151 ICALL_EXPORT MonoObject *
7152 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7159 domain = mono_object_domain (type);
7160 klass = mono_class_from_mono_type (type->type);
7161 mono_class_init_checked (klass, &error);
7162 mono_error_raise_exception (&error);
7164 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7165 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7169 if (klass->rank >= 1) {
7170 g_assert (klass->rank == 1);
7171 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7173 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7174 if (!is_ok (&error)) {
7175 mono_error_set_pending_exception (&error);
7178 /* Bypass remoting object creation check */
7179 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7180 mono_error_set_pending_exception (&error);
7186 ICALL_EXPORT MonoString *
7187 ves_icall_System_IO_get_temp_path (void)
7189 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7192 #ifndef PLATFORM_NO_DRIVEINFO
7193 ICALL_EXPORT MonoBoolean
7194 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7195 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7199 ULARGE_INTEGER wapi_free_bytes_avail;
7200 ULARGE_INTEGER wapi_total_number_of_bytes;
7201 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7203 *error = ERROR_SUCCESS;
7204 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7205 &wapi_total_number_of_free_bytes);
7208 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7209 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7210 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7212 *free_bytes_avail = 0;
7213 *total_number_of_bytes = 0;
7214 *total_number_of_free_bytes = 0;
7215 *error = GetLastError ();
7221 ICALL_EXPORT guint32
7222 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7224 return GetDriveType (mono_string_chars (root_path_name));
7228 ICALL_EXPORT gpointer
7229 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7231 return mono_compile_method (method);
7234 ICALL_EXPORT MonoString *
7235 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7240 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7242 #if defined (HOST_WIN32)
7243 /* Avoid mixing '/' and '\\' */
7246 for (i = strlen (path) - 1; i >= 0; i--)
7247 if (path [i] == '/')
7251 mcpath = mono_string_new (mono_domain_get (), path);
7258 get_bundled_app_config (void)
7260 const gchar *app_config;
7263 gchar *config_file_name, *config_file_path;
7264 gsize len, config_file_path_length, config_ext_length;
7267 domain = mono_domain_get ();
7268 file = domain->setup->configuration_file;
7269 if (!file || file->length == 0)
7272 // Retrieve config file and remove the extension
7273 config_file_name = mono_string_to_utf8 (file);
7274 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7275 if (!config_file_path)
7276 config_file_path = config_file_name;
7278 config_file_path_length = strlen (config_file_path);
7279 config_ext_length = strlen (".config");
7280 if (config_file_path_length <= config_ext_length)
7283 len = config_file_path_length - config_ext_length;
7284 module = (gchar *)g_malloc0 (len + 1);
7285 memcpy (module, config_file_path, len);
7286 // Get the config file from the module name
7287 app_config = mono_config_string_for_assembly_file (module);
7290 if (config_file_name != config_file_path)
7291 g_free (config_file_name);
7292 g_free (config_file_path);
7297 return mono_string_new (mono_domain_get (), app_config);
7301 get_bundled_machine_config (void)
7303 const gchar *machine_config;
7305 machine_config = mono_get_machine_config ();
7307 if (!machine_config)
7310 return mono_string_new (mono_domain_get (), machine_config);
7313 ICALL_EXPORT MonoString *
7314 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7319 path = g_path_get_dirname (mono_get_config_dir ());
7321 #if defined (HOST_WIN32)
7322 /* Avoid mixing '/' and '\\' */
7325 for (i = strlen (path) - 1; i >= 0; i--)
7326 if (path [i] == '/')
7330 ipath = mono_string_new (mono_domain_get (), path);
7336 ICALL_EXPORT gboolean
7337 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7339 MonoPEResourceDataEntry *entry;
7342 if (!assembly || !result || !size)
7347 image = assembly->assembly->image;
7348 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7352 *result = mono_image_rva_map (image, entry->rde_data_offset);
7357 *size = entry->rde_size;
7362 ICALL_EXPORT MonoBoolean
7363 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7365 return mono_is_debugger_attached ();
7368 ICALL_EXPORT MonoBoolean
7369 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7371 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7372 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7378 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7380 if (mono_get_runtime_callbacks ()->debug_log)
7381 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7385 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7387 #if defined (HOST_WIN32)
7388 OutputDebugString (mono_string_chars (message));
7390 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7394 /* Only used for value types */
7395 ICALL_EXPORT MonoObject *
7396 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7403 domain = mono_object_domain (type);
7404 klass = mono_class_from_mono_type (type->type);
7405 mono_class_init_checked (klass, &error);
7406 mono_error_raise_exception (&error);
7408 if (mono_class_is_nullable (klass))
7409 /* No arguments -> null */
7412 result = mono_object_new_checked (domain, klass, &error);
7413 mono_error_raise_exception (&error);
7417 ICALL_EXPORT MonoReflectionMethod *
7418 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7420 MonoReflectionMethod *ret = NULL;
7423 MonoClass *klass, *parent;
7424 MonoGenericContext *generic_inst = NULL;
7425 MonoMethod *method = m->method;
7426 MonoMethod *result = NULL;
7429 if (method->klass == NULL)
7432 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7433 MONO_CLASS_IS_INTERFACE (method->klass) ||
7434 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7437 slot = mono_method_get_vtable_slot (method);
7441 klass = method->klass;
7442 if (klass->generic_class) {
7443 generic_inst = mono_class_get_context (klass);
7444 klass = klass->generic_class->container_class;
7448 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7449 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7450 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7451 or klass is the generic container class and generic_inst is the instantiation.
7453 when we go to the parent, if the parent is an open constructed type, we need to
7454 replace the type parameters by the definitions from the generic_inst, and then take it
7455 apart again into the klass and the generic_inst.
7457 For cases like this:
7458 class C<T> : B<T, int> {
7459 public override void Foo () { ... }
7461 class B<U,V> : A<HashMap<U,V>> {
7462 public override void Foo () { ... }
7465 public virtual void Foo () { ... }
7468 if at each iteration the parent isn't open, we can skip inflating it. if at some
7469 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7472 MonoGenericContext *parent_inst = NULL;
7473 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7475 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7476 if (!mono_error_ok (&error)) {
7477 mono_error_set_pending_exception (&error);
7481 if (parent->generic_class) {
7482 parent_inst = mono_class_get_context (parent);
7483 parent = parent->generic_class->container_class;
7486 mono_class_setup_vtable (parent);
7487 if (parent->vtable_size <= slot)
7490 generic_inst = parent_inst;
7493 klass = klass->parent;
7496 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7497 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7498 if (!mono_error_ok (&error)) {
7499 mono_error_set_pending_exception (&error);
7503 generic_inst = NULL;
7505 if (klass->generic_class) {
7506 generic_inst = mono_class_get_context (klass);
7507 klass = klass->generic_class->container_class;
7513 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7514 if (!mono_error_ok (&error)) {
7515 mono_error_set_pending_exception (&error);
7520 if (klass == method->klass)
7523 /*This is possible if definition == FALSE.
7524 * Do it here to be really sure we don't read invalid memory.
7526 if (slot >= klass->vtable_size)
7529 mono_class_setup_vtable (klass);
7531 result = klass->vtable [slot];
7532 if (result == NULL) {
7533 /* It is an abstract method */
7534 gpointer iter = NULL;
7535 while ((result = mono_class_get_methods (klass, &iter)))
7536 if (result->slot == slot)
7543 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7544 mono_error_raise_exception (&error);
7548 ICALL_EXPORT MonoString*
7549 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7551 MonoMethod *method = m->method;
7553 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7558 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7560 iter->sig = *(MonoMethodSignature**)argsp;
7562 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7563 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7566 /* FIXME: it's not documented what start is exactly... */
7570 iter->args = argsp + sizeof (gpointer);
7572 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7574 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7577 ICALL_EXPORT MonoTypedRef
7578 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7580 guint32 i, arg_size;
7584 i = iter->sig->sentinelpos + iter->next_arg;
7586 g_assert (i < iter->sig->param_count);
7588 res.type = iter->sig->params [i];
7589 res.klass = mono_class_from_mono_type (res.type);
7590 arg_size = mono_type_stack_size (res.type, &align);
7591 #if defined(__arm__) || defined(__mips__)
7592 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7594 res.value = iter->args;
7595 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7596 /* Values are stored as 8 byte register sized objects, but 'value'
7597 * is dereferenced as a pointer in other routines.
7599 res.value = (char*)res.value + 4;
7601 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7602 if (arg_size <= sizeof (gpointer)) {
7604 int padding = arg_size - mono_type_size (res.type, &dummy);
7605 res.value = (guint8*)res.value + padding;
7608 iter->args = (char*)iter->args + arg_size;
7611 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7616 ICALL_EXPORT MonoTypedRef
7617 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7619 guint32 i, arg_size;
7623 i = iter->sig->sentinelpos + iter->next_arg;
7625 g_assert (i < iter->sig->param_count);
7627 while (i < iter->sig->param_count) {
7628 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7630 res.type = iter->sig->params [i];
7631 res.klass = mono_class_from_mono_type (res.type);
7632 /* FIXME: endianess issue... */
7633 arg_size = mono_type_stack_size (res.type, &align);
7634 #if defined(__arm__) || defined(__mips__)
7635 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7637 res.value = iter->args;
7638 iter->args = (char*)iter->args + arg_size;
7640 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7643 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7651 ICALL_EXPORT MonoType*
7652 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7656 i = iter->sig->sentinelpos + iter->next_arg;
7658 g_assert (i < iter->sig->param_count);
7660 return iter->sig->params [i];
7663 ICALL_EXPORT MonoObject*
7664 mono_TypedReference_ToObject (MonoTypedRef* tref)
7667 MonoObject *result = NULL;
7668 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7669 MonoObject** objp = (MonoObject **)tref->value;
7673 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7674 mono_error_set_pending_exception (&error);
7678 ICALL_EXPORT MonoTypedRef
7679 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7682 MonoReflectionField *f;
7684 MonoType *ftype = NULL;
7688 memset (&res, 0, sizeof (res));
7691 g_assert (mono_array_length (fields) > 0);
7693 klass = target->vtable->klass;
7695 for (i = 0; i < mono_array_length (fields); ++i) {
7696 f = mono_array_get (fields, MonoReflectionField*, i);
7698 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7701 if (f->field->parent != klass) {
7702 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7706 p = (guint8*)target + f->field->offset;
7708 p += f->field->offset - sizeof (MonoObject);
7709 klass = mono_class_from_mono_type (f->field->type);
7710 ftype = f->field->type;
7714 res.klass = mono_class_from_mono_type (ftype);
7721 prelink_method (MonoMethod *method, MonoError *error)
7723 const char *exc_class, *exc_arg;
7725 mono_error_init (error);
7726 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7728 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7730 mono_error_set_exception_instance (error,
7731 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7734 /* create the wrapper, too? */
7738 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7742 prelink_method (method->method, &error);
7743 mono_error_raise_exception (&error);
7747 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7750 MonoClass *klass = mono_class_from_mono_type (type->type);
7752 gpointer iter = NULL;
7754 mono_class_init_checked (klass, &error);
7755 mono_error_raise_exception (&error);
7757 while ((m = mono_class_get_methods (klass, &iter))) {
7758 prelink_method (m, &error);
7759 mono_error_raise_exception (&error);
7763 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7765 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7766 gint32 const **exponents,
7767 gunichar2 const **digitLowerTable,
7768 gunichar2 const **digitUpperTable,
7769 gint64 const **tenPowersList,
7770 gint32 const **decHexDigits)
7772 *mantissas = Formatter_MantissaBitsTable;
7773 *exponents = Formatter_TensExponentTable;
7774 *digitLowerTable = Formatter_DigitLowerTable;
7775 *digitUpperTable = Formatter_DigitUpperTable;
7776 *tenPowersList = Formatter_TenPowersList;
7777 *decHexDigits = Formatter_DecHexDigits;
7781 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7782 * and avoid useless allocations.
7785 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7787 MonoReflectionType *rt;
7791 mono_error_init (error);
7792 for (i = 0; i < type->num_mods; ++i) {
7793 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7798 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7800 for (i = 0; i < type->num_mods; ++i) {
7801 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7802 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7803 return_val_if_nok (error, NULL);
7805 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7806 return_val_if_nok (error, NULL);
7808 mono_array_setref (res, count, rt);
7815 ICALL_EXPORT MonoArray*
7816 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7819 MonoType *type = param->ClassImpl->type;
7820 MonoClass *member_class = mono_object_class (param->MemberImpl);
7821 MonoMethod *method = NULL;
7824 MonoMethodSignature *sig;
7827 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7828 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7829 method = rmethod->method;
7830 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7831 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7832 if (!(method = prop->property->get))
7833 method = prop->property->set;
7836 char *type_name = mono_type_get_full_name (member_class);
7837 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7838 MonoException *ex = mono_get_exception_not_supported (msg);
7841 mono_set_pending_exception (ex);
7845 image = method->klass->image;
7846 pos = param->PositionImpl;
7847 sig = mono_method_signature (method);
7851 type = sig->params [pos];
7853 res = type_array_from_modifiers (image, type, optional, &error);
7854 mono_error_raise_exception (&error);
7859 get_property_type (MonoProperty *prop)
7861 MonoMethodSignature *sig;
7863 sig = mono_method_signature (prop->get);
7865 } else if (prop->set) {
7866 sig = mono_method_signature (prop->set);
7867 return sig->params [sig->param_count - 1];
7872 ICALL_EXPORT MonoArray*
7873 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7876 MonoType *type = get_property_type (property->property);
7877 MonoImage *image = property->klass->image;
7882 res = type_array_from_modifiers (image, type, optional, &error);
7883 mono_error_raise_exception (&error);
7888 *Construct a MonoType suited to be used to decode a constant blob object.
7890 * @type is the target type which will be constructed
7891 * @blob_type is the blob type, for example, that comes from the constant table
7892 * @real_type is the expected constructed type.
7895 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7897 type->type = blob_type;
7898 type->data.klass = NULL;
7899 if (blob_type == MONO_TYPE_CLASS)
7900 type->data.klass = mono_defaults.object_class;
7901 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7902 /* For enums, we need to use the base type */
7903 type->type = MONO_TYPE_VALUETYPE;
7904 type->data.klass = mono_class_from_mono_type (real_type);
7906 type->data.klass = mono_class_from_mono_type (real_type);
7909 ICALL_EXPORT MonoObject*
7910 property_info_get_default_value (MonoReflectionProperty *property)
7914 MonoProperty *prop = property->property;
7915 MonoType *type = get_property_type (prop);
7916 MonoDomain *domain = mono_object_domain (property);
7917 MonoTypeEnum def_type;
7918 const char *def_value;
7921 mono_class_init (prop->parent);
7923 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7924 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7928 def_value = mono_class_get_property_default_value (prop, &def_type);
7930 mono_type_from_blob_type (&blob_type, def_type, type);
7931 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7933 mono_error_set_pending_exception (&error);
7937 ICALL_EXPORT MonoBoolean
7938 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7941 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7942 MonoCustomAttrInfo *cinfo;
7945 mono_class_init_checked (attr_class, &error);
7946 mono_error_raise_exception (&error);
7948 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7949 if (!is_ok (&error)) {
7950 mono_error_set_pending_exception (&error);
7955 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7957 mono_custom_attrs_free (cinfo);
7961 ICALL_EXPORT MonoArray*
7962 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7964 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7969 mono_class_init_checked (attr_class, &error);
7970 mono_error_raise_exception (&error);
7973 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7974 if (!mono_error_ok (&error)) {
7975 mono_error_set_pending_exception (&error);
7979 if (mono_loader_get_last_error ()) {
7980 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7987 ICALL_EXPORT MonoArray*
7988 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7992 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7993 mono_error_set_pending_exception (&error);
7998 ICALL_EXPORT MonoString*
7999 ves_icall_Mono_Runtime_GetDisplayName (void)
8002 MonoString *display_name;
8004 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8005 display_name = mono_string_new (mono_domain_get (), info);
8007 return display_name;
8010 ICALL_EXPORT MonoString*
8011 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8014 MonoString *message;
8018 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8019 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8022 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8024 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8025 mono_error_raise_exception (&error);
8032 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
8035 char *path_str = mono_string_to_utf8 (path);
8037 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
8045 ICALL_EXPORT gpointer
8046 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8048 return GetCurrentProcess ();
8051 ICALL_EXPORT MonoBoolean
8052 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8054 return GetExitCodeProcess (handle, (guint32*) exitcode);
8057 ICALL_EXPORT MonoBoolean
8058 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8060 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8061 return CloseHandle (handle);
8063 return CloseProcess (handle);
8067 ICALL_EXPORT MonoBoolean
8068 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8070 return TerminateProcess (handle, exitcode);
8074 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8076 return WaitForInputIdle (handle, milliseconds);
8079 ICALL_EXPORT MonoBoolean
8080 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8082 return GetProcessWorkingSetSize (handle, min, max);
8085 ICALL_EXPORT MonoBoolean
8086 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8088 return SetProcessWorkingSetSize (handle, min, max);
8091 ICALL_EXPORT MonoBoolean
8092 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8094 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8098 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8100 return mono_process_current_pid ();
8104 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8106 return GetPriorityClass (handle);
8109 ICALL_EXPORT MonoBoolean
8110 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8112 return SetPriorityClass (handle, priorityClass);
8115 #ifndef DISABLE_ICALL_TABLES
8117 #define ICALL_TYPE(id,name,first)
8118 #define ICALL(id,name,func) Icall_ ## id,
8121 #include "metadata/icall-def.h"
8127 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8128 #define ICALL(id,name,func)
8130 #include "metadata/icall-def.h"
8136 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8137 #define ICALL(id,name,func)
8139 guint16 first_icall;
8142 static const IcallTypeDesc
8143 icall_type_descs [] = {
8144 #include "metadata/icall-def.h"
8148 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8151 #define ICALL_TYPE(id,name,first)
8154 #ifdef HAVE_ARRAY_ELEM_INIT
8155 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8156 #define MSGSTRFIELD1(line) str##line
8158 static const struct msgstrtn_t {
8159 #define ICALL(id,name,func)
8161 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8162 #include "metadata/icall-def.h"
8164 } icall_type_names_str = {
8165 #define ICALL_TYPE(id,name,first) (name),
8166 #include "metadata/icall-def.h"
8169 static const guint16 icall_type_names_idx [] = {
8170 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8171 #include "metadata/icall-def.h"
8174 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8176 static const struct msgstr_t {
8178 #define ICALL_TYPE(id,name,first)
8179 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8180 #include "metadata/icall-def.h"
8182 } icall_names_str = {
8183 #define ICALL(id,name,func) (name),
8184 #include "metadata/icall-def.h"
8187 static const guint16 icall_names_idx [] = {
8188 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8189 #include "metadata/icall-def.h"
8192 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8198 #define ICALL_TYPE(id,name,first) name,
8199 #define ICALL(id,name,func)
8200 static const char* const
8201 icall_type_names [] = {
8202 #include "metadata/icall-def.h"
8206 #define icall_type_name_get(id) (icall_type_names [(id)])
8210 #define ICALL_TYPE(id,name,first)
8211 #define ICALL(id,name,func) name,
8212 static const char* const
8214 #include "metadata/icall-def.h"
8217 #define icall_name_get(id) icall_names [(id)]
8219 #endif /* !HAVE_ARRAY_ELEM_INIT */
8223 #define ICALL_TYPE(id,name,first)
8224 #define ICALL(id,name,func) func,
8225 static const gconstpointer
8226 icall_functions [] = {
8227 #include "metadata/icall-def.h"
8231 #ifdef ENABLE_ICALL_SYMBOL_MAP
8234 #define ICALL_TYPE(id,name,first)
8235 #define ICALL(id,name,func) #func,
8236 static const gconstpointer
8237 icall_symbols [] = {
8238 #include "metadata/icall-def.h"
8243 #endif /* DISABLE_ICALL_TABLES */
8245 static mono_mutex_t icall_mutex;
8246 static GHashTable *icall_hash = NULL;
8247 static GHashTable *jit_icall_hash_name = NULL;
8248 static GHashTable *jit_icall_hash_addr = NULL;
8251 mono_icall_init (void)
8253 #ifndef DISABLE_ICALL_TABLES
8256 /* check that tables are sorted: disable in release */
8259 const char *prev_class = NULL;
8260 const char *prev_method;
8262 for (i = 0; i < Icall_type_num; ++i) {
8263 const IcallTypeDesc *desc;
8266 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8267 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8268 prev_class = icall_type_name_get (i);
8269 desc = &icall_type_descs [i];
8270 num_icalls = icall_desc_num_icalls (desc);
8271 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8272 for (j = 0; j < num_icalls; ++j) {
8273 const char *methodn = icall_name_get (desc->first_icall + j);
8274 if (prev_method && strcmp (prev_method, methodn) >= 0)
8275 g_print ("method %s should come before method %s\n", methodn, prev_method);
8276 prev_method = methodn;
8282 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8283 mono_os_mutex_init (&icall_mutex);
8287 mono_icall_lock (void)
8289 mono_locks_os_acquire (&icall_mutex, IcallLock);
8293 mono_icall_unlock (void)
8295 mono_locks_os_release (&icall_mutex, IcallLock);
8299 mono_icall_cleanup (void)
8301 g_hash_table_destroy (icall_hash);
8302 g_hash_table_destroy (jit_icall_hash_name);
8303 g_hash_table_destroy (jit_icall_hash_addr);
8304 mono_os_mutex_destroy (&icall_mutex);
8308 * mono_add_internal_call:
8309 * @name: method specification to surface to the managed world
8310 * @method: pointer to a C method to invoke when the method is called
8312 * This method surfaces the C function pointed by @method as a method
8313 * that has been surfaced in managed code with the method specified in
8314 * @name as an internal call.
8316 * Internal calls are surfaced to all app domains loaded and they are
8317 * accessibly by a type with the specified name.
8319 * You must provide a fully qualified type name, that is namespaces
8320 * and type name, followed by a colon and the method name, with an
8321 * optional signature to bind.
8323 * For example, the following are all valid declarations:
8325 * "MyApp.Services.ScriptService:Accelerate"
8326 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8328 * You use method parameters in cases where there might be more than
8329 * one surface method to managed code. That way you can register different
8330 * internal calls for different method overloads.
8332 * The internal calls are invoked with no marshalling. This means that .NET
8333 * types like System.String are exposed as `MonoString *` parameters. This is
8334 * different than the way that strings are surfaced in P/Invoke.
8336 * For more information on how the parameters are marshalled, see the
8337 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8340 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8341 * reference for more information on the format of method descriptions.
8344 mono_add_internal_call (const char *name, gconstpointer method)
8348 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8350 mono_icall_unlock ();
8353 #ifndef DISABLE_ICALL_TABLES
8355 #ifdef HAVE_ARRAY_ELEM_INIT
8357 compare_method_imap (const void *key, const void *elem)
8359 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8360 return strcmp (key, method_name);
8364 find_method_icall (const IcallTypeDesc *imap, const char *name)
8366 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);
8369 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8373 compare_class_imap (const void *key, const void *elem)
8375 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8376 return strcmp (key, class_name);
8379 static const IcallTypeDesc*
8380 find_class_icalls (const char *name)
8382 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);
8385 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8388 #else /* HAVE_ARRAY_ELEM_INIT */
8391 compare_method_imap (const void *key, const void *elem)
8393 const char** method_name = (const char**)elem;
8394 return strcmp (key, *method_name);
8398 find_method_icall (const IcallTypeDesc *imap, const char *name)
8400 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8403 return (gpointer)icall_functions [(nameslot - icall_names)];
8407 compare_class_imap (const void *key, const void *elem)
8409 const char** class_name = (const char**)elem;
8410 return strcmp (key, *class_name);
8413 static const IcallTypeDesc*
8414 find_class_icalls (const char *name)
8416 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8419 return &icall_type_descs [nameslot - icall_type_names];
8422 #endif /* HAVE_ARRAY_ELEM_INIT */
8424 #endif /* DISABLE_ICALL_TABLES */
8427 * we should probably export this as an helper (handle nested types).
8428 * Returns the number of chars written in buf.
8431 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8433 int nspacelen, cnamelen;
8434 nspacelen = strlen (klass->name_space);
8435 cnamelen = strlen (klass->name);
8436 if (nspacelen + cnamelen + 2 > bufsize)
8439 memcpy (buf, klass->name_space, nspacelen);
8440 buf [nspacelen ++] = '.';
8442 memcpy (buf + nspacelen, klass->name, cnamelen);
8443 buf [nspacelen + cnamelen] = 0;
8444 return nspacelen + cnamelen;
8447 #ifdef DISABLE_ICALL_TABLES
8449 no_icall_table (void)
8451 g_assert_not_reached ();
8456 mono_lookup_internal_call (MonoMethod *method)
8461 int typelen = 0, mlen, siglen;
8463 #ifndef DISABLE_ICALL_TABLES
8464 const IcallTypeDesc *imap = NULL;
8467 g_assert (method != NULL);
8469 if (method->is_inflated)
8470 method = ((MonoMethodInflated *) method)->declaring;
8472 if (method->klass->nested_in) {
8473 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8477 mname [pos++] = '/';
8480 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8486 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8491 #ifndef DISABLE_ICALL_TABLES
8492 imap = find_class_icalls (mname);
8495 mname [typelen] = ':';
8496 mname [typelen + 1] = ':';
8498 mlen = strlen (method->name);
8499 memcpy (mname + typelen + 2, method->name, mlen);
8500 sigstart = mname + typelen + 2 + mlen;
8503 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8504 siglen = strlen (tmpsig);
8505 if (typelen + mlen + siglen + 6 > sizeof (mname))
8508 memcpy (sigstart + 1, tmpsig, siglen);
8509 sigstart [siglen + 1] = ')';
8510 sigstart [siglen + 2] = 0;
8515 res = g_hash_table_lookup (icall_hash, mname);
8517 mono_icall_unlock ();;
8520 /* try without signature */
8522 res = g_hash_table_lookup (icall_hash, mname);
8524 mono_icall_unlock ();
8528 #ifdef DISABLE_ICALL_TABLES
8529 mono_icall_unlock ();
8530 /* Fail only when the result is actually used */
8531 /* mono_marshal_get_native_wrapper () depends on this */
8532 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8533 return ves_icall_System_String_ctor_RedirectToCreateString;
8535 return no_icall_table;
8537 /* it wasn't found in the static call tables */
8539 mono_icall_unlock ();
8542 res = find_method_icall (imap, sigstart - mlen);
8544 mono_icall_unlock ();
8547 /* try _with_ signature */
8549 res = find_method_icall (imap, sigstart - mlen);
8551 mono_icall_unlock ();
8555 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8556 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8557 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8558 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8559 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");
8560 g_print ("If you see other errors or faults after this message they are probably related\n");
8561 g_print ("and you need to fix your mono install first.\n");
8563 mono_icall_unlock ();
8569 #ifdef ENABLE_ICALL_SYMBOL_MAP
8571 func_cmp (gconstpointer key, gconstpointer p)
8573 return (gsize)key - (gsize)*(gsize*)p;
8578 * mono_lookup_icall_symbol:
8580 * Given the icall METHOD, returns its C symbol.
8583 mono_lookup_icall_symbol (MonoMethod *m)
8585 #ifdef DISABLE_ICALL_TABLES
8586 g_assert_not_reached ();
8589 #ifdef ENABLE_ICALL_SYMBOL_MAP
8593 static gconstpointer *functions_sorted;
8594 static const char**symbols_sorted;
8595 static gboolean inited;
8600 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8601 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8602 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8603 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8604 /* Bubble sort the two arrays */
8608 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8609 if (functions_sorted [i] > functions_sorted [i + 1]) {
8612 tmp = functions_sorted [i];
8613 functions_sorted [i] = functions_sorted [i + 1];
8614 functions_sorted [i + 1] = tmp;
8615 tmp = symbols_sorted [i];
8616 symbols_sorted [i] = symbols_sorted [i + 1];
8617 symbols_sorted [i + 1] = tmp;
8624 func = mono_lookup_internal_call (m);
8627 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8631 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8633 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8634 g_assert_not_reached ();
8641 type_from_typename (char *type_name)
8643 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8645 if (!strcmp (type_name, "int"))
8646 klass = mono_defaults.int_class;
8647 else if (!strcmp (type_name, "ptr"))
8648 klass = mono_defaults.int_class;
8649 else if (!strcmp (type_name, "void"))
8650 klass = mono_defaults.void_class;
8651 else if (!strcmp (type_name, "int32"))
8652 klass = mono_defaults.int32_class;
8653 else if (!strcmp (type_name, "uint32"))
8654 klass = mono_defaults.uint32_class;
8655 else if (!strcmp (type_name, "int8"))
8656 klass = mono_defaults.sbyte_class;
8657 else if (!strcmp (type_name, "uint8"))
8658 klass = mono_defaults.byte_class;
8659 else if (!strcmp (type_name, "int16"))
8660 klass = mono_defaults.int16_class;
8661 else if (!strcmp (type_name, "uint16"))
8662 klass = mono_defaults.uint16_class;
8663 else if (!strcmp (type_name, "long"))
8664 klass = mono_defaults.int64_class;
8665 else if (!strcmp (type_name, "ulong"))
8666 klass = mono_defaults.uint64_class;
8667 else if (!strcmp (type_name, "float"))
8668 klass = mono_defaults.single_class;
8669 else if (!strcmp (type_name, "double"))
8670 klass = mono_defaults.double_class;
8671 else if (!strcmp (type_name, "object"))
8672 klass = mono_defaults.object_class;
8673 else if (!strcmp (type_name, "obj"))
8674 klass = mono_defaults.object_class;
8675 else if (!strcmp (type_name, "string"))
8676 klass = mono_defaults.string_class;
8677 else if (!strcmp (type_name, "bool"))
8678 klass = mono_defaults.boolean_class;
8679 else if (!strcmp (type_name, "boolean"))
8680 klass = mono_defaults.boolean_class;
8682 g_error ("%s", type_name);
8683 g_assert_not_reached ();
8685 return &klass->byval_arg;
8689 * LOCKING: Take the corlib image lock.
8691 MonoMethodSignature*
8692 mono_create_icall_signature (const char *sigstr)
8697 MonoMethodSignature *res, *res2;
8698 MonoImage *corlib = mono_defaults.corlib;
8700 mono_image_lock (corlib);
8701 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8702 mono_image_unlock (corlib);
8707 parts = g_strsplit (sigstr, " ", 256);
8716 res = mono_metadata_signature_alloc (corlib, len - 1);
8721 * Under windows, the default pinvoke calling convention is STDCALL but
8724 res->call_convention = MONO_CALL_C;
8727 res->ret = type_from_typename (parts [0]);
8728 for (i = 1; i < len; ++i) {
8729 res->params [i - 1] = type_from_typename (parts [i]);
8734 mono_image_lock (corlib);
8735 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8737 res = res2; /*Value is allocated in the image pool*/
8739 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8740 mono_image_unlock (corlib);
8746 mono_find_jit_icall_by_name (const char *name)
8748 MonoJitICallInfo *info;
8749 g_assert (jit_icall_hash_name);
8752 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8753 mono_icall_unlock ();
8758 mono_find_jit_icall_by_addr (gconstpointer addr)
8760 MonoJitICallInfo *info;
8761 g_assert (jit_icall_hash_addr);
8764 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8765 mono_icall_unlock ();
8771 * mono_get_jit_icall_info:
8773 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8774 * caller should access it while holding the icall lock.
8777 mono_get_jit_icall_info (void)
8779 return jit_icall_hash_name;
8783 * mono_lookup_jit_icall_symbol:
8785 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8788 mono_lookup_jit_icall_symbol (const char *name)
8790 MonoJitICallInfo *info;
8791 const char *res = NULL;
8794 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8796 res = info->c_symbol;
8797 mono_icall_unlock ();
8802 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8805 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8806 mono_icall_unlock ();
8810 * 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
8811 * icalls without wrappers in some cases.
8814 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8816 MonoJitICallInfo *info;
8823 if (!jit_icall_hash_name) {
8824 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8825 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8828 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8829 g_warning ("jit icall already defined \"%s\"\n", name);
8830 g_assert_not_reached ();
8833 info = g_new0 (MonoJitICallInfo, 1);
8838 info->c_symbol = c_symbol;
8839 info->no_raise = no_raise;
8842 info->wrapper = func;
8844 info->wrapper = NULL;
8847 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8848 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8850 mono_icall_unlock ();
8855 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8857 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);