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, &error)) {
3080 mono_error_set_pending_exception (&error);
3084 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3085 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3086 mono_error_cleanup (&error); /* FIXME does this make sense? */
3087 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3092 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3093 if (!is_ok (&error)) {
3094 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3097 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3098 char *target_name = mono_type_get_full_name (m->klass);
3099 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3100 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3102 g_free (target_name);
3106 m = mono_object_get_virtual_method (this_arg, m);
3107 /* must pass the pointer to the value for valuetype methods */
3108 if (m->klass->valuetype)
3109 obj = mono_object_unbox (this_arg);
3110 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3111 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3116 if (sig->ret->byref) {
3117 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"));
3121 pcount = params? mono_array_length (params): 0;
3122 if (pcount != sig->param_count) {
3123 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3127 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3128 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."));
3132 image = m->klass->image;
3133 if (image->assembly->ref_only) {
3134 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."));
3138 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3139 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3143 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3147 intptr_t *lower_bounds;
3148 pcount = mono_array_length (params);
3149 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3150 /* Note: the synthetized array .ctors have int32 as argument type */
3151 for (i = 0; i < pcount; ++i)
3152 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3154 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3155 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3156 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3157 if (!mono_error_ok (&error)) {
3158 mono_error_set_pending_exception (&error);
3162 for (i = 0; i < mono_array_length (arr); ++i) {
3163 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3164 if (!mono_error_ok (&error)) {
3165 mono_error_set_pending_exception (&error);
3168 mono_array_setref_fast (arr, i, subarray);
3170 return (MonoObject*)arr;
3173 if (m->klass->rank == pcount) {
3174 /* Only lengths provided. */
3175 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3176 if (!mono_error_ok (&error)) {
3177 mono_error_set_pending_exception (&error);
3181 return (MonoObject*)arr;
3183 g_assert (pcount == (m->klass->rank * 2));
3184 /* The arguments are lower-bound-length pairs */
3185 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3187 for (i = 0; i < pcount / 2; ++i) {
3188 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3189 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3192 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3193 if (!mono_error_ok (&error)) {
3194 mono_error_set_pending_exception (&error);
3198 return (MonoObject*)arr;
3201 return mono_runtime_invoke_array (m, obj, params, NULL);
3204 #ifndef DISABLE_REMOTING
3205 ICALL_EXPORT MonoObject *
3206 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3209 MonoDomain *domain = mono_object_domain (method);
3210 MonoMethod *m = method->method;
3211 MonoMethodSignature *sig = mono_method_signature (m);
3212 MonoArray *out_args;
3214 int i, j, outarg_count = 0;
3216 if (m->klass == mono_defaults.object_class) {
3217 if (!strcmp (m->name, "FieldGetter")) {
3218 MonoClass *k = this_arg->vtable->klass;
3222 /* If this is a proxy, then it must be a CBO */
3223 if (k == mono_defaults.transparent_proxy_class) {
3224 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3225 this_arg = tp->rp->unwrapped_server;
3226 g_assert (this_arg);
3227 k = this_arg->vtable->klass;
3230 name = mono_array_get (params, MonoString *, 1);
3231 str = mono_string_to_utf8 (name);
3234 MonoClassField* field = mono_class_get_field_from_name (k, str);
3236 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3237 if (field_klass->valuetype) {
3238 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3239 mono_error_set_pending_exception (&error);
3240 /* fallthru to cleanup */
3242 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3244 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3245 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3246 mono_array_setref (out_args, 0, result);
3254 g_assert_not_reached ();
3256 } else if (!strcmp (m->name, "FieldSetter")) {
3257 MonoClass *k = this_arg->vtable->klass;
3263 /* If this is a proxy, then it must be a CBO */
3264 if (k == mono_defaults.transparent_proxy_class) {
3265 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3266 this_arg = tp->rp->unwrapped_server;
3267 g_assert (this_arg);
3268 k = this_arg->vtable->klass;
3271 name = mono_array_get (params, MonoString *, 1);
3272 str = mono_string_to_utf8 (name);
3275 MonoClassField* field = mono_class_get_field_from_name (k, str);
3277 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3278 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3280 if (field_klass->valuetype) {
3281 size = mono_type_size (field->type, &align);
3282 g_assert (size == mono_class_value_size (field_klass, NULL));
3283 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3285 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3288 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3289 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3299 g_assert_not_reached ();
3304 for (i = 0; i < mono_array_length (params); i++) {
3305 if (sig->params [i]->byref)
3309 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3311 /* handle constructors only for objects already allocated */
3312 if (!strcmp (method->method->name, ".ctor"))
3313 g_assert (this_arg);
3315 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3316 g_assert (!method->method->klass->valuetype);
3317 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3319 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3320 if (sig->params [i]->byref) {
3322 arg = mono_array_get (params, gpointer, i);
3323 mono_array_setref (out_args, j, arg);
3328 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3335 read_enum_value (const char *mem, int type)
3338 case MONO_TYPE_BOOLEAN:
3340 return *(guint8*)mem;
3342 return *(gint8*)mem;
3343 case MONO_TYPE_CHAR:
3345 return read16 (mem);
3347 return (gint16) read16 (mem);
3349 return read32 (mem);
3351 return (gint32) read32 (mem);
3354 return read64 (mem);
3356 g_assert_not_reached ();
3362 write_enum_value (char *mem, int type, guint64 value)
3366 case MONO_TYPE_I1: {
3367 guint8 *p = (guint8*)mem;
3372 case MONO_TYPE_I2: {
3373 guint16 *p = (guint16 *)mem;
3378 case MONO_TYPE_I4: {
3379 guint32 *p = (guint32 *)mem;
3384 case MONO_TYPE_I8: {
3385 guint64 *p = (guint64 *)mem;
3390 g_assert_not_reached ();
3395 ICALL_EXPORT MonoObject *
3396 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3404 domain = mono_object_domain (enumType);
3405 enumc = mono_class_from_mono_type (enumType->type);
3407 mono_class_init_checked (enumc, &error);
3408 mono_error_raise_exception (&error);
3410 etype = mono_class_enum_basetype (enumc);
3412 res = mono_object_new_checked (domain, enumc, &error);
3413 mono_error_raise_exception (&error);
3414 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3419 ICALL_EXPORT MonoBoolean
3420 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3422 int size = mono_class_value_size (a->vtable->klass, NULL);
3423 guint64 a_val = 0, b_val = 0;
3425 memcpy (&a_val, mono_object_unbox (a), size);
3426 memcpy (&b_val, mono_object_unbox (b), size);
3428 return (a_val & b_val) == b_val;
3431 ICALL_EXPORT MonoObject *
3432 ves_icall_System_Enum_get_value (MonoObject *eobj)
3444 g_assert (eobj->vtable->klass->enumtype);
3446 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3447 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3448 mono_error_raise_exception (&error);
3449 dst = (char *)res + sizeof (MonoObject);
3450 src = (char *)eobj + sizeof (MonoObject);
3451 size = mono_class_value_size (enumc, NULL);
3453 memcpy (dst, src, size);
3458 ICALL_EXPORT MonoReflectionType *
3459 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3462 MonoReflectionType *ret;
3466 klass = mono_class_from_mono_type (type->type);
3467 mono_class_init_checked (klass, &error);
3468 mono_error_raise_exception (&error);
3470 etype = mono_class_enum_basetype (klass);
3472 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3476 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3477 mono_error_raise_exception (&error);
3483 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3485 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3486 gpointer odata = (char *)other + sizeof (MonoObject);
3487 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3488 g_assert (basetype);
3493 if (eobj->vtable->klass != other->vtable->klass)
3496 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3497 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3498 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3501 return me > other ? 1 : -1; \
3504 switch (basetype->type) {
3506 COMPARE_ENUM_VALUES (guint8);
3508 COMPARE_ENUM_VALUES (gint8);
3509 case MONO_TYPE_CHAR:
3511 COMPARE_ENUM_VALUES (guint16);
3513 COMPARE_ENUM_VALUES (gint16);
3515 COMPARE_ENUM_VALUES (guint32);
3517 COMPARE_ENUM_VALUES (gint32);
3519 COMPARE_ENUM_VALUES (guint64);
3521 COMPARE_ENUM_VALUES (gint64);
3525 #undef COMPARE_ENUM_VALUES
3526 /* indicates that the enum was of an unsupported unerlying type */
3531 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3533 gpointer data = (char *)eobj + sizeof (MonoObject);
3534 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3535 g_assert (basetype);
3537 switch (basetype->type) {
3538 case MONO_TYPE_I1: {
3539 gint8 value = *((gint8*)data);
3540 return ((int)value ^ (int)value << 8);
3543 return *((guint8*)data);
3544 case MONO_TYPE_CHAR:
3546 return *((guint16*)data);
3548 case MONO_TYPE_I2: {
3549 gint16 value = *((gint16*)data);
3550 return ((int)(guint16)value | (((int)value) << 16));
3553 return *((guint32*)data);
3555 return *((gint32*)data);
3557 case MONO_TYPE_I8: {
3558 gint64 value = *((gint64*)data);
3559 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3562 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3567 ICALL_EXPORT MonoBoolean
3568 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3571 MonoDomain *domain = mono_object_domain (type);
3572 MonoClass *enumc = mono_class_from_mono_type (type->type);
3573 guint j = 0, nvalues;
3575 MonoClassField *field;
3577 guint64 field_value, previous_value = 0;
3578 gboolean sorted = TRUE;
3580 mono_class_init_checked (enumc, &error);
3581 mono_error_raise_exception (&error);
3583 if (!enumc->enumtype) {
3584 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3588 base_type = mono_class_enum_basetype (enumc)->type;
3590 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3591 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3592 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3595 while ((field = mono_class_get_fields (enumc, &iter))) {
3597 MonoTypeEnum def_type;
3599 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3601 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3603 if (mono_field_is_deleted (field))
3605 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3607 p = mono_class_get_field_default_value (field, &def_type);
3608 /* len = */ mono_metadata_decode_blob_size (p, &p);
3610 field_value = read_enum_value (p, base_type);
3611 mono_array_set (*values, guint64, j, field_value);
3613 if (previous_value > field_value)
3616 previous_value = field_value;
3624 BFLAGS_IgnoreCase = 1,
3625 BFLAGS_DeclaredOnly = 2,
3626 BFLAGS_Instance = 4,
3628 BFLAGS_Public = 0x10,
3629 BFLAGS_NonPublic = 0x20,
3630 BFLAGS_FlattenHierarchy = 0x40,
3631 BFLAGS_InvokeMethod = 0x100,
3632 BFLAGS_CreateInstance = 0x200,
3633 BFLAGS_GetField = 0x400,
3634 BFLAGS_SetField = 0x800,
3635 BFLAGS_GetProperty = 0x1000,
3636 BFLAGS_SetProperty = 0x2000,
3637 BFLAGS_ExactBinding = 0x10000,
3638 BFLAGS_SuppressChangeType = 0x20000,
3639 BFLAGS_OptionalParamBinding = 0x40000
3642 ICALL_EXPORT MonoArray*
3643 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3647 MonoClass *startklass, *klass, *refklass;
3652 char *utf8_name = NULL;
3653 int (*compare_func) (const char *s1, const char *s2) = NULL;
3654 MonoClassField *field;
3655 MonoPtrArray tmp_array;
3657 domain = ((MonoObject *)type)->vtable->domain;
3658 if (type->type->byref)
3659 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3661 klass = startklass = mono_class_from_mono_type (type->type);
3662 refklass = mono_class_from_mono_type (reftype->type);
3664 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3667 if (mono_class_has_failure (klass)) {
3668 mono_ptr_array_destroy (tmp_array);
3669 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3674 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3675 guint32 flags = mono_field_get_flags (field);
3677 if (mono_field_is_deleted_with_flags (field, flags))
3679 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3680 if (bflags & BFLAGS_Public)
3682 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3683 if (bflags & BFLAGS_NonPublic) {
3690 if (flags & FIELD_ATTRIBUTE_STATIC) {
3691 if (bflags & BFLAGS_Static)
3692 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3695 if (bflags & BFLAGS_Instance)
3703 if (utf8_name == NULL) {
3704 utf8_name = mono_string_to_utf8 (name);
3705 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3708 if (compare_func (mono_field_get_name (field), utf8_name))
3712 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3713 if (!mono_error_ok (&error))
3715 mono_ptr_array_append (tmp_array, member);
3717 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3720 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3722 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3723 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3725 mono_ptr_array_destroy (tmp_array);
3727 if (utf8_name != NULL)
3732 mono_ptr_array_destroy (tmp_array);
3733 mono_error_raise_exception (&error);
3734 g_assert_not_reached ();
3738 method_nonpublic (MonoMethod* method, gboolean start_klass)
3740 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3741 case METHOD_ATTRIBUTE_ASSEM:
3742 return (start_klass || mono_defaults.generic_ilist_class);
3743 case METHOD_ATTRIBUTE_PRIVATE:
3745 case METHOD_ATTRIBUTE_PUBLIC:
3753 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3756 MonoClass *startklass;
3760 /*FIXME, use MonoBitSet*/
3761 guint32 method_slots_default [8];
3762 guint32 *method_slots = NULL;
3763 int (*compare_func) (const char *s1, const char *s2) = NULL;
3765 array = g_ptr_array_new ();
3770 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3772 /* An optimization for calls made from Delegate:CreateDelegate () */
3773 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3774 method = mono_get_delegate_invoke (klass);
3775 if (mono_loader_get_last_error ())
3778 g_ptr_array_add (array, method);
3782 mono_class_setup_methods (klass);
3783 mono_class_setup_vtable (klass);
3784 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3787 if (is_generic_parameter (&klass->byval_arg))
3788 nslots = mono_class_get_vtable_size (klass->parent);
3790 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3791 if (nslots >= sizeof (method_slots_default) * 8) {
3792 method_slots = g_new0 (guint32, nslots / 32 + 1);
3794 method_slots = method_slots_default;
3795 memset (method_slots, 0, sizeof (method_slots_default));
3798 mono_class_setup_methods (klass);
3799 mono_class_setup_vtable (klass);
3800 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3804 while ((method = mono_class_get_methods (klass, &iter))) {
3806 if (method->slot != -1) {
3807 g_assert (method->slot < nslots);
3808 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3810 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3811 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3814 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3816 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3817 if (bflags & BFLAGS_Public)
3819 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3825 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3826 if (bflags & BFLAGS_Static)
3827 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3830 if (bflags & BFLAGS_Instance)
3838 if (compare_func (name, method->name))
3843 g_ptr_array_add (array, method);
3845 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3847 if (method_slots != method_slots_default)
3848 g_free (method_slots);
3853 if (method_slots != method_slots_default)
3854 g_free (method_slots);
3855 g_ptr_array_free (array, TRUE);
3857 if (mono_class_has_failure (klass)) {
3858 *ex = mono_class_get_exception_for_failure (klass);
3860 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3861 mono_loader_clear_error ();
3866 ICALL_EXPORT MonoArray*
3867 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3869 static MonoClass *MethodInfo_array;
3873 MonoVTable *array_vtable;
3874 MonoException *ex = NULL;
3875 const char *mname = NULL;
3876 GPtrArray *method_array;
3877 MonoClass *klass, *refklass;
3880 mono_error_init (&error);
3882 if (!MethodInfo_array) {
3883 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3884 mono_memory_barrier ();
3885 MethodInfo_array = klass;
3888 klass = mono_class_from_mono_type (type->type);
3889 refklass = mono_class_from_mono_type (reftype->type);
3890 domain = ((MonoObject *)type)->vtable->domain;
3891 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3892 if (!is_ok (&error)) {
3893 mono_error_set_pending_exception (&error);
3896 if (type->type->byref) {
3897 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3898 mono_error_set_pending_exception (&error);
3904 mname = mono_string_to_utf8 (name);
3906 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3907 g_free ((char*)mname);
3909 mono_set_pending_exception (ex);
3913 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3914 if (!mono_error_ok (&error)) {
3915 mono_error_set_pending_exception (&error);
3919 for (i = 0; i < method_array->len; ++i) {
3920 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3921 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3922 if (!mono_error_ok (&error))
3924 mono_array_setref (res, i, rm);
3928 g_ptr_array_free (method_array, TRUE);
3929 if (!mono_error_ok (&error))
3930 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3934 ICALL_EXPORT MonoArray*
3935 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3938 MonoClass *startklass, *klass, *refklass;
3943 gpointer iter = NULL;
3944 MonoPtrArray tmp_array;
3947 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3949 domain = ((MonoObject *)type)->vtable->domain;
3950 if (type->type->byref)
3951 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3952 klass = startklass = mono_class_from_mono_type (type->type);
3953 refklass = mono_class_from_mono_type (reftype->type);
3955 mono_class_setup_methods (klass);
3956 if (mono_class_has_failure (klass)) {
3957 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3962 while ((method = mono_class_get_methods (klass, &iter))) {
3964 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3966 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3967 if (bflags & BFLAGS_Public)
3970 if (bflags & BFLAGS_NonPublic)
3976 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3977 if (bflags & BFLAGS_Static)
3978 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3981 if (bflags & BFLAGS_Instance)
3987 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3988 if (!mono_error_ok (&error)) {
3989 mono_error_set_pending_exception (&error);
3993 mono_ptr_array_append (tmp_array, member);
3996 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
3998 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3999 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4001 mono_ptr_array_destroy (tmp_array);
4007 property_hash (gconstpointer data)
4009 MonoProperty *prop = (MonoProperty*)data;
4011 return g_str_hash (prop->name);
4015 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
4017 if (method1->is_inflated)
4018 method1 = ((MonoMethodInflated*) method1)->declaring;
4019 if (method2->is_inflated)
4020 method2 = ((MonoMethodInflated*) method2)->declaring;
4022 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4026 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4028 // Properties are hide-by-name-and-signature
4029 if (!g_str_equal (prop1->name, prop2->name))
4032 /* If we see a property in a generic method, we want to
4033 compare the generic signatures, not the inflated signatures
4034 because we might conflate two properties that were
4038 public T this[T t] { getter { return t; } } // method 1
4039 public U this[U u] { getter { return u; } } // method 2
4042 If we see int Foo<int,int>::Item[int] we need to know if
4043 the indexer came from method 1 or from method 2, and we
4044 shouldn't conflate them. (Bugzilla 36283)
4046 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
4049 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4056 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4061 return method_nonpublic (accessor, start_klass);
4064 ICALL_EXPORT MonoArray*
4065 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4069 MonoClass *startklass, *klass;
4075 gchar *propname = NULL;
4076 int (*compare_func) (const char *s1, const char *s2) = NULL;
4078 GHashTable *properties = NULL;
4079 MonoPtrArray tmp_array;
4081 mono_error_init (&error);
4083 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4085 domain = ((MonoObject *)type)->vtable->domain;
4086 if (type->type->byref)
4087 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
4088 klass = startklass = mono_class_from_mono_type (type->type);
4091 propname = mono_string_to_utf8 (name);
4092 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4095 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4097 mono_class_setup_methods (klass);
4098 mono_class_setup_vtable (klass);
4099 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4103 while ((prop = mono_class_get_properties (klass, &iter))) {
4109 flags = method->flags;
4112 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4113 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4114 if (bflags & BFLAGS_Public)
4116 } else if (bflags & BFLAGS_NonPublic) {
4117 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4118 property_accessor_nonpublic(prop->set, startklass == klass)) {
4125 if (flags & METHOD_ATTRIBUTE_STATIC) {
4126 if (bflags & BFLAGS_Static)
4127 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4130 if (bflags & BFLAGS_Instance)
4139 if (compare_func (propname, prop->name))
4143 if (g_hash_table_lookup (properties, prop))
4146 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4149 mono_ptr_array_append (tmp_array, pr);
4151 g_hash_table_insert (properties, prop, prop);
4153 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4156 g_hash_table_destroy (properties);
4159 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4160 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4161 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4163 mono_ptr_array_destroy (tmp_array);
4170 if (mono_class_has_failure (klass)) {
4171 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4173 mono_error_set_from_loader_error (&error);
4174 mono_loader_clear_error ();
4179 g_hash_table_destroy (properties);
4182 mono_ptr_array_destroy (tmp_array);
4184 mono_error_set_pending_exception (&error);
4190 event_hash (gconstpointer data)
4192 MonoEvent *event = (MonoEvent*)data;
4194 return g_str_hash (event->name);
4198 event_equal (MonoEvent *event1, MonoEvent *event2)
4200 // Events are hide-by-name
4201 return g_str_equal (event1->name, event2->name);
4204 ICALL_EXPORT MonoArray*
4205 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4209 MonoClass *startklass, *klass;
4215 char *utf8_name = NULL;
4216 int (*compare_func) (const char *s1, const char *s2) = NULL;
4217 GHashTable *events = NULL;
4218 MonoPtrArray tmp_array;
4220 mono_error_init (&error);
4222 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4224 domain = mono_object_domain (type);
4225 if (type->type->byref)
4226 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4227 klass = startklass = mono_class_from_mono_type (type->type);
4229 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4231 mono_class_setup_methods (klass);
4232 mono_class_setup_vtable (klass);
4233 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4237 while ((event = mono_class_get_events (klass, &iter))) {
4239 method = event->add;
4241 method = event->remove;
4243 method = event->raise;
4245 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4246 if (bflags & BFLAGS_Public)
4248 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4249 if (bflags & BFLAGS_NonPublic)
4254 if (bflags & BFLAGS_NonPublic)
4260 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4261 if (bflags & BFLAGS_Static)
4262 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4265 if (bflags & BFLAGS_Instance)
4270 if (bflags & BFLAGS_Instance)
4276 if (utf8_name == NULL) {
4277 utf8_name = mono_string_to_utf8 (name);
4278 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4281 if (compare_func (event->name, utf8_name))
4285 if (g_hash_table_lookup (events, event))
4288 MonoReflectionEvent *ev_obj;
4289 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4292 mono_ptr_array_append (tmp_array, ev_obj);
4294 g_hash_table_insert (events, event, event);
4296 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4299 g_hash_table_destroy (events);
4301 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4303 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4304 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4306 mono_ptr_array_destroy (tmp_array);
4308 if (utf8_name != NULL)
4314 if (mono_class_has_failure (klass)) {
4315 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4317 mono_error_set_from_loader_error (&error);
4318 mono_loader_clear_error ();
4324 g_hash_table_destroy (events);
4325 if (utf8_name != NULL)
4328 mono_ptr_array_destroy (tmp_array);
4330 mono_error_set_pending_exception (&error);
4334 ICALL_EXPORT MonoArray*
4335 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4338 MonoReflectionType *rt;
4346 MonoPtrArray tmp_array;
4348 domain = ((MonoObject *)type)->vtable->domain;
4349 if (type->type->byref)
4350 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4351 klass = mono_class_from_mono_type (type->type);
4354 * If a nested type is generic, return its generic type definition.
4355 * Note that this means that the return value is essentially the set
4356 * of nested types of the generic type definition of @klass.
4358 * A note in MSDN claims that a generic type definition can have
4359 * nested types that aren't generic. In any case, the container of that
4360 * nested type would be the generic type definition.
4362 if (klass->generic_class)
4363 klass = klass->generic_class->container_class;
4365 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4367 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4369 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4370 if (bflags & BFLAGS_Public)
4373 if (bflags & BFLAGS_NonPublic)
4381 str = mono_string_to_utf8 (name);
4382 mono_identifier_unescape_type_name_chars (str);
4385 if (strcmp (nested->name, str))
4389 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4390 mono_error_raise_exception (&error);
4392 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4395 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4397 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4398 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4400 mono_ptr_array_destroy (tmp_array);
4407 ICALL_EXPORT MonoReflectionType*
4408 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4411 MonoReflectionType *ret;
4413 MonoType *type = NULL;
4414 MonoTypeNameParse info;
4415 gboolean type_resolve;
4417 /* On MS.NET, this does not fire a TypeResolve event */
4418 type_resolve = TRUE;
4419 str = mono_string_to_utf8 (name);
4420 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4421 if (!mono_reflection_parse_type (str, &info)) {
4423 mono_reflection_free_type_info (&info);
4425 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4428 /*g_print ("failed parse\n");*/
4432 if (info.assembly.name) {
4434 mono_reflection_free_type_info (&info);
4436 /* 1.0 and 2.0 throw different exceptions */
4437 if (mono_defaults.generic_ilist_class)
4438 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4440 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4446 if (module != NULL) {
4447 if (module->image) {
4448 type = mono_reflection_get_type_checked (module->image, &info, ignoreCase, &type_resolve, &error);
4449 if (!is_ok (&error)) {
4451 mono_reflection_free_type_info (&info);
4452 mono_error_set_pending_exception (&error);
4459 if (assembly_is_dynamic (assembly->assembly)) {
4460 /* Enumerate all modules */
4461 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4465 if (abuilder->modules) {
4466 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4467 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4468 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4469 if (!is_ok (&error)) {
4471 mono_reflection_free_type_info (&info);
4472 mono_error_set_pending_exception (&error);
4480 if (!type && abuilder->loaded_modules) {
4481 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4482 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4483 type = mono_reflection_get_type_checked (mod->image, &info, ignoreCase, &type_resolve, &error);
4484 if (!is_ok (&error)) {
4486 mono_reflection_free_type_info (&info);
4487 mono_error_set_pending_exception (&error);
4496 type = mono_reflection_get_type_checked (assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4497 if (!is_ok (&error)) {
4499 mono_reflection_free_type_info (&info);
4500 mono_error_set_pending_exception (&error);
4505 mono_reflection_free_type_info (&info);
4507 MonoException *e = NULL;
4510 e = mono_get_exception_type_load (name, NULL);
4512 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4513 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4515 mono_loader_clear_error ();
4518 mono_set_pending_exception (e);
4520 } else if (mono_loader_get_last_error ()) {
4522 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4525 mono_loader_clear_error ();
4528 if (type->type == MONO_TYPE_CLASS) {
4529 MonoClass *klass = mono_type_get_class (type);
4531 /* need to report exceptions ? */
4532 if (throwOnError && mono_class_has_failure (klass)) {
4533 /* report SecurityException (or others) that occured when loading the assembly */
4534 MonoException *exc = mono_class_get_exception_for_failure (klass);
4535 mono_loader_clear_error ();
4536 mono_set_pending_exception (exc);
4541 /* g_print ("got it\n"); */
4542 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4543 mono_error_set_pending_exception (&error);
4549 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4552 gchar *shadow_ini_file;
4555 /* Check for shadow-copied assembly */
4556 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4557 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4559 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4560 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4566 g_free (shadow_ini_file);
4567 if (content != NULL) {
4570 *filename = content;
4577 ICALL_EXPORT MonoString *
4578 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4580 MonoDomain *domain = mono_object_domain (assembly);
4581 MonoAssembly *mass = assembly->assembly;
4582 MonoString *res = NULL;
4587 if (g_path_is_absolute (mass->image->name)) {
4588 absolute = g_strdup (mass->image->name);
4589 dirname = g_path_get_dirname (absolute);
4591 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4592 dirname = g_strdup (mass->basedir);
4595 replace_shadow_path (domain, dirname, &absolute);
4600 for (i = strlen (absolute) - 1; i >= 0; i--)
4601 if (absolute [i] == '\\')
4606 uri = g_filename_to_uri (absolute, NULL, NULL);
4608 const char *prepend = "file://";
4610 if (*absolute == '/' && *(absolute + 1) == '/') {
4613 prepend = "file:///";
4616 uri = g_strconcat (prepend, absolute, NULL);
4620 res = mono_string_new (domain, uri);
4627 ICALL_EXPORT MonoBoolean
4628 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4630 MonoAssembly *mass = assembly->assembly;
4632 return mass->in_gac;
4635 ICALL_EXPORT MonoReflectionAssembly*
4636 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4641 MonoImageOpenStatus status;
4642 MonoReflectionAssembly* result = NULL;
4644 name = mono_string_to_utf8 (mname);
4645 res = mono_assembly_load_with_partial_name (name, &status);
4651 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4653 mono_error_set_pending_exception (&error);
4657 ICALL_EXPORT MonoString *
4658 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4660 MonoDomain *domain = mono_object_domain (assembly);
4663 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4668 ICALL_EXPORT MonoBoolean
4669 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4671 return assembly->assembly->ref_only;
4674 ICALL_EXPORT MonoString *
4675 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4677 MonoDomain *domain = mono_object_domain (assembly);
4679 return mono_string_new (domain, assembly->assembly->image->version);
4682 ICALL_EXPORT MonoReflectionMethod*
4683 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4686 MonoReflectionMethod *res = NULL;
4689 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4693 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4694 if (!mono_error_ok (&error))
4697 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4700 if (!mono_error_ok (&error))
4701 mono_error_set_pending_exception (&error);
4705 ICALL_EXPORT MonoReflectionModule*
4706 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4709 MonoReflectionModule *result = NULL;
4710 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4711 if (!mono_error_ok (&error))
4712 mono_error_set_pending_exception (&error);
4716 ICALL_EXPORT MonoArray*
4717 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4719 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4720 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4724 for (i = 0; i < table->rows; ++i) {
4725 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4726 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4732 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4734 static MonoMethod *create_version = NULL;
4738 mono_error_init (error);
4741 if (!create_version) {
4742 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4743 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4744 g_assert (create_version);
4745 mono_method_desc_free (desc);
4751 args [3] = &revision;
4752 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4753 return_val_if_nok (error, NULL);
4755 mono_runtime_invoke_checked (create_version, result, args, error);
4756 return_val_if_nok (error, NULL);
4761 ICALL_EXPORT MonoArray*
4762 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4766 MonoDomain *domain = mono_object_domain (assembly);
4768 static MonoMethod *create_culture = NULL;
4769 MonoImage *image = assembly->assembly->image;
4773 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4776 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4778 if (count > 0 && !create_culture) {
4779 MonoMethodDesc *desc = mono_method_desc_new (
4780 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4781 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4782 g_assert (create_culture);
4783 mono_method_desc_free (desc);
4786 for (i = 0; i < count; i++) {
4787 MonoObject *version;
4788 MonoReflectionAssemblyName *aname;
4789 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4791 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4793 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4794 domain, mono_class_get_assembly_name_class (), &error);
4795 mono_error_raise_exception (&error);
4797 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4799 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4800 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4801 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4802 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4803 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4804 aname->versioncompat = 1; /* SameMachine (default) */
4805 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4807 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4808 mono_error_raise_exception (&error);
4810 MONO_OBJECT_SETREF (aname, version, version);
4812 if (create_culture) {
4814 MonoBoolean assembly_ref = 1;
4815 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4816 args [1] = &assembly_ref;
4818 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4819 mono_error_raise_exception (&error);
4821 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4824 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4825 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4826 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4828 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4829 /* public key token isn't copied - the class library will
4830 automatically generate it from the public key if required */
4831 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4832 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4834 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4835 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4838 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4841 /* note: this function doesn't return the codebase on purpose (i.e. it can
4842 be used under partial trust as path information isn't present). */
4844 mono_array_setref (result, i, aname);
4849 /* move this in some file in mono/util/ */
4851 g_concat_dir_and_file (const char *dir, const char *file)
4853 g_return_val_if_fail (dir != NULL, NULL);
4854 g_return_val_if_fail (file != NULL, NULL);
4857 * If the directory name doesn't have a / on the end, we need
4858 * to add one so we get a proper path to the file
4860 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4861 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4863 return g_strconcat (dir, file, NULL);
4867 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4870 char *n = mono_string_to_utf8 (name);
4871 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4873 guint32 cols [MONO_MANIFEST_SIZE];
4874 guint32 impl, file_idx;
4878 for (i = 0; i < table->rows; ++i) {
4879 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4880 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4881 if (strcmp (val, n) == 0)
4885 if (i == table->rows)
4888 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4891 * this code should only be called after obtaining the
4892 * ResourceInfo and handling the other cases.
4894 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4895 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4897 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4902 module = assembly->assembly->image;
4905 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4906 mono_error_raise_exception (&error);
4907 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4909 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4912 ICALL_EXPORT gboolean
4913 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4916 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4918 guint32 cols [MONO_MANIFEST_SIZE];
4919 guint32 file_cols [MONO_FILE_SIZE];
4923 n = mono_string_to_utf8 (name);
4924 for (i = 0; i < table->rows; ++i) {
4925 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4926 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4927 if (strcmp (val, n) == 0)
4931 if (i == table->rows)
4934 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4935 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4938 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4939 case MONO_IMPLEMENTATION_FILE:
4940 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4941 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4942 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4943 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4944 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4945 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4948 info->location = RESOURCE_LOCATION_EMBEDDED;
4951 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4952 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4953 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4954 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4955 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4956 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4958 mono_set_pending_exception (ex);
4961 MonoReflectionAssembly *assm_obj;
4962 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4964 mono_error_set_pending_exception (&error);
4967 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4969 /* Obtain info recursively */
4970 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4971 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4974 case MONO_IMPLEMENTATION_EXP_TYPE:
4975 g_assert_not_reached ();
4983 ICALL_EXPORT MonoObject*
4984 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4986 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4987 MonoArray *result = NULL;
4992 /* check hash if needed */
4994 n = mono_string_to_utf8 (name);
4995 for (i = 0; i < table->rows; ++i) {
4996 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4997 if (strcmp (val, n) == 0) {
5000 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5001 fn = mono_string_new (mono_object_domain (assembly), n);
5003 return (MonoObject*)fn;
5011 for (i = 0; i < table->rows; ++i) {
5012 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5016 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
5019 for (i = 0; i < table->rows; ++i) {
5020 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5021 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5022 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5023 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5028 return (MonoObject*)result;
5031 ICALL_EXPORT MonoArray*
5032 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5035 MonoDomain *domain = mono_domain_get();
5038 int i, j, file_count = 0;
5039 MonoImage **modules;
5040 guint32 module_count, real_module_count;
5041 MonoTableInfo *table;
5042 guint32 cols [MONO_FILE_SIZE];
5043 MonoImage *image = assembly->assembly->image;
5045 g_assert (image != NULL);
5046 g_assert (!assembly_is_dynamic (assembly->assembly));
5048 table = &image->tables [MONO_TABLE_FILE];
5049 file_count = table->rows;
5051 modules = image->modules;
5052 module_count = image->module_count;
5054 real_module_count = 0;
5055 for (i = 0; i < module_count; ++i)
5057 real_module_count ++;
5059 klass = mono_class_get_module_class ();
5060 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
5062 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5063 mono_error_raise_exception (&error);
5064 mono_array_setref (res, 0, image_obj);
5066 for (i = 0; i < module_count; ++i)
5068 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5069 mono_error_raise_exception (&error);
5070 mono_array_setref (res, j, rm);
5074 for (i = 0; i < file_count; ++i, ++j) {
5075 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5076 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5077 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5078 mono_error_raise_exception (&error);
5079 mono_array_setref (res, j, rm);
5082 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5084 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5085 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5088 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5089 mono_error_raise_exception (&error);
5090 mono_array_setref (res, j, rm);
5097 ICALL_EXPORT MonoReflectionMethod*
5098 ves_icall_GetCurrentMethod (void)
5100 MonoReflectionMethod *res = NULL;
5103 MonoMethod *m = mono_method_get_last_managed ();
5106 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5110 while (m->is_inflated)
5111 m = ((MonoMethodInflated*)m)->declaring;
5113 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5114 mono_error_raise_exception (&error);
5120 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5123 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5126 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5127 //method is inflated, we should inflate it on the other class
5128 MonoGenericContext ctx;
5129 ctx.method_inst = inflated->context.method_inst;
5130 ctx.class_inst = inflated->context.class_inst;
5131 if (klass->generic_class)
5132 ctx.class_inst = klass->generic_class->context.class_inst;
5133 else if (klass->generic_container)
5134 ctx.class_inst = klass->generic_container->context.class_inst;
5135 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5136 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5140 mono_class_setup_methods (method->klass);
5141 if (mono_class_has_failure (method->klass))
5143 for (i = 0; i < method->klass->method.count; ++i) {
5144 if (method->klass->methods [i] == method) {
5149 mono_class_setup_methods (klass);
5150 if (mono_class_has_failure (klass))
5152 g_assert (offset >= 0 && offset < klass->method.count);
5153 return klass->methods [offset];
5156 ICALL_EXPORT MonoReflectionMethod*
5157 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5159 MonoReflectionMethod *res = NULL;
5163 klass = mono_class_from_mono_type (type);
5164 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5166 if (method->klass != klass) {
5167 method = mono_method_get_equivalent_method (method, klass);
5172 klass = method->klass;
5173 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5174 mono_error_raise_exception (&error);
5178 ICALL_EXPORT MonoReflectionMethodBody*
5179 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5182 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5183 mono_error_set_pending_exception (&error);
5187 ICALL_EXPORT MonoReflectionAssembly*
5188 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5191 MonoReflectionAssembly *result;
5192 MonoMethod *dest = NULL;
5194 mono_stack_walk_no_il (get_executing, &dest);
5196 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5198 mono_error_set_pending_exception (&error);
5203 ICALL_EXPORT MonoReflectionAssembly*
5204 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5207 MonoReflectionAssembly *result;
5208 MonoDomain* domain = mono_domain_get ();
5210 if (!domain->entry_assembly)
5213 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5215 mono_error_set_pending_exception (&error);
5219 ICALL_EXPORT MonoReflectionAssembly*
5220 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5225 MonoReflectionAssembly *result;
5228 mono_stack_walk_no_il (get_executing, &dest);
5230 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5234 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5237 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5239 mono_error_set_pending_exception (&error);
5243 ICALL_EXPORT MonoString *
5244 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5245 gboolean assembly_qualified)
5247 MonoDomain *domain = mono_object_domain (object);
5248 MonoTypeNameFormat format;
5253 format = assembly_qualified ?
5254 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5255 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5257 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5259 name = mono_type_get_name_full (object->type, format);
5263 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5268 res = mono_string_new (domain, name);
5275 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5278 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5280 mono_class_init_checked (klass, &error);
5281 mono_error_raise_exception (&error);
5282 return mono_security_core_clr_class_level (klass);
5286 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5288 MonoClassField *field = rfield->field;
5289 return mono_security_core_clr_field_level (field, TRUE);
5293 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5295 MonoMethod *method = rfield->method;
5296 return mono_security_core_clr_method_level (method, TRUE);
5300 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)
5302 static MonoMethod *create_culture = NULL;
5306 const char *pkey_ptr;
5308 MonoBoolean assembly_ref = 0;
5310 mono_error_init (error);
5312 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5313 aname->major = name->major;
5314 aname->minor = name->minor;
5315 aname->build = name->build;
5316 aname->flags = name->flags;
5317 aname->revision = name->revision;
5318 aname->hashalg = name->hash_alg;
5319 aname->versioncompat = 1; /* SameMachine (default) */
5320 aname->processor_architecture = name->arch;
5322 if (by_default_version) {
5323 MonoObject *version;
5325 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5326 return_if_nok (error);
5328 MONO_OBJECT_SETREF (aname, version, version);
5332 if (absolute != NULL && *absolute != '\0') {
5333 const gchar *prepend = "file://";
5336 codebase = g_strdup (absolute);
5341 for (i = strlen (codebase) - 1; i >= 0; i--)
5342 if (codebase [i] == '\\')
5345 if (*codebase == '/' && *(codebase + 1) == '/') {
5348 prepend = "file:///";
5352 result = g_strconcat (prepend, codebase, NULL);
5358 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5362 if (!create_culture) {
5363 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5364 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5365 g_assert (create_culture);
5366 mono_method_desc_free (desc);
5369 if (name->culture) {
5370 args [0] = mono_string_new (domain, name->culture);
5371 args [1] = &assembly_ref;
5373 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5374 return_if_nok (error);
5376 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5379 if (name->public_key) {
5380 pkey_ptr = (char*)name->public_key;
5381 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5383 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5384 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5385 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5386 } else if (default_publickey) {
5387 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5388 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5391 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5392 if (name->public_key_token [0]) {
5396 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5397 p = mono_array_addr (aname->keyToken, char, 0);
5399 for (i = 0, j = 0; i < 8; i++) {
5400 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5401 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5404 } else if (default_token) {
5405 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5409 ICALL_EXPORT MonoString *
5410 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5412 MonoDomain *domain = mono_object_domain (assembly);
5413 MonoAssembly *mass = assembly->assembly;
5417 name = mono_stringify_assembly_name (&mass->aname);
5418 res = mono_string_new (domain, name);
5425 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5429 MonoAssembly *mass = assembly->assembly;
5431 if (g_path_is_absolute (mass->image->name)) {
5432 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5433 mono_error_set_pending_exception (&error);
5436 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5438 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5439 mono_error_set_pending_exception (&error);
5445 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5449 MonoImageOpenStatus status = MONO_IMAGE_OK;
5452 MonoAssemblyName name;
5455 filename = mono_string_to_utf8 (fname);
5457 dirname = g_path_get_dirname (filename);
5458 replace_shadow_path (mono_domain_get (), dirname, &filename);
5461 image = mono_image_open (filename, &status);
5467 if (status == MONO_IMAGE_IMAGE_INVALID)
5468 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5470 exc = mono_get_exception_file_not_found2 (NULL, fname);
5471 mono_set_pending_exception (exc);
5475 res = mono_assembly_fill_assembly_name (image, &name);
5477 mono_image_close (image);
5479 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5483 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5484 mono_error_set_pending_exception (&error);
5486 mono_image_close (image);
5490 ICALL_EXPORT MonoBoolean
5491 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5492 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5494 MonoBoolean result = FALSE;
5495 MonoDeclSecurityEntry entry;
5497 /* SecurityAction.RequestMinimum */
5498 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5499 *minimum = entry.blob;
5500 *minLength = entry.size;
5503 /* SecurityAction.RequestOptional */
5504 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5505 *optional = entry.blob;
5506 *optLength = entry.size;
5509 /* SecurityAction.RequestRefuse */
5510 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5511 *refused = entry.blob;
5512 *refLength = entry.size;
5520 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5522 guint32 attrs, visibility;
5524 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5525 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5526 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5529 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5535 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5537 MonoReflectionType *rt;
5540 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5543 mono_error_init (error);
5545 /* we start the count from 1 because we skip the special type <Module> */
5548 for (i = 1; i < tdef->rows; ++i) {
5549 if (mono_module_type_is_visible (tdef, image, i + 1))
5553 count = tdef->rows - 1;
5555 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5556 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5558 for (i = 1; i < tdef->rows; ++i) {
5559 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5560 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5561 mono_loader_assert_no_error (); /* Plug any leaks */
5564 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5565 return_val_if_nok (error, NULL);
5567 mono_array_setref (res, count, rt);
5569 MonoException *ex = mono_error_convert_to_exception (error);
5570 mono_array_setref (*exceptions, count, ex);
5579 ICALL_EXPORT MonoArray*
5580 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5583 MonoArray *res = NULL;
5584 MonoArray *exceptions = NULL;
5585 MonoImage *image = NULL;
5586 MonoTableInfo *table = NULL;
5589 int i, len, ex_count;
5591 domain = mono_object_domain (assembly);
5593 g_assert (!assembly_is_dynamic (assembly->assembly));
5594 image = assembly->assembly->image;
5595 table = &image->tables [MONO_TABLE_FILE];
5596 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5597 mono_error_raise_exception (&error);
5599 /* Append data from all modules in the assembly */
5600 for (i = 0; i < table->rows; ++i) {
5601 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5602 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5607 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5608 mono_error_raise_exception (&error);
5610 /* Append the new types to the end of the array */
5611 if (mono_array_length (res2) > 0) {
5613 MonoArray *res3, *ex3;
5615 len1 = mono_array_length (res);
5616 len2 = mono_array_length (res2);
5618 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5619 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5620 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5623 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5624 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5625 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5632 /* the ReflectionTypeLoadException must have all the types (Types property),
5633 * NULL replacing types which throws an exception. The LoaderException must
5634 * contain all exceptions for NULL items.
5637 len = mono_array_length (res);
5640 for (i = 0; i < len; i++) {
5641 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5645 klass = mono_type_get_class (t->type);
5646 if ((klass != NULL) && mono_class_has_failure (klass)) {
5647 /* keep the class in the list */
5648 list = g_list_append (list, klass);
5649 /* and replace Type with NULL */
5650 mono_array_setref (res, i, NULL);
5657 if (list || ex_count) {
5659 MonoException *exc = NULL;
5660 MonoArray *exl = NULL;
5661 int j, length = g_list_length (list) + ex_count;
5663 mono_loader_clear_error ();
5665 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5666 /* Types for which mono_class_get_checked () succeeded */
5667 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5668 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5669 mono_array_setref (exl, i, exc);
5671 /* Types for which it don't */
5672 for (j = 0; j < mono_array_length (exceptions); ++j) {
5673 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5675 g_assert (i < length);
5676 mono_array_setref (exl, i, exc);
5683 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5684 if (!is_ok (&error)) {
5685 mono_error_set_pending_exception (&error);
5688 mono_loader_clear_error ();
5689 mono_set_pending_exception (exc);
5696 ICALL_EXPORT gboolean
5697 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5700 MonoAssemblyName aname;
5701 MonoDomain *domain = mono_object_domain (name);
5703 gboolean is_version_defined;
5704 gboolean is_token_defined;
5706 aname.public_key = NULL;
5707 val = mono_string_to_utf8 (assname);
5708 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5709 g_free ((guint8*) aname.public_key);
5714 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5715 mono_error_set_pending_exception (&error);
5717 mono_assembly_name_free (&aname);
5718 g_free ((guint8*) aname.public_key);
5724 ICALL_EXPORT MonoReflectionType*
5725 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5728 MonoReflectionType *ret;
5729 MonoDomain *domain = mono_object_domain (module);
5732 g_assert (module->image);
5734 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5735 /* These images do not have a global type */
5738 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5739 if (!mono_error_ok (&error)) {
5740 mono_error_set_pending_exception (&error);
5744 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5745 if (!mono_error_ok (&error)) {
5746 mono_error_set_pending_exception (&error);
5754 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5756 /*if (module->image)
5757 mono_image_close (module->image);*/
5760 ICALL_EXPORT MonoString*
5761 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5763 MonoDomain *domain = mono_object_domain (module);
5765 g_assert (module->image);
5766 return mono_string_new (domain, module->image->guid);
5769 ICALL_EXPORT gpointer
5770 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5773 if (module->image && module->image->is_module_handle)
5774 return module->image->raw_data;
5777 return (gpointer) (-1);
5781 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5783 if (image_is_dynamic (image)) {
5784 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5785 *pe_kind = dyn->pe_kind;
5786 *machine = dyn->machine;
5789 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5790 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5795 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5797 return (image->md_version_major << 16) | (image->md_version_minor);
5800 ICALL_EXPORT MonoArray*
5801 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5804 MonoArray *exceptions;
5808 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5812 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5813 mono_error_raise_exception (&error);
5815 for (i = 0; i < mono_array_length (exceptions); ++i) {
5816 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5818 mono_set_pending_exception (ex);
5827 mono_memberref_is_method (MonoImage *image, guint32 token)
5829 if (!image_is_dynamic (image)) {
5830 guint32 cols [MONO_MEMBERREF_SIZE];
5832 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5833 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5834 mono_metadata_decode_blob_size (sig, &sig);
5835 return (*sig != 0x6);
5838 MonoClass *handle_class;
5840 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5841 mono_error_cleanup (&error); /* just probing, ignore error */
5845 return mono_defaults.methodhandle_class == handle_class;
5850 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5853 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5854 mono_array_addr (type_args, MonoType*, 0));
5856 context->class_inst = NULL;
5858 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5859 mono_array_addr (method_args, MonoType*, 0));
5861 context->method_inst = NULL;
5864 ICALL_EXPORT MonoType*
5865 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5868 int table = mono_metadata_token_table (token);
5869 int index = mono_metadata_token_index (token);
5870 MonoGenericContext context;
5873 *resolve_error = ResolveTokenError_Other;
5875 /* Validate token */
5876 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5877 (table != MONO_TABLE_TYPESPEC)) {
5878 *resolve_error = ResolveTokenError_BadTable;
5882 if (image_is_dynamic (image)) {
5883 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5884 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5885 mono_error_cleanup (&error);
5886 return klass ? &klass->byval_arg : NULL;
5889 init_generic_context_from_args (&context, type_args, method_args);
5890 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5891 mono_error_cleanup (&error);
5892 return klass ? &klass->byval_arg : NULL;
5895 if ((index <= 0) || (index > image->tables [table].rows)) {
5896 *resolve_error = ResolveTokenError_OutOfRange;
5900 init_generic_context_from_args (&context, type_args, method_args);
5901 klass = mono_class_get_checked (image, token, &error);
5903 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5904 if (!mono_error_ok (&error)) {
5905 mono_error_set_pending_exception (&error);
5910 return &klass->byval_arg;
5915 ICALL_EXPORT MonoMethod*
5916 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5919 int table = mono_metadata_token_table (token);
5920 int index = mono_metadata_token_index (token);
5921 MonoGenericContext context;
5924 *resolve_error = ResolveTokenError_Other;
5926 /* Validate token */
5927 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5928 (table != MONO_TABLE_MEMBERREF)) {
5929 *resolve_error = ResolveTokenError_BadTable;
5933 if (image_is_dynamic (image)) {
5934 if (table == MONO_TABLE_METHOD) {
5935 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5936 mono_error_cleanup (&error);
5940 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5941 *resolve_error = ResolveTokenError_BadTable;
5945 init_generic_context_from_args (&context, type_args, method_args);
5946 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5947 mono_error_cleanup (&error);
5951 if ((index <= 0) || (index > image->tables [table].rows)) {
5952 *resolve_error = ResolveTokenError_OutOfRange;
5955 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5956 *resolve_error = ResolveTokenError_BadTable;
5960 init_generic_context_from_args (&context, type_args, method_args);
5961 method = mono_get_method_checked (image, token, NULL, &context, &error);
5962 mono_error_set_pending_exception (&error);
5967 ICALL_EXPORT MonoString*
5968 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5971 int index = mono_metadata_token_index (token);
5973 *resolve_error = ResolveTokenError_Other;
5975 /* Validate token */
5976 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5977 *resolve_error = ResolveTokenError_BadTable;
5981 if (image_is_dynamic (image)) {
5982 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5983 mono_error_cleanup (&error);
5987 if ((index <= 0) || (index >= image->heap_us.size)) {
5988 *resolve_error = ResolveTokenError_OutOfRange;
5992 /* FIXME: What to do if the index points into the middle of a string ? */
5994 return mono_ldstr (mono_domain_get (), image, index);
5997 ICALL_EXPORT MonoClassField*
5998 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6002 int table = mono_metadata_token_table (token);
6003 int index = mono_metadata_token_index (token);
6004 MonoGenericContext context;
6005 MonoClassField *field;
6007 *resolve_error = ResolveTokenError_Other;
6009 /* Validate token */
6010 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6011 *resolve_error = ResolveTokenError_BadTable;
6015 if (image_is_dynamic (image)) {
6016 if (table == MONO_TABLE_FIELD) {
6017 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6018 mono_error_cleanup (&error);
6022 if (mono_memberref_is_method (image, token)) {
6023 *resolve_error = ResolveTokenError_BadTable;
6027 init_generic_context_from_args (&context, type_args, method_args);
6028 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6029 mono_error_cleanup (&error);
6033 if ((index <= 0) || (index > image->tables [table].rows)) {
6034 *resolve_error = ResolveTokenError_OutOfRange;
6037 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6038 *resolve_error = ResolveTokenError_BadTable;
6042 init_generic_context_from_args (&context, type_args, method_args);
6043 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6044 mono_error_set_pending_exception (&error);
6050 ICALL_EXPORT MonoObject*
6051 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6055 int table = mono_metadata_token_table (token);
6057 *error = ResolveTokenError_Other;
6060 case MONO_TABLE_TYPEDEF:
6061 case MONO_TABLE_TYPEREF:
6062 case MONO_TABLE_TYPESPEC: {
6063 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6065 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6066 mono_error_raise_exception (&merror);
6073 case MONO_TABLE_METHOD:
6074 case MONO_TABLE_METHODSPEC: {
6075 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6077 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6078 mono_error_raise_exception (&merror);
6084 case MONO_TABLE_FIELD: {
6085 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6087 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6088 mono_error_raise_exception (&merror);
6094 case MONO_TABLE_MEMBERREF:
6095 if (mono_memberref_is_method (image, token)) {
6096 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6098 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6099 mono_error_raise_exception (&merror);
6106 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6108 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6109 mono_error_raise_exception (&merror);
6118 *error = ResolveTokenError_BadTable;
6124 ICALL_EXPORT MonoArray*
6125 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
6127 int table = mono_metadata_token_table (token);
6128 int idx = mono_metadata_token_index (token);
6129 MonoTableInfo *tables = image->tables;
6134 *error = ResolveTokenError_OutOfRange;
6136 /* FIXME: Support other tables ? */
6137 if (table != MONO_TABLE_STANDALONESIG)
6140 if (image_is_dynamic (image))
6143 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6146 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6148 ptr = mono_metadata_blob_heap (image, sig);
6149 len = mono_metadata_decode_blob_size (ptr, &ptr);
6151 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
6152 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6156 ICALL_EXPORT MonoReflectionType*
6157 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6160 MonoReflectionType *ret;
6162 int isbyref = 0, rank;
6163 char *str = mono_string_to_utf8 (smodifiers);
6166 klass = mono_class_from_mono_type (tb->type.type);
6168 /* logic taken from mono_reflection_parse_type(): keep in sync */
6172 if (isbyref) { /* only one level allowed by the spec */
6181 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6182 mono_error_raise_exception (&error);
6186 klass = mono_ptr_class_get (&klass->byval_arg);
6187 mono_class_init (klass);
6198 else if (*p != '*') { /* '*' means unknown lower bound */
6209 klass = mono_array_class_get (klass, rank);
6210 mono_class_init (klass);
6219 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6220 mono_error_raise_exception (&error);
6225 ICALL_EXPORT MonoBoolean
6226 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6232 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6238 check_for_invalid_type (MonoClass *klass, MonoError *error)
6243 mono_error_init (error);
6245 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6248 name = mono_type_get_full_name (klass);
6249 str = mono_string_new (mono_domain_get (), name);
6251 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6254 ICALL_EXPORT MonoReflectionType *
6255 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6258 MonoReflectionType *ret;
6259 MonoClass *klass, *aklass;
6261 klass = mono_class_from_mono_type (type->type);
6262 check_for_invalid_type (klass, &error);
6263 mono_error_raise_exception (&error);
6265 if (rank == 0) //single dimentional array
6266 aklass = mono_array_class_get (klass, 1);
6268 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6270 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6271 mono_error_raise_exception (&error);
6276 ICALL_EXPORT MonoReflectionType *
6277 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6280 MonoReflectionType *ret;
6283 klass = mono_class_from_mono_type (type->type);
6284 mono_class_init_checked (klass, &error);
6285 mono_error_raise_exception (&error);
6286 check_for_invalid_type (klass, &error);
6287 mono_error_raise_exception (&error);
6289 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6290 mono_error_raise_exception (&error);
6295 ICALL_EXPORT MonoReflectionType *
6296 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6299 MonoReflectionType *ret;
6300 MonoClass *klass, *pklass;
6302 klass = mono_class_from_mono_type (type->type);
6303 mono_class_init_checked (klass, &error);
6304 mono_error_raise_exception (&error);
6305 check_for_invalid_type (klass, &error);
6306 mono_error_raise_exception (&error);
6308 pklass = mono_ptr_class_get (type->type);
6310 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6311 mono_error_raise_exception (&error);
6316 ICALL_EXPORT MonoObject *
6317 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6318 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6321 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6322 MonoObject *delegate;
6324 MonoMethod *method = info->method;
6326 mono_class_init_checked (delegate_class, &error);
6327 mono_error_raise_exception (&error);
6329 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6330 /* FIXME improve this exception message */
6331 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6333 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6334 mono_error_set_pending_exception (&error);
6338 if (mono_security_core_clr_enabled ()) {
6339 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6340 if (throwOnBindFailure)
6341 mono_error_set_pending_exception (&error);
6343 mono_error_cleanup (&error);
6348 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6349 mono_error_raise_exception (&error);
6351 if (method_is_dynamic (method)) {
6352 /* Creating a trampoline would leak memory */
6353 func = mono_compile_method (method);
6355 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6356 method = mono_object_get_virtual_method (target, method);
6357 func = mono_create_ftnptr (mono_domain_get (),
6358 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6361 mono_delegate_ctor_with_method (delegate, target, func, method);
6366 ICALL_EXPORT MonoMulticastDelegate *
6367 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6370 MonoMulticastDelegate *ret;
6372 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6374 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6375 mono_error_raise_exception (&error);
6376 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6381 ICALL_EXPORT MonoReflectionMethod*
6382 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6384 MonoReflectionMethod *ret = NULL;
6386 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6387 mono_error_raise_exception (&error);
6393 static inline gint32
6394 mono_array_get_byte_length (MonoArray *array)
6400 klass = array->obj.vtable->klass;
6402 if (array->bounds == NULL)
6403 length = array->max_length;
6406 for (i = 0; i < klass->rank; ++ i)
6407 length *= array->bounds [i].length;
6410 switch (klass->element_class->byval_arg.type) {
6413 case MONO_TYPE_BOOLEAN:
6417 case MONO_TYPE_CHAR:
6425 return length * sizeof (gpointer);
6436 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6438 return mono_array_get_byte_length (array);
6442 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6444 return mono_array_get (array, gint8, idx);
6448 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6450 mono_array_set (array, gint8, idx, value);
6453 ICALL_EXPORT MonoBoolean
6454 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6456 guint8 *src_buf, *dest_buf;
6459 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6463 g_assert (count >= 0);
6465 /* This is called directly from the class libraries without going through the managed wrapper */
6466 MONO_CHECK_ARG_NULL (src, FALSE);
6467 MONO_CHECK_ARG_NULL (dest, FALSE);
6469 /* watch out for integer overflow */
6470 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6473 src_buf = (guint8 *)src->vector + src_offset;
6474 dest_buf = (guint8 *)dest->vector + dest_offset;
6477 memcpy (dest_buf, src_buf, count);
6479 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6484 #ifndef DISABLE_REMOTING
6485 ICALL_EXPORT MonoObject *
6486 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6489 MonoDomain *domain = mono_object_domain (this_obj);
6491 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6492 MonoTransparentProxy *tp;
6496 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6497 mono_error_raise_exception (&error);
6498 tp = (MonoTransparentProxy*) res;
6500 MONO_OBJECT_SETREF (tp, rp, rp);
6501 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6502 klass = mono_class_from_mono_type (type);
6504 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6505 mono_class_setup_vtable (klass);
6506 if (mono_class_has_failure (klass)) {
6507 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6511 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6512 if (!is_ok (&error)) {
6513 mono_error_set_pending_exception (&error);
6516 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6517 if (!is_ok (&error)) {
6518 mono_error_set_pending_exception (&error);
6522 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6526 ICALL_EXPORT MonoReflectionType *
6527 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6530 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6531 mono_error_raise_exception (&error);
6537 /* System.Environment */
6540 ves_icall_System_Environment_get_UserName (void)
6542 /* using glib is more portable */
6543 return mono_string_new (mono_domain_get (), g_get_user_name ());
6547 ICALL_EXPORT MonoString *
6548 ves_icall_System_Environment_get_MachineName (void)
6550 #if defined (HOST_WIN32)
6555 len = MAX_COMPUTERNAME_LENGTH + 1;
6556 buf = g_new (gunichar2, len);
6559 if (GetComputerName (buf, (PDWORD) &len)) {
6561 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6562 mono_error_raise_exception (&error);
6567 #elif !defined(DISABLE_SOCKETS)
6571 #if defined _SC_HOST_NAME_MAX
6572 n = sysconf (_SC_HOST_NAME_MAX);
6576 buf = g_malloc (n+1);
6578 if (gethostname (buf, n) == 0){
6580 result = mono_string_new (mono_domain_get (), buf);
6587 return mono_string_new (mono_domain_get (), "mono");
6592 ves_icall_System_Environment_get_Platform (void)
6594 #if defined (TARGET_WIN32)
6597 #elif defined(__MACH__)
6600 // Notice that the value is hidden from user code, and only exposed
6601 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6602 // define and making assumptions based on Unix/128/4 values before there
6603 // was a MacOS define. Lots of code would assume that not-Unix meant
6604 // Windows, but in this case, it would be OSX.
6613 ICALL_EXPORT MonoString *
6614 ves_icall_System_Environment_get_NewLine (void)
6616 #if defined (HOST_WIN32)
6617 return mono_string_new (mono_domain_get (), "\r\n");
6619 return mono_string_new (mono_domain_get (), "\n");
6623 ICALL_EXPORT MonoBoolean
6624 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6626 #if SIZEOF_VOID_P == 8
6630 gboolean isWow64Process = FALSE;
6631 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6632 return (MonoBoolean)isWow64Process;
6634 #elif defined(HAVE_SYS_UTSNAME_H)
6635 struct utsname name;
6637 if (uname (&name) >= 0) {
6638 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6645 ICALL_EXPORT MonoString *
6646 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6654 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6655 value = g_getenv (utf8_name);
6662 return mono_string_new (mono_domain_get (), value);
6666 * There is no standard way to get at environ.
6669 #ifndef __MINGW32_VERSION
6670 #if defined(__APPLE__)
6671 #if defined (TARGET_OSX)
6672 /* Apple defines this in crt_externs.h but doesn't provide that header for
6673 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6674 * in fact exist on all implementations (so far)
6676 gchar ***_NSGetEnviron(void);
6677 #define environ (*_NSGetEnviron())
6679 static char *mono_environ[1] = { NULL };
6680 #define environ mono_environ
6681 #endif /* defined (TARGET_OSX) */
6689 ICALL_EXPORT MonoArray *
6690 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6701 env_strings = GetEnvironmentStrings();
6704 env_string = env_strings;
6705 while (*env_string != '\0') {
6706 /* weird case that MS seems to skip */
6707 if (*env_string != '=')
6709 while (*env_string != '\0')
6715 domain = mono_domain_get ();
6716 names = mono_array_new (domain, mono_defaults.string_class, n);
6720 env_string = env_strings;
6721 while (*env_string != '\0') {
6722 /* weird case that MS seems to skip */
6723 if (*env_string != '=') {
6724 equal_str = wcschr(env_string, '=');
6725 g_assert(equal_str);
6727 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6728 mono_error_raise_exception (&error);
6729 mono_array_setref (names, n, str);
6732 while (*env_string != '\0')
6737 FreeEnvironmentStrings (env_strings);
6750 for (e = environ; *e != 0; ++ e)
6753 domain = mono_domain_get ();
6754 names = mono_array_new (domain, mono_defaults.string_class, n);
6757 for (e = environ; *e != 0; ++ e) {
6758 parts = g_strsplit (*e, "=", 2);
6760 str = mono_string_new (domain, *parts);
6761 mono_array_setref (names, n, str);
6774 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6776 #if !GLIB_CHECK_VERSION(2,4,0)
6777 #define g_setenv(a,b,c) setenv(a,b,c)
6778 #define g_unsetenv(a) unsetenv(a)
6782 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6785 gunichar2 *utf16_name, *utf16_value;
6787 gchar *utf8_name, *utf8_value;
6792 utf16_name = mono_string_to_utf16 (name);
6793 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6794 SetEnvironmentVariable (utf16_name, NULL);
6795 g_free (utf16_name);
6799 utf16_value = mono_string_to_utf16 (value);
6801 SetEnvironmentVariable (utf16_name, utf16_value);
6803 g_free (utf16_name);
6804 g_free (utf16_value);
6806 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6808 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6809 g_unsetenv (utf8_name);
6814 utf8_value = mono_string_to_utf8_checked (value, &error);
6815 if (!mono_error_ok (&error)) {
6817 mono_error_set_pending_exception (&error);
6820 g_setenv (utf8_name, utf8_value, TRUE);
6823 g_free (utf8_value);
6828 ves_icall_System_Environment_Exit (int result)
6830 mono_environment_exitcode_set (result);
6832 /* FIXME: There are some cleanup hangs that should be worked out, but
6833 * if the program is going to exit, everything will be cleaned up when
6834 * NaCl exits anyway.
6836 #ifndef __native_client__
6837 if (!mono_runtime_try_shutdown ())
6838 mono_thread_exit ();
6840 /* Suspend all managed threads since the runtime is going away */
6841 mono_thread_suspend_all_other_threads ();
6843 mono_runtime_quit ();
6846 /* we may need to do some cleanup here... */
6850 ICALL_EXPORT MonoString*
6851 ves_icall_System_Environment_GetGacPath (void)
6853 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6856 ICALL_EXPORT MonoString*
6857 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6859 #if defined (HOST_WIN32)
6860 #ifndef CSIDL_FLAG_CREATE
6861 #define CSIDL_FLAG_CREATE 0x8000
6864 WCHAR path [MAX_PATH];
6865 /* Create directory if no existing */
6866 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6871 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6872 mono_error_raise_exception (&error);
6876 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6878 return mono_string_new (mono_domain_get (), "");
6881 ICALL_EXPORT MonoArray *
6882 ves_icall_System_Environment_GetLogicalDrives (void)
6885 gunichar2 buf [256], *ptr, *dname;
6887 guint initial_size = 127, size = 128;
6890 MonoString *drivestr;
6891 MonoDomain *domain = mono_domain_get ();
6897 while (size > initial_size) {
6898 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6899 if (size > initial_size) {
6902 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6903 initial_size = size;
6917 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6922 while (*u16) { u16++; len ++; }
6923 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6924 mono_error_raise_exception (&error);
6925 mono_array_setref (result, ndrives++, drivestr);
6935 ICALL_EXPORT MonoString *
6936 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6938 gunichar2 volume_name [MAX_PATH + 1];
6940 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6942 return mono_string_from_utf16 (volume_name);
6945 ICALL_EXPORT MonoString *
6946 ves_icall_System_Environment_InternalGetHome (void)
6948 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6951 static const char *encodings [] = {
6953 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6954 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6955 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6957 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6958 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6959 "x_unicode_2_0_utf_7",
6961 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6962 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6964 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6967 "unicodefffe", "utf_16be",
6974 * Returns the internal codepage, if the value of "int_code_page" is
6975 * 1 at entry, and we can not compute a suitable code page number,
6976 * returns the code page as a string
6978 ICALL_EXPORT MonoString*
6979 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6984 char *codepage = NULL;
6986 int want_name = *int_code_page;
6989 *int_code_page = -1;
6991 g_get_charset (&cset);
6992 c = codepage = strdup (cset);
6993 for (c = codepage; *c; c++){
6994 if (isascii (*c) && isalpha (*c))
6999 /* g_print ("charset: %s\n", cset); */
7001 /* handle some common aliases */
7004 for (i = 0; p != 0; ){
7007 p = encodings [++i];
7010 if (strcmp (p, codepage) == 0){
7011 *int_code_page = code;
7014 p = encodings [++i];
7017 if (strstr (codepage, "utf_8") != NULL)
7018 *int_code_page |= 0x10000000;
7021 if (want_name && *int_code_page == -1)
7022 return mono_string_new (mono_domain_get (), cset);
7027 ICALL_EXPORT MonoBoolean
7028 ves_icall_System_Environment_get_HasShutdownStarted (void)
7030 if (mono_runtime_is_shutting_down ())
7033 if (mono_domain_is_unloading (mono_domain_get ()))
7040 ves_icall_System_Environment_BroadcastSettingChange (void)
7043 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7048 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7054 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
7055 MonoReflectionMethod *method,
7056 MonoArray *out_args)
7058 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
7061 #ifndef DISABLE_REMOTING
7062 ICALL_EXPORT MonoBoolean
7063 ves_icall_IsTransparentProxy (MonoObject *proxy)
7068 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7074 ICALL_EXPORT MonoReflectionMethod *
7075 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7076 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7078 MonoReflectionMethod *ret = NULL;
7083 MonoMethod **vtable;
7084 MonoMethod *res = NULL;
7086 MONO_CHECK_ARG_NULL (rtype, NULL);
7087 MONO_CHECK_ARG_NULL (rmethod, NULL);
7089 method = rmethod->method;
7090 klass = mono_class_from_mono_type (rtype->type);
7091 mono_class_init_checked (klass, &error);
7092 mono_error_raise_exception (&error);
7094 if (MONO_CLASS_IS_INTERFACE (klass))
7097 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7100 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7101 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7107 mono_class_setup_vtable (klass);
7108 vtable = klass->vtable;
7110 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7111 gboolean variance_used = FALSE;
7112 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7113 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7115 res = vtable [offs + method->slot];
7117 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7120 if (method->slot != -1)
7121 res = vtable [method->slot];
7127 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7128 mono_error_raise_exception (&error);
7133 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7139 klass = mono_class_from_mono_type (type->type);
7140 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7141 if (!is_ok (&error)) {
7142 mono_error_set_pending_exception (&error);
7146 mono_vtable_set_is_remote (vtable, enable);
7149 #else /* DISABLE_REMOTING */
7152 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7154 g_assert_not_reached ();
7159 ICALL_EXPORT MonoObject *
7160 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7167 domain = mono_object_domain (type);
7168 klass = mono_class_from_mono_type (type->type);
7169 mono_class_init_checked (klass, &error);
7170 mono_error_raise_exception (&error);
7172 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7173 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7177 if (klass->rank >= 1) {
7178 g_assert (klass->rank == 1);
7179 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7181 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7182 if (!is_ok (&error)) {
7183 mono_error_set_pending_exception (&error);
7186 /* Bypass remoting object creation check */
7187 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7188 mono_error_set_pending_exception (&error);
7194 ICALL_EXPORT MonoString *
7195 ves_icall_System_IO_get_temp_path (void)
7197 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7200 #ifndef PLATFORM_NO_DRIVEINFO
7201 ICALL_EXPORT MonoBoolean
7202 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7203 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7207 ULARGE_INTEGER wapi_free_bytes_avail;
7208 ULARGE_INTEGER wapi_total_number_of_bytes;
7209 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7211 *error = ERROR_SUCCESS;
7212 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7213 &wapi_total_number_of_free_bytes);
7216 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7217 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7218 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7220 *free_bytes_avail = 0;
7221 *total_number_of_bytes = 0;
7222 *total_number_of_free_bytes = 0;
7223 *error = GetLastError ();
7229 ICALL_EXPORT guint32
7230 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7232 return GetDriveType (mono_string_chars (root_path_name));
7236 ICALL_EXPORT gpointer
7237 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7239 return mono_compile_method (method);
7242 ICALL_EXPORT MonoString *
7243 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7248 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7250 #if defined (HOST_WIN32)
7251 /* Avoid mixing '/' and '\\' */
7254 for (i = strlen (path) - 1; i >= 0; i--)
7255 if (path [i] == '/')
7259 mcpath = mono_string_new (mono_domain_get (), path);
7266 get_bundled_app_config (void)
7268 const gchar *app_config;
7271 gchar *config_file_name, *config_file_path;
7272 gsize len, config_file_path_length, config_ext_length;
7275 domain = mono_domain_get ();
7276 file = domain->setup->configuration_file;
7277 if (!file || file->length == 0)
7280 // Retrieve config file and remove the extension
7281 config_file_name = mono_string_to_utf8 (file);
7282 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7283 if (!config_file_path)
7284 config_file_path = config_file_name;
7286 config_file_path_length = strlen (config_file_path);
7287 config_ext_length = strlen (".config");
7288 if (config_file_path_length <= config_ext_length)
7291 len = config_file_path_length - config_ext_length;
7292 module = (gchar *)g_malloc0 (len + 1);
7293 memcpy (module, config_file_path, len);
7294 // Get the config file from the module name
7295 app_config = mono_config_string_for_assembly_file (module);
7298 if (config_file_name != config_file_path)
7299 g_free (config_file_name);
7300 g_free (config_file_path);
7305 return mono_string_new (mono_domain_get (), app_config);
7309 get_bundled_machine_config (void)
7311 const gchar *machine_config;
7313 machine_config = mono_get_machine_config ();
7315 if (!machine_config)
7318 return mono_string_new (mono_domain_get (), machine_config);
7321 ICALL_EXPORT MonoString *
7322 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7327 path = g_path_get_dirname (mono_get_config_dir ());
7329 #if defined (HOST_WIN32)
7330 /* Avoid mixing '/' and '\\' */
7333 for (i = strlen (path) - 1; i >= 0; i--)
7334 if (path [i] == '/')
7338 ipath = mono_string_new (mono_domain_get (), path);
7344 ICALL_EXPORT gboolean
7345 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7347 MonoPEResourceDataEntry *entry;
7350 if (!assembly || !result || !size)
7355 image = assembly->assembly->image;
7356 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7360 *result = mono_image_rva_map (image, entry->rde_data_offset);
7365 *size = entry->rde_size;
7370 ICALL_EXPORT MonoBoolean
7371 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7373 return mono_is_debugger_attached ();
7376 ICALL_EXPORT MonoBoolean
7377 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7379 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7380 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7386 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7388 if (mono_get_runtime_callbacks ()->debug_log)
7389 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7393 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7395 #if defined (HOST_WIN32)
7396 OutputDebugString (mono_string_chars (message));
7398 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7402 /* Only used for value types */
7403 ICALL_EXPORT MonoObject *
7404 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7411 domain = mono_object_domain (type);
7412 klass = mono_class_from_mono_type (type->type);
7413 mono_class_init_checked (klass, &error);
7414 mono_error_raise_exception (&error);
7416 if (mono_class_is_nullable (klass))
7417 /* No arguments -> null */
7420 result = mono_object_new_checked (domain, klass, &error);
7421 mono_error_raise_exception (&error);
7425 ICALL_EXPORT MonoReflectionMethod *
7426 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7428 MonoReflectionMethod *ret = NULL;
7431 MonoClass *klass, *parent;
7432 MonoGenericContext *generic_inst = NULL;
7433 MonoMethod *method = m->method;
7434 MonoMethod *result = NULL;
7437 if (method->klass == NULL)
7440 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7441 MONO_CLASS_IS_INTERFACE (method->klass) ||
7442 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7445 slot = mono_method_get_vtable_slot (method);
7449 klass = method->klass;
7450 if (klass->generic_class) {
7451 generic_inst = mono_class_get_context (klass);
7452 klass = klass->generic_class->container_class;
7456 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7457 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7458 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7459 or klass is the generic container class and generic_inst is the instantiation.
7461 when we go to the parent, if the parent is an open constructed type, we need to
7462 replace the type parameters by the definitions from the generic_inst, and then take it
7463 apart again into the klass and the generic_inst.
7465 For cases like this:
7466 class C<T> : B<T, int> {
7467 public override void Foo () { ... }
7469 class B<U,V> : A<HashMap<U,V>> {
7470 public override void Foo () { ... }
7473 public virtual void Foo () { ... }
7476 if at each iteration the parent isn't open, we can skip inflating it. if at some
7477 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7480 MonoGenericContext *parent_inst = NULL;
7481 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7483 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7484 if (!mono_error_ok (&error)) {
7485 mono_error_set_pending_exception (&error);
7489 if (parent->generic_class) {
7490 parent_inst = mono_class_get_context (parent);
7491 parent = parent->generic_class->container_class;
7494 mono_class_setup_vtable (parent);
7495 if (parent->vtable_size <= slot)
7498 generic_inst = parent_inst;
7501 klass = klass->parent;
7504 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7505 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7506 if (!mono_error_ok (&error)) {
7507 mono_error_set_pending_exception (&error);
7511 generic_inst = NULL;
7513 if (klass->generic_class) {
7514 generic_inst = mono_class_get_context (klass);
7515 klass = klass->generic_class->container_class;
7521 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7522 if (!mono_error_ok (&error)) {
7523 mono_error_set_pending_exception (&error);
7528 if (klass == method->klass)
7531 /*This is possible if definition == FALSE.
7532 * Do it here to be really sure we don't read invalid memory.
7534 if (slot >= klass->vtable_size)
7537 mono_class_setup_vtable (klass);
7539 result = klass->vtable [slot];
7540 if (result == NULL) {
7541 /* It is an abstract method */
7542 gpointer iter = NULL;
7543 while ((result = mono_class_get_methods (klass, &iter)))
7544 if (result->slot == slot)
7551 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7552 mono_error_raise_exception (&error);
7556 ICALL_EXPORT MonoString*
7557 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7559 MonoMethod *method = m->method;
7561 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7566 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7568 iter->sig = *(MonoMethodSignature**)argsp;
7570 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7571 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7574 /* FIXME: it's not documented what start is exactly... */
7578 iter->args = argsp + sizeof (gpointer);
7580 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7582 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7585 ICALL_EXPORT MonoTypedRef
7586 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7588 guint32 i, arg_size;
7592 i = iter->sig->sentinelpos + iter->next_arg;
7594 g_assert (i < iter->sig->param_count);
7596 res.type = iter->sig->params [i];
7597 res.klass = mono_class_from_mono_type (res.type);
7598 arg_size = mono_type_stack_size (res.type, &align);
7599 #if defined(__arm__) || defined(__mips__)
7600 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7602 res.value = iter->args;
7603 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7604 /* Values are stored as 8 byte register sized objects, but 'value'
7605 * is dereferenced as a pointer in other routines.
7607 res.value = (char*)res.value + 4;
7609 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7610 if (arg_size <= sizeof (gpointer)) {
7612 int padding = arg_size - mono_type_size (res.type, &dummy);
7613 res.value = (guint8*)res.value + padding;
7616 iter->args = (char*)iter->args + arg_size;
7619 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7624 ICALL_EXPORT MonoTypedRef
7625 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7627 guint32 i, arg_size;
7631 i = iter->sig->sentinelpos + iter->next_arg;
7633 g_assert (i < iter->sig->param_count);
7635 while (i < iter->sig->param_count) {
7636 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7638 res.type = iter->sig->params [i];
7639 res.klass = mono_class_from_mono_type (res.type);
7640 /* FIXME: endianess issue... */
7641 arg_size = mono_type_stack_size (res.type, &align);
7642 #if defined(__arm__) || defined(__mips__)
7643 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7645 res.value = iter->args;
7646 iter->args = (char*)iter->args + arg_size;
7648 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7651 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7659 ICALL_EXPORT MonoType*
7660 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7664 i = iter->sig->sentinelpos + iter->next_arg;
7666 g_assert (i < iter->sig->param_count);
7668 return iter->sig->params [i];
7671 ICALL_EXPORT MonoObject*
7672 mono_TypedReference_ToObject (MonoTypedRef* tref)
7675 MonoObject *result = NULL;
7676 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7677 MonoObject** objp = (MonoObject **)tref->value;
7681 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7682 mono_error_set_pending_exception (&error);
7686 ICALL_EXPORT MonoTypedRef
7687 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7690 MonoReflectionField *f;
7692 MonoType *ftype = NULL;
7696 memset (&res, 0, sizeof (res));
7699 g_assert (mono_array_length (fields) > 0);
7701 klass = target->vtable->klass;
7703 for (i = 0; i < mono_array_length (fields); ++i) {
7704 f = mono_array_get (fields, MonoReflectionField*, i);
7706 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7709 if (f->field->parent != klass) {
7710 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7714 p = (guint8*)target + f->field->offset;
7716 p += f->field->offset - sizeof (MonoObject);
7717 klass = mono_class_from_mono_type (f->field->type);
7718 ftype = f->field->type;
7722 res.klass = mono_class_from_mono_type (ftype);
7729 prelink_method (MonoMethod *method, MonoError *error)
7731 const char *exc_class, *exc_arg;
7733 mono_error_init (error);
7734 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7736 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7738 mono_error_set_exception_instance (error,
7739 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7742 /* create the wrapper, too? */
7746 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7750 prelink_method (method->method, &error);
7751 mono_error_raise_exception (&error);
7755 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7758 MonoClass *klass = mono_class_from_mono_type (type->type);
7760 gpointer iter = NULL;
7762 mono_class_init_checked (klass, &error);
7763 mono_error_raise_exception (&error);
7765 while ((m = mono_class_get_methods (klass, &iter))) {
7766 prelink_method (m, &error);
7767 mono_error_raise_exception (&error);
7771 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7773 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7774 gint32 const **exponents,
7775 gunichar2 const **digitLowerTable,
7776 gunichar2 const **digitUpperTable,
7777 gint64 const **tenPowersList,
7778 gint32 const **decHexDigits)
7780 *mantissas = Formatter_MantissaBitsTable;
7781 *exponents = Formatter_TensExponentTable;
7782 *digitLowerTable = Formatter_DigitLowerTable;
7783 *digitUpperTable = Formatter_DigitUpperTable;
7784 *tenPowersList = Formatter_TenPowersList;
7785 *decHexDigits = Formatter_DecHexDigits;
7789 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7790 * and avoid useless allocations.
7793 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7795 MonoReflectionType *rt;
7799 mono_error_init (error);
7800 for (i = 0; i < type->num_mods; ++i) {
7801 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7806 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7808 for (i = 0; i < type->num_mods; ++i) {
7809 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7810 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7811 return_val_if_nok (error, NULL);
7813 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7814 return_val_if_nok (error, NULL);
7816 mono_array_setref (res, count, rt);
7823 ICALL_EXPORT MonoArray*
7824 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7827 MonoType *type = param->ClassImpl->type;
7828 MonoClass *member_class = mono_object_class (param->MemberImpl);
7829 MonoMethod *method = NULL;
7832 MonoMethodSignature *sig;
7835 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7836 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7837 method = rmethod->method;
7838 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7839 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7840 if (!(method = prop->property->get))
7841 method = prop->property->set;
7844 char *type_name = mono_type_get_full_name (member_class);
7845 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7846 MonoException *ex = mono_get_exception_not_supported (msg);
7849 mono_set_pending_exception (ex);
7853 image = method->klass->image;
7854 pos = param->PositionImpl;
7855 sig = mono_method_signature (method);
7859 type = sig->params [pos];
7861 res = type_array_from_modifiers (image, type, optional, &error);
7862 mono_error_raise_exception (&error);
7867 get_property_type (MonoProperty *prop)
7869 MonoMethodSignature *sig;
7871 sig = mono_method_signature (prop->get);
7873 } else if (prop->set) {
7874 sig = mono_method_signature (prop->set);
7875 return sig->params [sig->param_count - 1];
7880 ICALL_EXPORT MonoArray*
7881 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7884 MonoType *type = get_property_type (property->property);
7885 MonoImage *image = property->klass->image;
7890 res = type_array_from_modifiers (image, type, optional, &error);
7891 mono_error_raise_exception (&error);
7896 *Construct a MonoType suited to be used to decode a constant blob object.
7898 * @type is the target type which will be constructed
7899 * @blob_type is the blob type, for example, that comes from the constant table
7900 * @real_type is the expected constructed type.
7903 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7905 type->type = blob_type;
7906 type->data.klass = NULL;
7907 if (blob_type == MONO_TYPE_CLASS)
7908 type->data.klass = mono_defaults.object_class;
7909 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7910 /* For enums, we need to use the base type */
7911 type->type = MONO_TYPE_VALUETYPE;
7912 type->data.klass = mono_class_from_mono_type (real_type);
7914 type->data.klass = mono_class_from_mono_type (real_type);
7917 ICALL_EXPORT MonoObject*
7918 property_info_get_default_value (MonoReflectionProperty *property)
7922 MonoProperty *prop = property->property;
7923 MonoType *type = get_property_type (prop);
7924 MonoDomain *domain = mono_object_domain (property);
7925 MonoTypeEnum def_type;
7926 const char *def_value;
7929 mono_class_init (prop->parent);
7931 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7932 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7936 def_value = mono_class_get_property_default_value (prop, &def_type);
7938 mono_type_from_blob_type (&blob_type, def_type, type);
7939 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7941 mono_error_set_pending_exception (&error);
7945 ICALL_EXPORT MonoBoolean
7946 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7949 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7950 MonoCustomAttrInfo *cinfo;
7953 mono_class_init_checked (attr_class, &error);
7954 mono_error_raise_exception (&error);
7956 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7957 if (!is_ok (&error)) {
7958 mono_error_set_pending_exception (&error);
7963 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7965 mono_custom_attrs_free (cinfo);
7969 ICALL_EXPORT MonoArray*
7970 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7972 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7977 mono_class_init_checked (attr_class, &error);
7978 mono_error_raise_exception (&error);
7981 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7982 if (!mono_error_ok (&error)) {
7983 mono_error_set_pending_exception (&error);
7987 if (mono_loader_get_last_error ()) {
7988 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7995 ICALL_EXPORT MonoArray*
7996 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8000 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8001 mono_error_set_pending_exception (&error);
8006 ICALL_EXPORT MonoString*
8007 ves_icall_Mono_Runtime_GetDisplayName (void)
8010 MonoString *display_name;
8012 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8013 display_name = mono_string_new (mono_domain_get (), info);
8015 return display_name;
8018 ICALL_EXPORT MonoString*
8019 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8022 MonoString *message;
8026 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8027 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8030 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8032 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8033 mono_error_raise_exception (&error);
8039 ICALL_EXPORT gpointer
8040 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8042 return GetCurrentProcess ();
8045 ICALL_EXPORT MonoBoolean
8046 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8048 return GetExitCodeProcess (handle, (guint32*) exitcode);
8051 ICALL_EXPORT MonoBoolean
8052 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8054 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8055 return CloseHandle (handle);
8057 return CloseProcess (handle);
8061 ICALL_EXPORT MonoBoolean
8062 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8064 return TerminateProcess (handle, exitcode);
8068 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8070 return WaitForInputIdle (handle, milliseconds);
8073 ICALL_EXPORT MonoBoolean
8074 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8076 return GetProcessWorkingSetSize (handle, min, max);
8079 ICALL_EXPORT MonoBoolean
8080 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8082 return SetProcessWorkingSetSize (handle, min, max);
8085 ICALL_EXPORT MonoBoolean
8086 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8088 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8092 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8094 return mono_process_current_pid ();
8098 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8100 return GetPriorityClass (handle);
8103 ICALL_EXPORT MonoBoolean
8104 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8106 return SetPriorityClass (handle, priorityClass);
8109 #ifndef DISABLE_ICALL_TABLES
8111 #define ICALL_TYPE(id,name,first)
8112 #define ICALL(id,name,func) Icall_ ## id,
8115 #include "metadata/icall-def.h"
8121 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8122 #define ICALL(id,name,func)
8124 #include "metadata/icall-def.h"
8130 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8131 #define ICALL(id,name,func)
8133 guint16 first_icall;
8136 static const IcallTypeDesc
8137 icall_type_descs [] = {
8138 #include "metadata/icall-def.h"
8142 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8145 #define ICALL_TYPE(id,name,first)
8148 #ifdef HAVE_ARRAY_ELEM_INIT
8149 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8150 #define MSGSTRFIELD1(line) str##line
8152 static const struct msgstrtn_t {
8153 #define ICALL(id,name,func)
8155 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8156 #include "metadata/icall-def.h"
8158 } icall_type_names_str = {
8159 #define ICALL_TYPE(id,name,first) (name),
8160 #include "metadata/icall-def.h"
8163 static const guint16 icall_type_names_idx [] = {
8164 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8165 #include "metadata/icall-def.h"
8168 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8170 static const struct msgstr_t {
8172 #define ICALL_TYPE(id,name,first)
8173 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8174 #include "metadata/icall-def.h"
8176 } icall_names_str = {
8177 #define ICALL(id,name,func) (name),
8178 #include "metadata/icall-def.h"
8181 static const guint16 icall_names_idx [] = {
8182 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8183 #include "metadata/icall-def.h"
8186 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8192 #define ICALL_TYPE(id,name,first) name,
8193 #define ICALL(id,name,func)
8194 static const char* const
8195 icall_type_names [] = {
8196 #include "metadata/icall-def.h"
8200 #define icall_type_name_get(id) (icall_type_names [(id)])
8204 #define ICALL_TYPE(id,name,first)
8205 #define ICALL(id,name,func) name,
8206 static const char* const
8208 #include "metadata/icall-def.h"
8211 #define icall_name_get(id) icall_names [(id)]
8213 #endif /* !HAVE_ARRAY_ELEM_INIT */
8217 #define ICALL_TYPE(id,name,first)
8218 #define ICALL(id,name,func) func,
8219 static const gconstpointer
8220 icall_functions [] = {
8221 #include "metadata/icall-def.h"
8225 #ifdef ENABLE_ICALL_SYMBOL_MAP
8228 #define ICALL_TYPE(id,name,first)
8229 #define ICALL(id,name,func) #func,
8230 static const gconstpointer
8231 icall_symbols [] = {
8232 #include "metadata/icall-def.h"
8237 #endif /* DISABLE_ICALL_TABLES */
8239 static mono_mutex_t icall_mutex;
8240 static GHashTable *icall_hash = NULL;
8241 static GHashTable *jit_icall_hash_name = NULL;
8242 static GHashTable *jit_icall_hash_addr = NULL;
8245 mono_icall_init (void)
8247 #ifndef DISABLE_ICALL_TABLES
8250 /* check that tables are sorted: disable in release */
8253 const char *prev_class = NULL;
8254 const char *prev_method;
8256 for (i = 0; i < Icall_type_num; ++i) {
8257 const IcallTypeDesc *desc;
8260 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8261 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8262 prev_class = icall_type_name_get (i);
8263 desc = &icall_type_descs [i];
8264 num_icalls = icall_desc_num_icalls (desc);
8265 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8266 for (j = 0; j < num_icalls; ++j) {
8267 const char *methodn = icall_name_get (desc->first_icall + j);
8268 if (prev_method && strcmp (prev_method, methodn) >= 0)
8269 g_print ("method %s should come before method %s\n", methodn, prev_method);
8270 prev_method = methodn;
8276 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8277 mono_os_mutex_init (&icall_mutex);
8281 mono_icall_lock (void)
8283 mono_locks_os_acquire (&icall_mutex, IcallLock);
8287 mono_icall_unlock (void)
8289 mono_locks_os_release (&icall_mutex, IcallLock);
8293 mono_icall_cleanup (void)
8295 g_hash_table_destroy (icall_hash);
8296 g_hash_table_destroy (jit_icall_hash_name);
8297 g_hash_table_destroy (jit_icall_hash_addr);
8298 mono_os_mutex_destroy (&icall_mutex);
8302 * mono_add_internal_call:
8303 * @name: method specification to surface to the managed world
8304 * @method: pointer to a C method to invoke when the method is called
8306 * This method surfaces the C function pointed by @method as a method
8307 * that has been surfaced in managed code with the method specified in
8308 * @name as an internal call.
8310 * Internal calls are surfaced to all app domains loaded and they are
8311 * accessibly by a type with the specified name.
8313 * You must provide a fully qualified type name, that is namespaces
8314 * and type name, followed by a colon and the method name, with an
8315 * optional signature to bind.
8317 * For example, the following are all valid declarations:
8319 * "MyApp.Services.ScriptService:Accelerate"
8320 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8322 * You use method parameters in cases where there might be more than
8323 * one surface method to managed code. That way you can register different
8324 * internal calls for different method overloads.
8326 * The internal calls are invoked with no marshalling. This means that .NET
8327 * types like System.String are exposed as `MonoString *` parameters. This is
8328 * different than the way that strings are surfaced in P/Invoke.
8330 * For more information on how the parameters are marshalled, see the
8331 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8334 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8335 * reference for more information on the format of method descriptions.
8338 mono_add_internal_call (const char *name, gconstpointer method)
8342 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8344 mono_icall_unlock ();
8347 #ifndef DISABLE_ICALL_TABLES
8349 #ifdef HAVE_ARRAY_ELEM_INIT
8351 compare_method_imap (const void *key, const void *elem)
8353 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8354 return strcmp (key, method_name);
8358 find_method_icall (const IcallTypeDesc *imap, const char *name)
8360 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);
8363 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8367 compare_class_imap (const void *key, const void *elem)
8369 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8370 return strcmp (key, class_name);
8373 static const IcallTypeDesc*
8374 find_class_icalls (const char *name)
8376 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);
8379 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8382 #else /* HAVE_ARRAY_ELEM_INIT */
8385 compare_method_imap (const void *key, const void *elem)
8387 const char** method_name = (const char**)elem;
8388 return strcmp (key, *method_name);
8392 find_method_icall (const IcallTypeDesc *imap, const char *name)
8394 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8397 return (gpointer)icall_functions [(nameslot - icall_names)];
8401 compare_class_imap (const void *key, const void *elem)
8403 const char** class_name = (const char**)elem;
8404 return strcmp (key, *class_name);
8407 static const IcallTypeDesc*
8408 find_class_icalls (const char *name)
8410 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8413 return &icall_type_descs [nameslot - icall_type_names];
8416 #endif /* HAVE_ARRAY_ELEM_INIT */
8418 #endif /* DISABLE_ICALL_TABLES */
8421 * we should probably export this as an helper (handle nested types).
8422 * Returns the number of chars written in buf.
8425 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8427 int nspacelen, cnamelen;
8428 nspacelen = strlen (klass->name_space);
8429 cnamelen = strlen (klass->name);
8430 if (nspacelen + cnamelen + 2 > bufsize)
8433 memcpy (buf, klass->name_space, nspacelen);
8434 buf [nspacelen ++] = '.';
8436 memcpy (buf + nspacelen, klass->name, cnamelen);
8437 buf [nspacelen + cnamelen] = 0;
8438 return nspacelen + cnamelen;
8441 #ifdef DISABLE_ICALL_TABLES
8443 no_icall_table (void)
8445 g_assert_not_reached ();
8450 mono_lookup_internal_call (MonoMethod *method)
8455 int typelen = 0, mlen, siglen;
8457 #ifndef DISABLE_ICALL_TABLES
8458 const IcallTypeDesc *imap = NULL;
8461 g_assert (method != NULL);
8463 if (method->is_inflated)
8464 method = ((MonoMethodInflated *) method)->declaring;
8466 if (method->klass->nested_in) {
8467 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8471 mname [pos++] = '/';
8474 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8480 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8485 #ifndef DISABLE_ICALL_TABLES
8486 imap = find_class_icalls (mname);
8489 mname [typelen] = ':';
8490 mname [typelen + 1] = ':';
8492 mlen = strlen (method->name);
8493 memcpy (mname + typelen + 2, method->name, mlen);
8494 sigstart = mname + typelen + 2 + mlen;
8497 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8498 siglen = strlen (tmpsig);
8499 if (typelen + mlen + siglen + 6 > sizeof (mname))
8502 memcpy (sigstart + 1, tmpsig, siglen);
8503 sigstart [siglen + 1] = ')';
8504 sigstart [siglen + 2] = 0;
8509 res = g_hash_table_lookup (icall_hash, mname);
8511 mono_icall_unlock ();;
8514 /* try without signature */
8516 res = g_hash_table_lookup (icall_hash, mname);
8518 mono_icall_unlock ();
8522 #ifdef DISABLE_ICALL_TABLES
8523 mono_icall_unlock ();
8524 /* Fail only when the result is actually used */
8525 /* mono_marshal_get_native_wrapper () depends on this */
8526 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8527 return ves_icall_System_String_ctor_RedirectToCreateString;
8529 return no_icall_table;
8531 /* it wasn't found in the static call tables */
8533 mono_icall_unlock ();
8536 res = find_method_icall (imap, sigstart - mlen);
8538 mono_icall_unlock ();
8541 /* try _with_ signature */
8543 res = find_method_icall (imap, sigstart - mlen);
8545 mono_icall_unlock ();
8549 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8550 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8551 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8552 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8553 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");
8554 g_print ("If you see other errors or faults after this message they are probably related\n");
8555 g_print ("and you need to fix your mono install first.\n");
8557 mono_icall_unlock ();
8563 #ifdef ENABLE_ICALL_SYMBOL_MAP
8565 func_cmp (gconstpointer key, gconstpointer p)
8567 return (gsize)key - (gsize)*(gsize*)p;
8572 * mono_lookup_icall_symbol:
8574 * Given the icall METHOD, returns its C symbol.
8577 mono_lookup_icall_symbol (MonoMethod *m)
8579 #ifdef DISABLE_ICALL_TABLES
8580 g_assert_not_reached ();
8583 #ifdef ENABLE_ICALL_SYMBOL_MAP
8587 static gconstpointer *functions_sorted;
8588 static const char**symbols_sorted;
8589 static gboolean inited;
8594 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8595 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8596 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8597 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8598 /* Bubble sort the two arrays */
8602 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8603 if (functions_sorted [i] > functions_sorted [i + 1]) {
8606 tmp = functions_sorted [i];
8607 functions_sorted [i] = functions_sorted [i + 1];
8608 functions_sorted [i + 1] = tmp;
8609 tmp = symbols_sorted [i];
8610 symbols_sorted [i] = symbols_sorted [i + 1];
8611 symbols_sorted [i + 1] = tmp;
8618 func = mono_lookup_internal_call (m);
8621 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8625 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8627 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8628 g_assert_not_reached ();
8635 type_from_typename (char *type_name)
8637 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8639 if (!strcmp (type_name, "int"))
8640 klass = mono_defaults.int_class;
8641 else if (!strcmp (type_name, "ptr"))
8642 klass = mono_defaults.int_class;
8643 else if (!strcmp (type_name, "void"))
8644 klass = mono_defaults.void_class;
8645 else if (!strcmp (type_name, "int32"))
8646 klass = mono_defaults.int32_class;
8647 else if (!strcmp (type_name, "uint32"))
8648 klass = mono_defaults.uint32_class;
8649 else if (!strcmp (type_name, "int8"))
8650 klass = mono_defaults.sbyte_class;
8651 else if (!strcmp (type_name, "uint8"))
8652 klass = mono_defaults.byte_class;
8653 else if (!strcmp (type_name, "int16"))
8654 klass = mono_defaults.int16_class;
8655 else if (!strcmp (type_name, "uint16"))
8656 klass = mono_defaults.uint16_class;
8657 else if (!strcmp (type_name, "long"))
8658 klass = mono_defaults.int64_class;
8659 else if (!strcmp (type_name, "ulong"))
8660 klass = mono_defaults.uint64_class;
8661 else if (!strcmp (type_name, "float"))
8662 klass = mono_defaults.single_class;
8663 else if (!strcmp (type_name, "double"))
8664 klass = mono_defaults.double_class;
8665 else if (!strcmp (type_name, "object"))
8666 klass = mono_defaults.object_class;
8667 else if (!strcmp (type_name, "obj"))
8668 klass = mono_defaults.object_class;
8669 else if (!strcmp (type_name, "string"))
8670 klass = mono_defaults.string_class;
8671 else if (!strcmp (type_name, "bool"))
8672 klass = mono_defaults.boolean_class;
8673 else if (!strcmp (type_name, "boolean"))
8674 klass = mono_defaults.boolean_class;
8676 g_error ("%s", type_name);
8677 g_assert_not_reached ();
8679 return &klass->byval_arg;
8683 * LOCKING: Take the corlib image lock.
8685 MonoMethodSignature*
8686 mono_create_icall_signature (const char *sigstr)
8691 MonoMethodSignature *res, *res2;
8692 MonoImage *corlib = mono_defaults.corlib;
8694 mono_image_lock (corlib);
8695 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8696 mono_image_unlock (corlib);
8701 parts = g_strsplit (sigstr, " ", 256);
8710 res = mono_metadata_signature_alloc (corlib, len - 1);
8715 * Under windows, the default pinvoke calling convention is STDCALL but
8718 res->call_convention = MONO_CALL_C;
8721 res->ret = type_from_typename (parts [0]);
8722 for (i = 1; i < len; ++i) {
8723 res->params [i - 1] = type_from_typename (parts [i]);
8728 mono_image_lock (corlib);
8729 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8731 res = res2; /*Value is allocated in the image pool*/
8733 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8734 mono_image_unlock (corlib);
8740 mono_find_jit_icall_by_name (const char *name)
8742 MonoJitICallInfo *info;
8743 g_assert (jit_icall_hash_name);
8746 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8747 mono_icall_unlock ();
8752 mono_find_jit_icall_by_addr (gconstpointer addr)
8754 MonoJitICallInfo *info;
8755 g_assert (jit_icall_hash_addr);
8758 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8759 mono_icall_unlock ();
8765 * mono_get_jit_icall_info:
8767 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8768 * caller should access it while holding the icall lock.
8771 mono_get_jit_icall_info (void)
8773 return jit_icall_hash_name;
8777 * mono_lookup_jit_icall_symbol:
8779 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8782 mono_lookup_jit_icall_symbol (const char *name)
8784 MonoJitICallInfo *info;
8785 const char *res = NULL;
8788 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8790 res = info->c_symbol;
8791 mono_icall_unlock ();
8796 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8799 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8800 mono_icall_unlock ();
8804 * 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
8805 * icalls without wrappers in some cases.
8808 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8810 MonoJitICallInfo *info;
8817 if (!jit_icall_hash_name) {
8818 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8819 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8822 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8823 g_warning ("jit icall already defined \"%s\"\n", name);
8824 g_assert_not_reached ();
8827 info = g_new0 (MonoJitICallInfo, 1);
8832 info->c_symbol = c_symbol;
8833 info->no_raise = no_raise;
8836 info->wrapper = func;
8838 info->wrapper = NULL;
8841 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8842 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8844 mono_icall_unlock ();
8849 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8851 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);