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);
1875 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1876 mono_error_set_pending_exception (&error);
1881 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1884 MonoClassField *cf = field->field;
1888 if (field->klass->image->assembly->ref_only) {
1889 mono_set_pending_exception (mono_get_exception_invalid_operation (
1890 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1894 if (mono_security_core_clr_enabled ())
1895 mono_security_core_clr_ensure_reflection_access_field (cf);
1897 type = mono_field_get_type_checked (cf, &error);
1898 if (!mono_error_ok (&error)) {
1899 mono_error_set_pending_exception (&error);
1903 v = (gchar *) value;
1905 switch (type->type) {
1908 case MONO_TYPE_BOOLEAN:
1911 case MONO_TYPE_CHAR:
1920 case MONO_TYPE_VALUETYPE:
1923 v += sizeof (MonoObject);
1925 case MONO_TYPE_STRING:
1926 case MONO_TYPE_OBJECT:
1927 case MONO_TYPE_CLASS:
1928 case MONO_TYPE_ARRAY:
1929 case MONO_TYPE_SZARRAY:
1932 case MONO_TYPE_GENERICINST: {
1933 MonoGenericClass *gclass = type->data.generic_class;
1934 g_assert (!gclass->context.class_inst->is_open);
1936 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1937 MonoClass *nklass = mono_class_from_mono_type (type);
1938 MonoObject *nullable;
1941 * Convert the boxed vtype into a Nullable structure.
1942 * This is complicated by the fact that Nullables have
1943 * a variable structure.
1945 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1946 if (!mono_error_ok (&error)) {
1947 mono_error_set_pending_exception (&error);
1951 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1953 v = (gchar *)mono_object_unbox (nullable);
1956 if (gclass->container_class->valuetype && (v != NULL))
1957 v += sizeof (MonoObject);
1961 g_error ("type 0x%x not handled in "
1962 "ves_icall_FieldInfo_SetValueInternal", type->type);
1967 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1968 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
1969 if (!is_ok (&error)) {
1970 mono_error_set_pending_exception (&error);
1973 if (!vtable->initialized) {
1974 if (!mono_runtime_class_init_full (vtable, &error)) {
1975 mono_error_set_pending_exception (&error);
1979 mono_field_static_set_value (vtable, cf, v);
1981 mono_field_set_value (obj, cf, v);
1986 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1995 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1996 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2000 if (MONO_TYPE_IS_REFERENCE (f->type))
2001 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2003 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2006 ICALL_EXPORT MonoObject *
2007 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2009 MonoObject *o = NULL;
2010 MonoClassField *field = rfield->field;
2012 MonoDomain *domain = mono_object_domain (rfield);
2014 MonoTypeEnum def_type;
2015 const char *def_value;
2019 mono_class_init (field->parent);
2021 t = mono_field_get_type_checked (field, &error);
2022 if (!mono_error_ok (&error)) {
2023 mono_error_set_pending_exception (&error);
2027 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2028 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2032 if (image_is_dynamic (field->parent->image)) {
2033 MonoClass *klass = field->parent;
2034 int fidx = field - klass->fields;
2036 g_assert (fidx >= 0 && fidx < klass->field.count);
2037 g_assert (klass->ext);
2038 g_assert (klass->ext->field_def_values);
2039 def_type = klass->ext->field_def_values [fidx].def_type;
2040 def_value = klass->ext->field_def_values [fidx].data;
2041 if (def_type == MONO_TYPE_END) {
2042 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2046 def_value = mono_class_get_field_default_value (field, &def_type);
2047 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2049 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2054 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2058 case MONO_TYPE_BOOLEAN:
2061 case MONO_TYPE_CHAR:
2069 case MONO_TYPE_R8: {
2072 /* boxed value type */
2073 t = g_new0 (MonoType, 1);
2075 klass = mono_class_from_mono_type (t);
2077 o = mono_object_new_checked (domain, klass, &error);
2078 if (!mono_error_ok (&error)) {
2079 mono_error_set_pending_exception (&error);
2082 v = ((gchar *) o) + sizeof (MonoObject);
2083 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2086 case MONO_TYPE_STRING:
2087 case MONO_TYPE_CLASS:
2088 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2091 g_assert_not_reached ();
2097 ICALL_EXPORT MonoReflectionType*
2098 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2101 MonoReflectionType *ret;
2104 type = mono_field_get_type_checked (ref_field->field, &error);
2105 if (!mono_error_ok (&error)) {
2106 mono_error_set_pending_exception (&error);
2110 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2111 if (!mono_error_ok (&error)) {
2112 mono_error_set_pending_exception (&error);
2119 /* From MonoProperty.cs */
2121 PInfo_Attributes = 1,
2122 PInfo_GetMethod = 1 << 1,
2123 PInfo_SetMethod = 1 << 2,
2124 PInfo_ReflectedType = 1 << 3,
2125 PInfo_DeclaringType = 1 << 4,
2130 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2133 MonoReflectionType *rt;
2134 MonoReflectionMethod *rm;
2135 MonoDomain *domain = mono_object_domain (property);
2136 const MonoProperty *pproperty = property->property;
2138 if ((req_info & PInfo_ReflectedType) != 0) {
2139 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2140 mono_error_raise_exception (&error);
2142 MONO_STRUCT_SETREF (info, parent, rt);
2144 if ((req_info & PInfo_DeclaringType) != 0) {
2145 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2146 mono_error_raise_exception (&error);
2148 MONO_STRUCT_SETREF (info, declaring_type, rt);
2151 if ((req_info & PInfo_Name) != 0)
2152 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2154 if ((req_info & PInfo_Attributes) != 0)
2155 info->attrs = pproperty->attrs;
2157 if ((req_info & PInfo_GetMethod) != 0) {
2158 if (pproperty->get &&
2159 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2160 pproperty->get->klass == property->klass)) {
2161 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2162 mono_error_raise_exception (&error);
2167 MONO_STRUCT_SETREF (info, get, rm);
2169 if ((req_info & PInfo_SetMethod) != 0) {
2170 if (pproperty->set &&
2171 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2172 pproperty->set->klass == property->klass)) {
2173 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2174 mono_error_raise_exception (&error);
2179 MONO_STRUCT_SETREF (info, set, rm);
2182 * There may be other methods defined for properties, though, it seems they are not exposed
2183 * in the reflection API
2188 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2191 MonoReflectionType *rt;
2192 MonoReflectionMethod *rm;
2193 MonoDomain *domain = mono_object_domain (event);
2195 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2196 mono_error_raise_exception (&error);
2198 MONO_STRUCT_SETREF (info, reflected_type, rt);
2200 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2201 mono_error_raise_exception (&error);
2203 MONO_STRUCT_SETREF (info, declaring_type, rt);
2205 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2206 info->attrs = event->event->attrs;
2208 if (event->event->add) {
2209 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2210 mono_error_raise_exception (&error);
2215 MONO_STRUCT_SETREF (info, add_method, rm);
2217 if (event->event->remove) {
2218 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2219 mono_error_raise_exception (&error);
2224 MONO_STRUCT_SETREF (info, remove_method, rm);
2226 if (event->event->raise) {
2227 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2228 mono_error_raise_exception (&error);
2233 MONO_STRUCT_SETREF (info, raise_method, rm);
2235 #ifndef MONO_SMALL_CONFIG
2236 if (event->event->other) {
2238 while (event->event->other [n])
2240 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2242 for (i = 0; i < n; i++) {
2243 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2244 mono_error_raise_exception (&error);
2245 mono_array_setref (info->other_methods, i, rm);
2252 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2257 mono_class_setup_interfaces (klass, error);
2258 if (!mono_error_ok (error))
2261 for (i = 0; i < klass->interface_count; i++) {
2262 ic = klass->interfaces [i];
2263 g_hash_table_insert (ifaces, ic, ic);
2265 collect_interfaces (ic, ifaces, error);
2266 if (!mono_error_ok (error))
2272 MonoArray *iface_array;
2273 MonoGenericContext *context;
2277 } FillIfaceArrayData;
2280 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2282 MonoReflectionType *rt;
2283 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2284 MonoClass *ic = (MonoClass *)key;
2285 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2287 if (!mono_error_ok (data->error))
2290 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2291 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2292 if (!mono_error_ok (data->error))
2296 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2297 if (!mono_error_ok (data->error))
2300 mono_array_setref (data->iface_array, data->next_idx++, rt);
2303 mono_metadata_free_type (inflated);
2307 get_interfaces_hash (gconstpointer v1)
2309 MonoClass *k = (MonoClass*)v1;
2311 return k->type_token;
2314 ICALL_EXPORT MonoArray*
2315 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2318 MonoClass *klass = mono_class_from_mono_type (type->type);
2320 FillIfaceArrayData data = { 0 };
2323 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2325 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2326 data.context = mono_class_get_context (klass);
2327 klass = klass->generic_class->container_class;
2330 for (parent = klass; parent; parent = parent->parent) {
2331 mono_class_setup_interfaces (parent, &error);
2332 if (!mono_error_ok (&error))
2334 collect_interfaces (parent, iface_hash, &error);
2335 if (!mono_error_ok (&error))
2339 data.error = &error;
2340 data.domain = mono_object_domain (type);
2342 len = g_hash_table_size (iface_hash);
2344 g_hash_table_destroy (iface_hash);
2345 if (!data.domain->empty_types)
2346 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2347 return data.domain->empty_types;
2350 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2351 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2352 if (!mono_error_ok (&error))
2355 g_hash_table_destroy (iface_hash);
2356 return data.iface_array;
2359 g_hash_table_destroy (iface_hash);
2360 mono_error_set_pending_exception (&error);
2365 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2367 gboolean variance_used;
2368 MonoClass *klass = mono_class_from_mono_type (type->type);
2369 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2370 MonoReflectionMethod *member;
2373 int i = 0, len, ioffset;
2377 mono_class_init_checked (klass, &error);
2378 mono_error_raise_exception (&error);
2379 mono_class_init_checked (iclass, &error);
2380 mono_error_raise_exception (&error);
2382 mono_class_setup_vtable (klass);
2384 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2388 len = mono_class_num_methods (iclass);
2389 domain = mono_object_domain (type);
2390 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2391 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2393 while ((method = mono_class_get_methods (iclass, &iter))) {
2394 member = mono_method_get_object_checked (domain, method, iclass, &error);
2395 mono_error_raise_exception (&error);
2396 mono_array_setref (*methods, i, member);
2397 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2398 mono_error_raise_exception (&error);
2399 mono_array_setref (*targets, i, member);
2406 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2409 MonoClass *klass = mono_class_from_mono_type (type->type);
2411 mono_class_init_checked (klass, &error);
2412 mono_error_raise_exception (&error);
2414 if (image_is_dynamic (klass->image)) {
2415 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2416 *packing = tb->packing_size;
2417 *size = tb->class_size;
2419 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2423 ICALL_EXPORT MonoReflectionType*
2424 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2427 MonoReflectionType *ret;
2430 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2431 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2432 mono_error_raise_exception (&error);
2437 klass = mono_class_from_mono_type (type->type);
2438 mono_class_init_checked (klass, &error);
2439 mono_error_raise_exception (&error);
2441 // GetElementType should only return a type for:
2442 // Array Pointer PassedByRef
2443 if (type->type->byref)
2444 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2445 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2446 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2447 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2448 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2452 mono_error_raise_exception (&error);
2457 ICALL_EXPORT MonoReflectionType*
2458 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2461 MonoReflectionType *ret;
2463 if (type->type->byref)
2466 MonoClass *klass = mono_class_from_mono_type (type->type);
2470 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2471 mono_error_raise_exception (&error);
2476 ICALL_EXPORT MonoBoolean
2477 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2479 return type->type->type == MONO_TYPE_PTR;
2482 ICALL_EXPORT MonoBoolean
2483 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2485 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)));
2488 ICALL_EXPORT MonoBoolean
2489 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2491 return type->type->byref;
2494 ICALL_EXPORT MonoBoolean
2495 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2498 MonoClass *klass = mono_class_from_mono_type (type->type);
2499 mono_class_init_checked (klass, &error);
2500 mono_error_raise_exception (&error);
2502 return mono_class_is_com_object (klass);
2505 ICALL_EXPORT guint32
2506 ves_icall_reflection_get_token (MonoObject* obj)
2509 guint32 result = mono_reflection_get_token_checked (obj, &error);
2510 mono_error_set_pending_exception (&error);
2514 ICALL_EXPORT MonoReflectionModule*
2515 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2518 MonoReflectionModule *result = NULL;
2519 MonoClass *klass = mono_class_from_mono_type (type->type);
2520 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2521 if (!mono_error_ok (&error))
2522 mono_error_set_pending_exception (&error);
2526 ICALL_EXPORT MonoReflectionAssembly*
2527 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2530 MonoDomain *domain = mono_domain_get ();
2531 MonoClass *klass = mono_class_from_mono_type (type->type);
2532 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2534 mono_error_set_pending_exception (&error);
2538 ICALL_EXPORT MonoReflectionType*
2539 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2542 MonoReflectionType *ret;
2543 MonoDomain *domain = mono_domain_get ();
2546 if (type->type->byref)
2548 if (type->type->type == MONO_TYPE_VAR) {
2549 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2550 klass = param ? param->owner.klass : NULL;
2551 } else if (type->type->type == MONO_TYPE_MVAR) {
2552 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2553 klass = param ? param->owner.method->klass : NULL;
2555 klass = mono_class_from_mono_type (type->type)->nested_in;
2561 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2562 mono_error_raise_exception (&error);
2567 ICALL_EXPORT MonoString*
2568 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2570 MonoDomain *domain = mono_domain_get ();
2571 MonoClass *klass = mono_class_from_mono_type (type->type);
2573 if (type->type->byref) {
2574 char *n = g_strdup_printf ("%s&", klass->name);
2575 MonoString *res = mono_string_new (domain, n);
2581 return mono_string_new (domain, klass->name);
2585 ICALL_EXPORT MonoString*
2586 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2588 MonoDomain *domain = mono_domain_get ();
2589 MonoClass *klass = mono_class_from_mono_type (type->type);
2591 while (klass->nested_in)
2592 klass = klass->nested_in;
2594 if (klass->name_space [0] == '\0')
2597 return mono_string_new (domain, klass->name_space);
2601 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2605 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2606 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2610 klass = mono_class_from_mono_type (type->type);
2616 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2619 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2623 ICALL_EXPORT MonoArray*
2624 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2627 MonoReflectionType *rt;
2629 MonoClass *klass, *pklass;
2630 MonoDomain *domain = mono_object_domain (type);
2633 klass = mono_class_from_mono_type (type->type);
2635 if (klass->generic_container) {
2636 MonoGenericContainer *container = klass->generic_container;
2637 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2638 for (i = 0; i < container->type_argc; ++i) {
2639 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2641 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2642 mono_error_raise_exception (&error);
2644 mono_array_setref (res, i, rt);
2646 } else if (klass->generic_class) {
2647 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2648 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2649 for (i = 0; i < inst->type_argc; ++i) {
2650 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2651 mono_error_raise_exception (&error);
2653 mono_array_setref (res, i, rt);
2661 ICALL_EXPORT gboolean
2662 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2666 if (!IS_MONOTYPE (type))
2669 if (type->type->byref)
2672 klass = mono_class_from_mono_type (type->type);
2673 return klass->generic_container != NULL;
2676 ICALL_EXPORT MonoReflectionType*
2677 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2680 MonoReflectionType *ret;
2683 if (type->type->byref)
2686 klass = mono_class_from_mono_type (type->type);
2688 if (klass->generic_container) {
2689 return type; /* check this one */
2691 if (klass->generic_class) {
2692 MonoClass *generic_class = klass->generic_class->container_class;
2695 tb = mono_class_get_ref_info (generic_class);
2697 if (generic_class->wastypebuilder && tb)
2698 return (MonoReflectionType *)tb;
2700 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2701 mono_error_raise_exception (&error);
2709 ICALL_EXPORT MonoReflectionType*
2710 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2713 MonoReflectionType *ret;
2715 MonoType *geninst, **types;
2718 g_assert (IS_MONOTYPE (type));
2719 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2720 mono_error_raise_exception (&error);
2722 count = mono_array_length (type_array);
2723 types = g_new0 (MonoType *, count);
2725 for (i = 0; i < count; i++) {
2726 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2727 types [i] = t->type;
2730 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2733 mono_error_set_pending_exception (&error);
2737 klass = mono_class_from_mono_type (geninst);
2739 /*we might inflate to the GTD*/
2740 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2741 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2745 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2746 mono_error_raise_exception (&error);
2751 ICALL_EXPORT gboolean
2752 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2756 if (!IS_MONOTYPE (type))
2759 if (type->type->byref)
2762 klass = mono_class_from_mono_type (type->type);
2763 return klass->generic_class != NULL || klass->generic_container != NULL;
2767 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2769 if (!IS_MONOTYPE (type))
2772 if (is_generic_parameter (type->type))
2773 return mono_type_get_generic_param_num (type->type);
2777 ICALL_EXPORT GenericParameterAttributes
2778 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2780 g_assert (IS_MONOTYPE (type));
2781 g_assert (is_generic_parameter (type->type));
2782 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2785 ICALL_EXPORT MonoArray *
2786 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2789 MonoReflectionType *rt;
2790 MonoGenericParamInfo *param_info;
2796 g_assert (IS_MONOTYPE (type));
2798 domain = mono_object_domain (type);
2799 param_info = mono_generic_param_info (type->type->data.generic_param);
2800 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2803 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2804 for (i = 0; i < count; i++) {
2805 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2806 mono_error_raise_exception (&error);
2808 mono_array_setref (res, i, rt);
2815 ICALL_EXPORT MonoBoolean
2816 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2818 return is_generic_parameter (type->type);
2821 ICALL_EXPORT MonoBoolean
2822 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2824 return is_generic_parameter (tb->type.type);
2828 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2829 MonoReflectionType *t)
2831 enumtype->type = t->type;
2834 ICALL_EXPORT MonoReflectionMethod*
2835 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2836 MonoReflectionMethod* generic)
2843 MonoReflectionMethod *ret = NULL;
2845 domain = ((MonoObject *)type)->vtable->domain;
2847 klass = mono_class_from_mono_type (type->type);
2848 mono_class_init_checked (klass, &error);
2849 mono_error_raise_exception (&error);
2852 while ((method = mono_class_get_methods (klass, &iter))) {
2853 if (method->token == generic->method->token) {
2854 ret = mono_method_get_object_checked (domain, method, klass, &error);
2855 mono_error_raise_exception (&error);
2862 ICALL_EXPORT MonoReflectionMethod *
2863 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2866 MonoType *type = ref_type->type;
2868 MonoReflectionMethod *ret = NULL;
2870 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2871 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2874 if (type->type == MONO_TYPE_VAR)
2877 method = mono_type_get_generic_param_owner (type)->owner.method;
2880 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2881 if (!mono_error_ok (&error))
2882 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2886 ICALL_EXPORT MonoBoolean
2887 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2889 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2893 ICALL_EXPORT MonoBoolean
2894 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2896 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2901 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2903 MonoDomain *domain = mono_domain_get ();
2904 MonoImage *image = method->method->klass->image;
2905 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2906 MonoTableInfo *tables = image->tables;
2907 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2908 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2909 guint32 im_cols [MONO_IMPLMAP_SIZE];
2910 guint32 scope_token;
2911 const char *import = NULL;
2912 const char *scope = NULL;
2914 if (image_is_dynamic (image)) {
2915 MonoReflectionMethodAux *method_aux =
2916 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2918 import = method_aux->dllentry;
2919 scope = method_aux->dll;
2922 if (!import || !scope) {
2923 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2928 if (piinfo->implmap_idx) {
2929 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2931 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2932 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2933 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2934 scope = mono_metadata_string_heap (image, scope_token);
2938 *flags = piinfo->piflags;
2939 *entry_point = mono_string_new (domain, import);
2940 *dll_name = mono_string_new (domain, scope);
2943 ICALL_EXPORT MonoReflectionMethod *
2944 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2946 MonoMethodInflated *imethod;
2948 MonoReflectionMethod *ret = NULL;
2951 if (method->method->is_generic)
2954 if (!method->method->is_inflated)
2957 imethod = (MonoMethodInflated *) method->method;
2959 result = imethod->declaring;
2960 /* Not a generic method. */
2961 if (!result->is_generic)
2964 if (image_is_dynamic (method->method->klass->image)) {
2965 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2966 MonoReflectionMethod *res;
2969 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2970 * the dynamic case as well ?
2972 mono_image_lock ((MonoImage*)image);
2973 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2974 mono_image_unlock ((MonoImage*)image);
2980 if (imethod->context.class_inst) {
2981 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2982 /*Generic methods gets the context of the GTD.*/
2983 if (mono_class_get_context (klass)) {
2984 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2985 if (!mono_error_ok (&error))
2990 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2992 if (!mono_error_ok (&error))
2993 mono_error_set_pending_exception (&error);
2997 ICALL_EXPORT gboolean
2998 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3000 return mono_method_signature (method->method)->generic_param_count != 0;
3003 ICALL_EXPORT gboolean
3004 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3006 return method->method->is_generic;
3009 ICALL_EXPORT MonoArray*
3010 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3013 MonoReflectionType *rt;
3018 domain = mono_object_domain (method);
3020 if (method->method->is_inflated) {
3021 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3024 count = inst->type_argc;
3025 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3027 for (i = 0; i < count; i++) {
3028 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3029 mono_error_raise_exception (&error);
3031 mono_array_setref (res, i, rt);
3038 count = mono_method_signature (method->method)->generic_param_count;
3039 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3041 for (i = 0; i < count; i++) {
3042 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3043 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3044 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3046 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3047 mono_error_raise_exception (&error);
3049 mono_array_setref (res, i, rt);
3055 ICALL_EXPORT MonoObject *
3056 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3060 * Invoke from reflection is supposed to always be a virtual call (the API
3061 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3062 * greater flexibility.
3064 MonoMethod *m = method->method;
3065 MonoMethodSignature *sig = mono_method_signature (m);
3068 void *obj = this_arg;
3072 if (mono_security_core_clr_enabled ())
3073 mono_security_core_clr_ensure_reflection_access_method (m);
3075 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3076 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3077 mono_error_cleanup (&error); /* FIXME does this make sense? */
3078 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3083 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3084 if (!is_ok (&error)) {
3085 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3088 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3089 char *target_name = mono_type_get_full_name (m->klass);
3090 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3091 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3093 g_free (target_name);
3097 m = mono_object_get_virtual_method (this_arg, m);
3098 /* must pass the pointer to the value for valuetype methods */
3099 if (m->klass->valuetype)
3100 obj = mono_object_unbox (this_arg);
3101 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3102 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3107 if (sig->ret->byref) {
3108 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"));
3112 pcount = params? mono_array_length (params): 0;
3113 if (pcount != sig->param_count) {
3114 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3118 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3119 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."));
3123 image = m->klass->image;
3124 if (image->assembly->ref_only) {
3125 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."));
3129 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3130 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3134 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3138 intptr_t *lower_bounds;
3139 pcount = mono_array_length (params);
3140 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3141 /* Note: the synthetized array .ctors have int32 as argument type */
3142 for (i = 0; i < pcount; ++i)
3143 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3145 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3146 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3147 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3148 if (!mono_error_ok (&error)) {
3149 mono_error_set_pending_exception (&error);
3153 for (i = 0; i < mono_array_length (arr); ++i) {
3154 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3155 if (!mono_error_ok (&error)) {
3156 mono_error_set_pending_exception (&error);
3159 mono_array_setref_fast (arr, i, subarray);
3161 return (MonoObject*)arr;
3164 if (m->klass->rank == pcount) {
3165 /* Only lengths provided. */
3166 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3167 if (!mono_error_ok (&error)) {
3168 mono_error_set_pending_exception (&error);
3172 return (MonoObject*)arr;
3174 g_assert (pcount == (m->klass->rank * 2));
3175 /* The arguments are lower-bound-length pairs */
3176 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3178 for (i = 0; i < pcount / 2; ++i) {
3179 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3180 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3183 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3184 if (!mono_error_ok (&error)) {
3185 mono_error_set_pending_exception (&error);
3189 return (MonoObject*)arr;
3192 return mono_runtime_invoke_array (m, obj, params, NULL);
3195 #ifndef DISABLE_REMOTING
3196 ICALL_EXPORT MonoObject *
3197 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3200 MonoDomain *domain = mono_object_domain (method);
3201 MonoMethod *m = method->method;
3202 MonoMethodSignature *sig = mono_method_signature (m);
3203 MonoArray *out_args;
3205 int i, j, outarg_count = 0;
3207 if (m->klass == mono_defaults.object_class) {
3208 if (!strcmp (m->name, "FieldGetter")) {
3209 MonoClass *k = this_arg->vtable->klass;
3213 /* If this is a proxy, then it must be a CBO */
3214 if (k == mono_defaults.transparent_proxy_class) {
3215 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3216 this_arg = tp->rp->unwrapped_server;
3217 g_assert (this_arg);
3218 k = this_arg->vtable->klass;
3221 name = mono_array_get (params, MonoString *, 1);
3222 str = mono_string_to_utf8 (name);
3225 MonoClassField* field = mono_class_get_field_from_name (k, str);
3227 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3228 if (field_klass->valuetype) {
3229 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3230 mono_error_set_pending_exception (&error);
3231 /* fallthru to cleanup */
3233 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3235 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3236 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3237 mono_array_setref (out_args, 0, result);
3245 g_assert_not_reached ();
3247 } else if (!strcmp (m->name, "FieldSetter")) {
3248 MonoClass *k = this_arg->vtable->klass;
3254 /* If this is a proxy, then it must be a CBO */
3255 if (k == mono_defaults.transparent_proxy_class) {
3256 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3257 this_arg = tp->rp->unwrapped_server;
3258 g_assert (this_arg);
3259 k = this_arg->vtable->klass;
3262 name = mono_array_get (params, MonoString *, 1);
3263 str = mono_string_to_utf8 (name);
3266 MonoClassField* field = mono_class_get_field_from_name (k, str);
3268 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3269 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3271 if (field_klass->valuetype) {
3272 size = mono_type_size (field->type, &align);
3273 g_assert (size == mono_class_value_size (field_klass, NULL));
3274 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3276 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3279 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3280 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3290 g_assert_not_reached ();
3295 for (i = 0; i < mono_array_length (params); i++) {
3296 if (sig->params [i]->byref)
3300 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3302 /* handle constructors only for objects already allocated */
3303 if (!strcmp (method->method->name, ".ctor"))
3304 g_assert (this_arg);
3306 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3307 g_assert (!method->method->klass->valuetype);
3308 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3310 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3311 if (sig->params [i]->byref) {
3313 arg = mono_array_get (params, gpointer, i);
3314 mono_array_setref (out_args, j, arg);
3319 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3326 read_enum_value (const char *mem, int type)
3329 case MONO_TYPE_BOOLEAN:
3331 return *(guint8*)mem;
3333 return *(gint8*)mem;
3334 case MONO_TYPE_CHAR:
3336 return read16 (mem);
3338 return (gint16) read16 (mem);
3340 return read32 (mem);
3342 return (gint32) read32 (mem);
3345 return read64 (mem);
3347 g_assert_not_reached ();
3353 write_enum_value (char *mem, int type, guint64 value)
3357 case MONO_TYPE_I1: {
3358 guint8 *p = (guint8*)mem;
3363 case MONO_TYPE_I2: {
3364 guint16 *p = (guint16 *)mem;
3369 case MONO_TYPE_I4: {
3370 guint32 *p = (guint32 *)mem;
3375 case MONO_TYPE_I8: {
3376 guint64 *p = (guint64 *)mem;
3381 g_assert_not_reached ();
3386 ICALL_EXPORT MonoObject *
3387 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3395 domain = mono_object_domain (enumType);
3396 enumc = mono_class_from_mono_type (enumType->type);
3398 mono_class_init_checked (enumc, &error);
3399 mono_error_raise_exception (&error);
3401 etype = mono_class_enum_basetype (enumc);
3403 res = mono_object_new_checked (domain, enumc, &error);
3404 mono_error_raise_exception (&error);
3405 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3410 ICALL_EXPORT MonoBoolean
3411 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3413 int size = mono_class_value_size (a->vtable->klass, NULL);
3414 guint64 a_val = 0, b_val = 0;
3416 memcpy (&a_val, mono_object_unbox (a), size);
3417 memcpy (&b_val, mono_object_unbox (b), size);
3419 return (a_val & b_val) == b_val;
3422 ICALL_EXPORT MonoObject *
3423 ves_icall_System_Enum_get_value (MonoObject *eobj)
3435 g_assert (eobj->vtable->klass->enumtype);
3437 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3438 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3439 mono_error_raise_exception (&error);
3440 dst = (char *)res + sizeof (MonoObject);
3441 src = (char *)eobj + sizeof (MonoObject);
3442 size = mono_class_value_size (enumc, NULL);
3444 memcpy (dst, src, size);
3449 ICALL_EXPORT MonoReflectionType *
3450 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3453 MonoReflectionType *ret;
3457 klass = mono_class_from_mono_type (type->type);
3458 mono_class_init_checked (klass, &error);
3459 mono_error_raise_exception (&error);
3461 etype = mono_class_enum_basetype (klass);
3463 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3467 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3468 mono_error_raise_exception (&error);
3474 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3476 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3477 gpointer odata = (char *)other + sizeof (MonoObject);
3478 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3479 g_assert (basetype);
3484 if (eobj->vtable->klass != other->vtable->klass)
3487 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3488 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3489 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3492 return me > other ? 1 : -1; \
3495 switch (basetype->type) {
3497 COMPARE_ENUM_VALUES (guint8);
3499 COMPARE_ENUM_VALUES (gint8);
3500 case MONO_TYPE_CHAR:
3502 COMPARE_ENUM_VALUES (guint16);
3504 COMPARE_ENUM_VALUES (gint16);
3506 COMPARE_ENUM_VALUES (guint32);
3508 COMPARE_ENUM_VALUES (gint32);
3510 COMPARE_ENUM_VALUES (guint64);
3512 COMPARE_ENUM_VALUES (gint64);
3516 #undef COMPARE_ENUM_VALUES
3517 /* indicates that the enum was of an unsupported unerlying type */
3522 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3524 gpointer data = (char *)eobj + sizeof (MonoObject);
3525 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3526 g_assert (basetype);
3528 switch (basetype->type) {
3529 case MONO_TYPE_I1: {
3530 gint8 value = *((gint8*)data);
3531 return ((int)value ^ (int)value << 8);
3534 return *((guint8*)data);
3535 case MONO_TYPE_CHAR:
3537 return *((guint16*)data);
3539 case MONO_TYPE_I2: {
3540 gint16 value = *((gint16*)data);
3541 return ((int)(guint16)value | (((int)value) << 16));
3544 return *((guint32*)data);
3546 return *((gint32*)data);
3548 case MONO_TYPE_I8: {
3549 gint64 value = *((gint64*)data);
3550 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3553 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3558 ICALL_EXPORT MonoBoolean
3559 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3562 MonoDomain *domain = mono_object_domain (type);
3563 MonoClass *enumc = mono_class_from_mono_type (type->type);
3564 guint j = 0, nvalues;
3566 MonoClassField *field;
3568 guint64 field_value, previous_value = 0;
3569 gboolean sorted = TRUE;
3571 mono_class_init_checked (enumc, &error);
3572 mono_error_raise_exception (&error);
3574 if (!enumc->enumtype) {
3575 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3579 base_type = mono_class_enum_basetype (enumc)->type;
3581 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3582 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3583 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3586 while ((field = mono_class_get_fields (enumc, &iter))) {
3588 MonoTypeEnum def_type;
3590 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3592 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3594 if (mono_field_is_deleted (field))
3596 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3598 p = mono_class_get_field_default_value (field, &def_type);
3599 /* len = */ mono_metadata_decode_blob_size (p, &p);
3601 field_value = read_enum_value (p, base_type);
3602 mono_array_set (*values, guint64, j, field_value);
3604 if (previous_value > field_value)
3607 previous_value = field_value;
3615 BFLAGS_IgnoreCase = 1,
3616 BFLAGS_DeclaredOnly = 2,
3617 BFLAGS_Instance = 4,
3619 BFLAGS_Public = 0x10,
3620 BFLAGS_NonPublic = 0x20,
3621 BFLAGS_FlattenHierarchy = 0x40,
3622 BFLAGS_InvokeMethod = 0x100,
3623 BFLAGS_CreateInstance = 0x200,
3624 BFLAGS_GetField = 0x400,
3625 BFLAGS_SetField = 0x800,
3626 BFLAGS_GetProperty = 0x1000,
3627 BFLAGS_SetProperty = 0x2000,
3628 BFLAGS_ExactBinding = 0x10000,
3629 BFLAGS_SuppressChangeType = 0x20000,
3630 BFLAGS_OptionalParamBinding = 0x40000
3633 ICALL_EXPORT MonoArray*
3634 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3638 MonoClass *startklass, *klass, *refklass;
3643 char *utf8_name = NULL;
3644 int (*compare_func) (const char *s1, const char *s2) = NULL;
3645 MonoClassField *field;
3646 MonoPtrArray tmp_array;
3648 domain = ((MonoObject *)type)->vtable->domain;
3649 if (type->type->byref)
3650 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3652 klass = startklass = mono_class_from_mono_type (type->type);
3653 refklass = mono_class_from_mono_type (reftype->type);
3655 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3658 if (mono_class_has_failure (klass)) {
3659 mono_ptr_array_destroy (tmp_array);
3660 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3665 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3666 guint32 flags = mono_field_get_flags (field);
3668 if (mono_field_is_deleted_with_flags (field, flags))
3670 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3671 if (bflags & BFLAGS_Public)
3673 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3674 if (bflags & BFLAGS_NonPublic) {
3681 if (flags & FIELD_ATTRIBUTE_STATIC) {
3682 if (bflags & BFLAGS_Static)
3683 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3686 if (bflags & BFLAGS_Instance)
3694 if (utf8_name == NULL) {
3695 utf8_name = mono_string_to_utf8 (name);
3696 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3699 if (compare_func (mono_field_get_name (field), utf8_name))
3703 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3704 if (!mono_error_ok (&error))
3706 mono_ptr_array_append (tmp_array, member);
3708 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3711 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3713 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3714 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3716 mono_ptr_array_destroy (tmp_array);
3718 if (utf8_name != NULL)
3723 mono_ptr_array_destroy (tmp_array);
3724 mono_error_raise_exception (&error);
3725 g_assert_not_reached ();
3729 method_nonpublic (MonoMethod* method, gboolean start_klass)
3731 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3732 case METHOD_ATTRIBUTE_ASSEM:
3733 return (start_klass || mono_defaults.generic_ilist_class);
3734 case METHOD_ATTRIBUTE_PRIVATE:
3736 case METHOD_ATTRIBUTE_PUBLIC:
3744 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3747 MonoClass *startklass;
3751 /*FIXME, use MonoBitSet*/
3752 guint32 method_slots_default [8];
3753 guint32 *method_slots = NULL;
3754 int (*compare_func) (const char *s1, const char *s2) = NULL;
3756 array = g_ptr_array_new ();
3761 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3763 /* An optimization for calls made from Delegate:CreateDelegate () */
3764 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3765 method = mono_get_delegate_invoke (klass);
3766 if (mono_loader_get_last_error ())
3769 g_ptr_array_add (array, method);
3773 mono_class_setup_methods (klass);
3774 mono_class_setup_vtable (klass);
3775 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3778 if (is_generic_parameter (&klass->byval_arg))
3779 nslots = mono_class_get_vtable_size (klass->parent);
3781 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3782 if (nslots >= sizeof (method_slots_default) * 8) {
3783 method_slots = g_new0 (guint32, nslots / 32 + 1);
3785 method_slots = method_slots_default;
3786 memset (method_slots, 0, sizeof (method_slots_default));
3789 mono_class_setup_methods (klass);
3790 mono_class_setup_vtable (klass);
3791 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3795 while ((method = mono_class_get_methods (klass, &iter))) {
3797 if (method->slot != -1) {
3798 g_assert (method->slot < nslots);
3799 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3801 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3802 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3805 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3807 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3808 if (bflags & BFLAGS_Public)
3810 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3816 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3817 if (bflags & BFLAGS_Static)
3818 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3821 if (bflags & BFLAGS_Instance)
3829 if (compare_func (name, method->name))
3834 g_ptr_array_add (array, method);
3836 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3838 if (method_slots != method_slots_default)
3839 g_free (method_slots);
3844 if (method_slots != method_slots_default)
3845 g_free (method_slots);
3846 g_ptr_array_free (array, TRUE);
3848 if (mono_class_has_failure (klass)) {
3849 *ex = mono_class_get_exception_for_failure (klass);
3851 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3852 mono_loader_clear_error ();
3857 ICALL_EXPORT MonoArray*
3858 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3860 static MonoClass *MethodInfo_array;
3864 MonoVTable *array_vtable;
3865 MonoException *ex = NULL;
3866 const char *mname = NULL;
3867 GPtrArray *method_array;
3868 MonoClass *klass, *refklass;
3871 mono_error_init (&error);
3873 if (!MethodInfo_array) {
3874 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3875 mono_memory_barrier ();
3876 MethodInfo_array = klass;
3879 klass = mono_class_from_mono_type (type->type);
3880 refklass = mono_class_from_mono_type (reftype->type);
3881 domain = ((MonoObject *)type)->vtable->domain;
3882 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3883 if (!is_ok (&error)) {
3884 mono_error_set_pending_exception (&error);
3887 if (type->type->byref) {
3888 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3889 mono_error_set_pending_exception (&error);
3895 mname = mono_string_to_utf8 (name);
3897 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3898 g_free ((char*)mname);
3900 mono_set_pending_exception (ex);
3904 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3905 if (!mono_error_ok (&error)) {
3906 mono_error_set_pending_exception (&error);
3910 for (i = 0; i < method_array->len; ++i) {
3911 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3912 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3913 if (!mono_error_ok (&error))
3915 mono_array_setref (res, i, rm);
3919 g_ptr_array_free (method_array, TRUE);
3920 if (!mono_error_ok (&error))
3921 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3925 ICALL_EXPORT MonoArray*
3926 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3929 MonoClass *startklass, *klass, *refklass;
3934 gpointer iter = NULL;
3935 MonoPtrArray tmp_array;
3938 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3940 domain = ((MonoObject *)type)->vtable->domain;
3941 if (type->type->byref)
3942 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3943 klass = startklass = mono_class_from_mono_type (type->type);
3944 refklass = mono_class_from_mono_type (reftype->type);
3946 mono_class_setup_methods (klass);
3947 if (mono_class_has_failure (klass)) {
3948 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3953 while ((method = mono_class_get_methods (klass, &iter))) {
3955 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3957 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3958 if (bflags & BFLAGS_Public)
3961 if (bflags & BFLAGS_NonPublic)
3967 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3968 if (bflags & BFLAGS_Static)
3969 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3972 if (bflags & BFLAGS_Instance)
3978 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3979 if (!mono_error_ok (&error)) {
3980 mono_error_set_pending_exception (&error);
3984 mono_ptr_array_append (tmp_array, member);
3987 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
3989 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3990 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3992 mono_ptr_array_destroy (tmp_array);
3998 property_hash (gconstpointer data)
4000 MonoProperty *prop = (MonoProperty*)data;
4002 return g_str_hash (prop->name);
4006 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
4008 if (method1->is_inflated)
4009 method1 = ((MonoMethodInflated*) method1)->declaring;
4010 if (method2->is_inflated)
4011 method2 = ((MonoMethodInflated*) method2)->declaring;
4013 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4017 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4019 // Properties are hide-by-name-and-signature
4020 if (!g_str_equal (prop1->name, prop2->name))
4023 /* If we see a property in a generic method, we want to
4024 compare the generic signatures, not the inflated signatures
4025 because we might conflate two properties that were
4029 public T this[T t] { getter { return t; } } // method 1
4030 public U this[U u] { getter { return u; } } // method 2
4033 If we see int Foo<int,int>::Item[int] we need to know if
4034 the indexer came from method 1 or from method 2, and we
4035 shouldn't conflate them. (Bugzilla 36283)
4037 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
4040 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4047 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4052 return method_nonpublic (accessor, start_klass);
4055 ICALL_EXPORT MonoArray*
4056 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4060 MonoClass *startklass, *klass;
4066 gchar *propname = NULL;
4067 int (*compare_func) (const char *s1, const char *s2) = NULL;
4069 GHashTable *properties = NULL;
4070 MonoPtrArray tmp_array;
4072 mono_error_init (&error);
4074 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4076 domain = ((MonoObject *)type)->vtable->domain;
4077 if (type->type->byref)
4078 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
4079 klass = startklass = mono_class_from_mono_type (type->type);
4082 propname = mono_string_to_utf8 (name);
4083 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4086 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4088 mono_class_setup_methods (klass);
4089 mono_class_setup_vtable (klass);
4090 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4094 while ((prop = mono_class_get_properties (klass, &iter))) {
4100 flags = method->flags;
4103 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4104 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4105 if (bflags & BFLAGS_Public)
4107 } else if (bflags & BFLAGS_NonPublic) {
4108 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4109 property_accessor_nonpublic(prop->set, startklass == klass)) {
4116 if (flags & METHOD_ATTRIBUTE_STATIC) {
4117 if (bflags & BFLAGS_Static)
4118 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4121 if (bflags & BFLAGS_Instance)
4130 if (compare_func (propname, prop->name))
4134 if (g_hash_table_lookup (properties, prop))
4137 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4140 mono_ptr_array_append (tmp_array, pr);
4142 g_hash_table_insert (properties, prop, prop);
4144 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4147 g_hash_table_destroy (properties);
4150 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4151 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4152 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4154 mono_ptr_array_destroy (tmp_array);
4161 if (mono_class_has_failure (klass)) {
4162 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4164 mono_error_set_from_loader_error (&error);
4165 mono_loader_clear_error ();
4170 g_hash_table_destroy (properties);
4173 mono_ptr_array_destroy (tmp_array);
4175 mono_error_set_pending_exception (&error);
4181 event_hash (gconstpointer data)
4183 MonoEvent *event = (MonoEvent*)data;
4185 return g_str_hash (event->name);
4189 event_equal (MonoEvent *event1, MonoEvent *event2)
4191 // Events are hide-by-name
4192 return g_str_equal (event1->name, event2->name);
4195 ICALL_EXPORT MonoArray*
4196 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4200 MonoClass *startklass, *klass;
4206 char *utf8_name = NULL;
4207 int (*compare_func) (const char *s1, const char *s2) = NULL;
4208 GHashTable *events = NULL;
4209 MonoPtrArray tmp_array;
4211 mono_error_init (&error);
4213 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4215 domain = mono_object_domain (type);
4216 if (type->type->byref)
4217 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4218 klass = startklass = mono_class_from_mono_type (type->type);
4220 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4222 mono_class_setup_methods (klass);
4223 mono_class_setup_vtable (klass);
4224 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4228 while ((event = mono_class_get_events (klass, &iter))) {
4230 method = event->add;
4232 method = event->remove;
4234 method = event->raise;
4236 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4237 if (bflags & BFLAGS_Public)
4239 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4240 if (bflags & BFLAGS_NonPublic)
4245 if (bflags & BFLAGS_NonPublic)
4251 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4252 if (bflags & BFLAGS_Static)
4253 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4256 if (bflags & BFLAGS_Instance)
4261 if (bflags & BFLAGS_Instance)
4267 if (utf8_name == NULL) {
4268 utf8_name = mono_string_to_utf8 (name);
4269 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4272 if (compare_func (event->name, utf8_name))
4276 if (g_hash_table_lookup (events, event))
4279 MonoReflectionEvent *ev_obj;
4280 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4283 mono_ptr_array_append (tmp_array, ev_obj);
4285 g_hash_table_insert (events, event, event);
4287 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4290 g_hash_table_destroy (events);
4292 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4294 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4295 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4297 mono_ptr_array_destroy (tmp_array);
4299 if (utf8_name != NULL)
4305 if (mono_class_has_failure (klass)) {
4306 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4308 mono_error_set_from_loader_error (&error);
4309 mono_loader_clear_error ();
4315 g_hash_table_destroy (events);
4316 if (utf8_name != NULL)
4319 mono_ptr_array_destroy (tmp_array);
4321 mono_error_set_pending_exception (&error);
4325 ICALL_EXPORT MonoArray*
4326 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4329 MonoReflectionType *rt;
4337 MonoPtrArray tmp_array;
4339 domain = ((MonoObject *)type)->vtable->domain;
4340 if (type->type->byref)
4341 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4342 klass = mono_class_from_mono_type (type->type);
4345 * If a nested type is generic, return its generic type definition.
4346 * Note that this means that the return value is essentially the set
4347 * of nested types of the generic type definition of @klass.
4349 * A note in MSDN claims that a generic type definition can have
4350 * nested types that aren't generic. In any case, the container of that
4351 * nested type would be the generic type definition.
4353 if (klass->generic_class)
4354 klass = klass->generic_class->container_class;
4356 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4358 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4360 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4361 if (bflags & BFLAGS_Public)
4364 if (bflags & BFLAGS_NonPublic)
4372 str = mono_string_to_utf8 (name);
4373 mono_identifier_unescape_type_name_chars (str);
4376 if (strcmp (nested->name, str))
4380 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4381 mono_error_raise_exception (&error);
4383 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4386 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4388 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4389 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4391 mono_ptr_array_destroy (tmp_array);
4398 ICALL_EXPORT MonoReflectionType*
4399 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4402 MonoReflectionType *ret;
4404 MonoType *type = NULL;
4405 MonoTypeNameParse info;
4406 gboolean type_resolve;
4408 /* On MS.NET, this does not fire a TypeResolve event */
4409 type_resolve = TRUE;
4410 str = mono_string_to_utf8 (name);
4411 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4412 if (!mono_reflection_parse_type (str, &info)) {
4414 mono_reflection_free_type_info (&info);
4416 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4419 /*g_print ("failed parse\n");*/
4423 if (info.assembly.name) {
4425 mono_reflection_free_type_info (&info);
4427 /* 1.0 and 2.0 throw different exceptions */
4428 if (mono_defaults.generic_ilist_class)
4429 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4431 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4437 if (module != NULL) {
4438 if (module->image) {
4439 type = mono_reflection_get_type_checked (module->image, &info, ignoreCase, &type_resolve, &error);
4440 if (!is_ok (&error)) {
4442 mono_reflection_free_type_info (&info);
4443 mono_error_set_pending_exception (&error);
4450 if (assembly_is_dynamic (assembly->assembly)) {
4451 /* Enumerate all modules */
4452 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4456 if (abuilder->modules) {
4457 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4458 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4459 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4460 if (!is_ok (&error)) {
4462 mono_reflection_free_type_info (&info);
4463 mono_error_set_pending_exception (&error);
4471 if (!type && abuilder->loaded_modules) {
4472 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4473 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4474 type = mono_reflection_get_type_checked (mod->image, &info, ignoreCase, &type_resolve, &error);
4475 if (!is_ok (&error)) {
4477 mono_reflection_free_type_info (&info);
4478 mono_error_set_pending_exception (&error);
4487 type = mono_reflection_get_type_checked (assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4488 if (!is_ok (&error)) {
4490 mono_reflection_free_type_info (&info);
4491 mono_error_set_pending_exception (&error);
4496 mono_reflection_free_type_info (&info);
4498 MonoException *e = NULL;
4501 e = mono_get_exception_type_load (name, NULL);
4503 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4504 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4506 mono_loader_clear_error ();
4509 mono_set_pending_exception (e);
4511 } else if (mono_loader_get_last_error ()) {
4513 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4516 mono_loader_clear_error ();
4519 if (type->type == MONO_TYPE_CLASS) {
4520 MonoClass *klass = mono_type_get_class (type);
4522 /* need to report exceptions ? */
4523 if (throwOnError && mono_class_has_failure (klass)) {
4524 /* report SecurityException (or others) that occured when loading the assembly */
4525 MonoException *exc = mono_class_get_exception_for_failure (klass);
4526 mono_loader_clear_error ();
4527 mono_set_pending_exception (exc);
4532 /* g_print ("got it\n"); */
4533 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4534 mono_error_set_pending_exception (&error);
4540 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4543 gchar *shadow_ini_file;
4546 /* Check for shadow-copied assembly */
4547 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4548 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4550 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4551 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4557 g_free (shadow_ini_file);
4558 if (content != NULL) {
4561 *filename = content;
4568 ICALL_EXPORT MonoString *
4569 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4571 MonoDomain *domain = mono_object_domain (assembly);
4572 MonoAssembly *mass = assembly->assembly;
4573 MonoString *res = NULL;
4578 if (g_path_is_absolute (mass->image->name)) {
4579 absolute = g_strdup (mass->image->name);
4580 dirname = g_path_get_dirname (absolute);
4582 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4583 dirname = g_strdup (mass->basedir);
4586 replace_shadow_path (domain, dirname, &absolute);
4591 for (i = strlen (absolute) - 1; i >= 0; i--)
4592 if (absolute [i] == '\\')
4597 uri = g_filename_to_uri (absolute, NULL, NULL);
4599 const char *prepend = "file://";
4601 if (*absolute == '/' && *(absolute + 1) == '/') {
4604 prepend = "file:///";
4607 uri = g_strconcat (prepend, absolute, NULL);
4611 res = mono_string_new (domain, uri);
4618 ICALL_EXPORT MonoBoolean
4619 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4621 MonoAssembly *mass = assembly->assembly;
4623 return mass->in_gac;
4626 ICALL_EXPORT MonoReflectionAssembly*
4627 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4632 MonoImageOpenStatus status;
4633 MonoReflectionAssembly* result = NULL;
4635 name = mono_string_to_utf8 (mname);
4636 res = mono_assembly_load_with_partial_name (name, &status);
4642 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4644 mono_error_set_pending_exception (&error);
4648 ICALL_EXPORT MonoString *
4649 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4651 MonoDomain *domain = mono_object_domain (assembly);
4654 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4659 ICALL_EXPORT MonoBoolean
4660 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4662 return assembly->assembly->ref_only;
4665 ICALL_EXPORT MonoString *
4666 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4668 MonoDomain *domain = mono_object_domain (assembly);
4670 return mono_string_new (domain, assembly->assembly->image->version);
4673 ICALL_EXPORT MonoReflectionMethod*
4674 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4677 MonoReflectionMethod *res = NULL;
4680 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4684 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4685 if (!mono_error_ok (&error))
4688 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4691 if (!mono_error_ok (&error))
4692 mono_error_set_pending_exception (&error);
4696 ICALL_EXPORT MonoReflectionModule*
4697 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4700 MonoReflectionModule *result = NULL;
4701 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4702 if (!mono_error_ok (&error))
4703 mono_error_set_pending_exception (&error);
4707 ICALL_EXPORT MonoArray*
4708 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4710 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4711 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4715 for (i = 0; i < table->rows; ++i) {
4716 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4717 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4723 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4725 static MonoMethod *create_version = NULL;
4729 mono_error_init (error);
4732 if (!create_version) {
4733 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4734 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4735 g_assert (create_version);
4736 mono_method_desc_free (desc);
4742 args [3] = &revision;
4743 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4744 return_val_if_nok (error, NULL);
4746 mono_runtime_invoke_checked (create_version, result, args, error);
4747 return_val_if_nok (error, NULL);
4752 ICALL_EXPORT MonoArray*
4753 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4757 MonoDomain *domain = mono_object_domain (assembly);
4759 static MonoMethod *create_culture = NULL;
4760 MonoImage *image = assembly->assembly->image;
4764 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4767 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4769 if (count > 0 && !create_culture) {
4770 MonoMethodDesc *desc = mono_method_desc_new (
4771 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4772 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4773 g_assert (create_culture);
4774 mono_method_desc_free (desc);
4777 for (i = 0; i < count; i++) {
4778 MonoObject *version;
4779 MonoReflectionAssemblyName *aname;
4780 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4782 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4784 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4785 domain, mono_class_get_assembly_name_class (), &error);
4786 mono_error_raise_exception (&error);
4788 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4790 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4791 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4792 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4793 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4794 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4795 aname->versioncompat = 1; /* SameMachine (default) */
4796 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4798 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4799 mono_error_raise_exception (&error);
4801 MONO_OBJECT_SETREF (aname, version, version);
4803 if (create_culture) {
4805 MonoBoolean assembly_ref = 1;
4806 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4807 args [1] = &assembly_ref;
4809 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4810 mono_error_raise_exception (&error);
4812 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4815 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4816 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4817 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4819 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4820 /* public key token isn't copied - the class library will
4821 automatically generate it from the public key if required */
4822 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4823 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4825 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4826 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4829 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4832 /* note: this function doesn't return the codebase on purpose (i.e. it can
4833 be used under partial trust as path information isn't present). */
4835 mono_array_setref (result, i, aname);
4840 /* move this in some file in mono/util/ */
4842 g_concat_dir_and_file (const char *dir, const char *file)
4844 g_return_val_if_fail (dir != NULL, NULL);
4845 g_return_val_if_fail (file != NULL, NULL);
4848 * If the directory name doesn't have a / on the end, we need
4849 * to add one so we get a proper path to the file
4851 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4852 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4854 return g_strconcat (dir, file, NULL);
4858 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4861 char *n = mono_string_to_utf8 (name);
4862 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4864 guint32 cols [MONO_MANIFEST_SIZE];
4865 guint32 impl, file_idx;
4869 for (i = 0; i < table->rows; ++i) {
4870 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4871 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4872 if (strcmp (val, n) == 0)
4876 if (i == table->rows)
4879 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4882 * this code should only be called after obtaining the
4883 * ResourceInfo and handling the other cases.
4885 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4886 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4888 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4893 module = assembly->assembly->image;
4896 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4897 mono_error_raise_exception (&error);
4898 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4900 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4903 ICALL_EXPORT gboolean
4904 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4907 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4909 guint32 cols [MONO_MANIFEST_SIZE];
4910 guint32 file_cols [MONO_FILE_SIZE];
4914 n = mono_string_to_utf8 (name);
4915 for (i = 0; i < table->rows; ++i) {
4916 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4917 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4918 if (strcmp (val, n) == 0)
4922 if (i == table->rows)
4925 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4926 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4929 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4930 case MONO_IMPLEMENTATION_FILE:
4931 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4932 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4933 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4934 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4935 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4936 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4939 info->location = RESOURCE_LOCATION_EMBEDDED;
4942 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4943 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4944 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4945 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4946 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4947 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4949 mono_set_pending_exception (ex);
4952 MonoReflectionAssembly *assm_obj;
4953 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4955 mono_error_set_pending_exception (&error);
4958 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4960 /* Obtain info recursively */
4961 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4962 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4965 case MONO_IMPLEMENTATION_EXP_TYPE:
4966 g_assert_not_reached ();
4974 ICALL_EXPORT MonoObject*
4975 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4977 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4978 MonoArray *result = NULL;
4983 /* check hash if needed */
4985 n = mono_string_to_utf8 (name);
4986 for (i = 0; i < table->rows; ++i) {
4987 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4988 if (strcmp (val, n) == 0) {
4991 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4992 fn = mono_string_new (mono_object_domain (assembly), n);
4994 return (MonoObject*)fn;
5002 for (i = 0; i < table->rows; ++i) {
5003 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5007 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
5010 for (i = 0; i < table->rows; ++i) {
5011 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5012 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5013 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5014 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5019 return (MonoObject*)result;
5022 ICALL_EXPORT MonoArray*
5023 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5026 MonoDomain *domain = mono_domain_get();
5029 int i, j, file_count = 0;
5030 MonoImage **modules;
5031 guint32 module_count, real_module_count;
5032 MonoTableInfo *table;
5033 guint32 cols [MONO_FILE_SIZE];
5034 MonoImage *image = assembly->assembly->image;
5036 g_assert (image != NULL);
5037 g_assert (!assembly_is_dynamic (assembly->assembly));
5039 table = &image->tables [MONO_TABLE_FILE];
5040 file_count = table->rows;
5042 modules = image->modules;
5043 module_count = image->module_count;
5045 real_module_count = 0;
5046 for (i = 0; i < module_count; ++i)
5048 real_module_count ++;
5050 klass = mono_class_get_module_class ();
5051 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
5053 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5054 mono_error_raise_exception (&error);
5055 mono_array_setref (res, 0, image_obj);
5057 for (i = 0; i < module_count; ++i)
5059 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5060 mono_error_raise_exception (&error);
5061 mono_array_setref (res, j, rm);
5065 for (i = 0; i < file_count; ++i, ++j) {
5066 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5067 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5068 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5069 mono_error_raise_exception (&error);
5070 mono_array_setref (res, j, rm);
5073 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5075 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5076 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5079 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5080 mono_error_raise_exception (&error);
5081 mono_array_setref (res, j, rm);
5088 ICALL_EXPORT MonoReflectionMethod*
5089 ves_icall_GetCurrentMethod (void)
5091 MonoReflectionMethod *res = NULL;
5094 MonoMethod *m = mono_method_get_last_managed ();
5097 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5101 while (m->is_inflated)
5102 m = ((MonoMethodInflated*)m)->declaring;
5104 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5105 mono_error_raise_exception (&error);
5111 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5114 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5117 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5118 //method is inflated, we should inflate it on the other class
5119 MonoGenericContext ctx;
5120 ctx.method_inst = inflated->context.method_inst;
5121 ctx.class_inst = inflated->context.class_inst;
5122 if (klass->generic_class)
5123 ctx.class_inst = klass->generic_class->context.class_inst;
5124 else if (klass->generic_container)
5125 ctx.class_inst = klass->generic_container->context.class_inst;
5126 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5127 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5131 mono_class_setup_methods (method->klass);
5132 if (mono_class_has_failure (method->klass))
5134 for (i = 0; i < method->klass->method.count; ++i) {
5135 if (method->klass->methods [i] == method) {
5140 mono_class_setup_methods (klass);
5141 if (mono_class_has_failure (klass))
5143 g_assert (offset >= 0 && offset < klass->method.count);
5144 return klass->methods [offset];
5147 ICALL_EXPORT MonoReflectionMethod*
5148 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5150 MonoReflectionMethod *res = NULL;
5154 klass = mono_class_from_mono_type (type);
5155 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5157 if (method->klass != klass) {
5158 method = mono_method_get_equivalent_method (method, klass);
5163 klass = method->klass;
5164 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5165 mono_error_raise_exception (&error);
5169 ICALL_EXPORT MonoReflectionMethodBody*
5170 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5173 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5174 mono_error_set_pending_exception (&error);
5178 ICALL_EXPORT MonoReflectionAssembly*
5179 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5182 MonoReflectionAssembly *result;
5183 MonoMethod *dest = NULL;
5185 mono_stack_walk_no_il (get_executing, &dest);
5187 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5189 mono_error_set_pending_exception (&error);
5194 ICALL_EXPORT MonoReflectionAssembly*
5195 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5198 MonoReflectionAssembly *result;
5199 MonoDomain* domain = mono_domain_get ();
5201 if (!domain->entry_assembly)
5204 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5206 mono_error_set_pending_exception (&error);
5210 ICALL_EXPORT MonoReflectionAssembly*
5211 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5216 MonoReflectionAssembly *result;
5219 mono_stack_walk_no_il (get_executing, &dest);
5221 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5225 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5228 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5230 mono_error_set_pending_exception (&error);
5234 ICALL_EXPORT MonoString *
5235 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5236 gboolean assembly_qualified)
5238 MonoDomain *domain = mono_object_domain (object);
5239 MonoTypeNameFormat format;
5244 format = assembly_qualified ?
5245 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5246 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5248 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5250 name = mono_type_get_name_full (object->type, format);
5254 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5259 res = mono_string_new (domain, name);
5266 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5269 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5271 mono_class_init_checked (klass, &error);
5272 mono_error_raise_exception (&error);
5273 return mono_security_core_clr_class_level (klass);
5277 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5279 MonoClassField *field = rfield->field;
5280 return mono_security_core_clr_field_level (field, TRUE);
5284 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5286 MonoMethod *method = rfield->method;
5287 return mono_security_core_clr_method_level (method, TRUE);
5291 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)
5293 static MonoMethod *create_culture = NULL;
5297 const char *pkey_ptr;
5299 MonoBoolean assembly_ref = 0;
5301 mono_error_init (error);
5303 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5304 aname->major = name->major;
5305 aname->minor = name->minor;
5306 aname->build = name->build;
5307 aname->flags = name->flags;
5308 aname->revision = name->revision;
5309 aname->hashalg = name->hash_alg;
5310 aname->versioncompat = 1; /* SameMachine (default) */
5311 aname->processor_architecture = name->arch;
5313 if (by_default_version) {
5314 MonoObject *version;
5316 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5317 return_if_nok (error);
5319 MONO_OBJECT_SETREF (aname, version, version);
5323 if (absolute != NULL && *absolute != '\0') {
5324 const gchar *prepend = "file://";
5327 codebase = g_strdup (absolute);
5332 for (i = strlen (codebase) - 1; i >= 0; i--)
5333 if (codebase [i] == '\\')
5336 if (*codebase == '/' && *(codebase + 1) == '/') {
5339 prepend = "file:///";
5343 result = g_strconcat (prepend, codebase, NULL);
5349 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5353 if (!create_culture) {
5354 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5355 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5356 g_assert (create_culture);
5357 mono_method_desc_free (desc);
5360 if (name->culture) {
5361 args [0] = mono_string_new (domain, name->culture);
5362 args [1] = &assembly_ref;
5364 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5365 return_if_nok (error);
5367 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5370 if (name->public_key) {
5371 pkey_ptr = (char*)name->public_key;
5372 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5374 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5375 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5376 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5377 } else if (default_publickey) {
5378 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5379 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5382 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5383 if (name->public_key_token [0]) {
5387 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5388 p = mono_array_addr (aname->keyToken, char, 0);
5390 for (i = 0, j = 0; i < 8; i++) {
5391 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5392 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5395 } else if (default_token) {
5396 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5400 ICALL_EXPORT MonoString *
5401 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5403 MonoDomain *domain = mono_object_domain (assembly);
5404 MonoAssembly *mass = assembly->assembly;
5408 name = mono_stringify_assembly_name (&mass->aname);
5409 res = mono_string_new (domain, name);
5416 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5420 MonoAssembly *mass = assembly->assembly;
5422 if (g_path_is_absolute (mass->image->name)) {
5423 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5424 mono_error_set_pending_exception (&error);
5427 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5429 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5430 mono_error_set_pending_exception (&error);
5436 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5440 MonoImageOpenStatus status = MONO_IMAGE_OK;
5443 MonoAssemblyName name;
5446 filename = mono_string_to_utf8 (fname);
5448 dirname = g_path_get_dirname (filename);
5449 replace_shadow_path (mono_domain_get (), dirname, &filename);
5452 image = mono_image_open (filename, &status);
5458 if (status == MONO_IMAGE_IMAGE_INVALID)
5459 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5461 exc = mono_get_exception_file_not_found2 (NULL, fname);
5462 mono_set_pending_exception (exc);
5466 res = mono_assembly_fill_assembly_name (image, &name);
5468 mono_image_close (image);
5470 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5474 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5475 mono_error_set_pending_exception (&error);
5477 mono_image_close (image);
5481 ICALL_EXPORT MonoBoolean
5482 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5483 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5485 MonoBoolean result = FALSE;
5486 MonoDeclSecurityEntry entry;
5488 /* SecurityAction.RequestMinimum */
5489 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5490 *minimum = entry.blob;
5491 *minLength = entry.size;
5494 /* SecurityAction.RequestOptional */
5495 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5496 *optional = entry.blob;
5497 *optLength = entry.size;
5500 /* SecurityAction.RequestRefuse */
5501 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5502 *refused = entry.blob;
5503 *refLength = entry.size;
5511 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5513 guint32 attrs, visibility;
5515 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5516 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5517 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5520 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5526 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5528 MonoReflectionType *rt;
5531 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5534 mono_error_init (error);
5536 /* we start the count from 1 because we skip the special type <Module> */
5539 for (i = 1; i < tdef->rows; ++i) {
5540 if (mono_module_type_is_visible (tdef, image, i + 1))
5544 count = tdef->rows - 1;
5546 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5547 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5549 for (i = 1; i < tdef->rows; ++i) {
5550 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5551 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5552 mono_loader_assert_no_error (); /* Plug any leaks */
5555 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5556 return_val_if_nok (error, NULL);
5558 mono_array_setref (res, count, rt);
5560 MonoException *ex = mono_error_convert_to_exception (error);
5561 mono_array_setref (*exceptions, count, ex);
5570 ICALL_EXPORT MonoArray*
5571 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5574 MonoArray *res = NULL;
5575 MonoArray *exceptions = NULL;
5576 MonoImage *image = NULL;
5577 MonoTableInfo *table = NULL;
5580 int i, len, ex_count;
5582 domain = mono_object_domain (assembly);
5584 g_assert (!assembly_is_dynamic (assembly->assembly));
5585 image = assembly->assembly->image;
5586 table = &image->tables [MONO_TABLE_FILE];
5587 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5588 mono_error_raise_exception (&error);
5590 /* Append data from all modules in the assembly */
5591 for (i = 0; i < table->rows; ++i) {
5592 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5593 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5598 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5599 mono_error_raise_exception (&error);
5601 /* Append the new types to the end of the array */
5602 if (mono_array_length (res2) > 0) {
5604 MonoArray *res3, *ex3;
5606 len1 = mono_array_length (res);
5607 len2 = mono_array_length (res2);
5609 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5610 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5611 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5614 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5615 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5616 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5623 /* the ReflectionTypeLoadException must have all the types (Types property),
5624 * NULL replacing types which throws an exception. The LoaderException must
5625 * contain all exceptions for NULL items.
5628 len = mono_array_length (res);
5631 for (i = 0; i < len; i++) {
5632 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5636 klass = mono_type_get_class (t->type);
5637 if ((klass != NULL) && mono_class_has_failure (klass)) {
5638 /* keep the class in the list */
5639 list = g_list_append (list, klass);
5640 /* and replace Type with NULL */
5641 mono_array_setref (res, i, NULL);
5648 if (list || ex_count) {
5650 MonoException *exc = NULL;
5651 MonoArray *exl = NULL;
5652 int j, length = g_list_length (list) + ex_count;
5654 mono_loader_clear_error ();
5656 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5657 /* Types for which mono_class_get_checked () succeeded */
5658 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5659 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5660 mono_array_setref (exl, i, exc);
5662 /* Types for which it don't */
5663 for (j = 0; j < mono_array_length (exceptions); ++j) {
5664 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5666 g_assert (i < length);
5667 mono_array_setref (exl, i, exc);
5674 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5675 if (!is_ok (&error)) {
5676 mono_error_set_pending_exception (&error);
5679 mono_loader_clear_error ();
5680 mono_set_pending_exception (exc);
5687 ICALL_EXPORT gboolean
5688 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5691 MonoAssemblyName aname;
5692 MonoDomain *domain = mono_object_domain (name);
5694 gboolean is_version_defined;
5695 gboolean is_token_defined;
5697 aname.public_key = NULL;
5698 val = mono_string_to_utf8 (assname);
5699 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5700 g_free ((guint8*) aname.public_key);
5705 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5706 mono_error_set_pending_exception (&error);
5708 mono_assembly_name_free (&aname);
5709 g_free ((guint8*) aname.public_key);
5715 ICALL_EXPORT MonoReflectionType*
5716 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5719 MonoReflectionType *ret;
5720 MonoDomain *domain = mono_object_domain (module);
5723 g_assert (module->image);
5725 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5726 /* These images do not have a global type */
5729 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5730 if (!mono_error_ok (&error)) {
5731 mono_error_set_pending_exception (&error);
5735 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5736 if (!mono_error_ok (&error)) {
5737 mono_error_set_pending_exception (&error);
5745 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5747 /*if (module->image)
5748 mono_image_close (module->image);*/
5751 ICALL_EXPORT MonoString*
5752 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5754 MonoDomain *domain = mono_object_domain (module);
5756 g_assert (module->image);
5757 return mono_string_new (domain, module->image->guid);
5760 ICALL_EXPORT gpointer
5761 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5764 if (module->image && module->image->is_module_handle)
5765 return module->image->raw_data;
5768 return (gpointer) (-1);
5772 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5774 if (image_is_dynamic (image)) {
5775 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5776 *pe_kind = dyn->pe_kind;
5777 *machine = dyn->machine;
5780 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5781 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5786 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5788 return (image->md_version_major << 16) | (image->md_version_minor);
5791 ICALL_EXPORT MonoArray*
5792 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5795 MonoArray *exceptions;
5799 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5803 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5804 mono_error_raise_exception (&error);
5806 for (i = 0; i < mono_array_length (exceptions); ++i) {
5807 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5809 mono_set_pending_exception (ex);
5818 mono_memberref_is_method (MonoImage *image, guint32 token)
5820 if (!image_is_dynamic (image)) {
5821 guint32 cols [MONO_MEMBERREF_SIZE];
5823 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5824 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5825 mono_metadata_decode_blob_size (sig, &sig);
5826 return (*sig != 0x6);
5828 MonoClass *handle_class;
5830 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5833 return mono_defaults.methodhandle_class == handle_class;
5838 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5841 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5842 mono_array_addr (type_args, MonoType*, 0));
5844 context->class_inst = NULL;
5846 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5847 mono_array_addr (method_args, MonoType*, 0));
5849 context->method_inst = NULL;
5852 ICALL_EXPORT MonoType*
5853 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5856 int table = mono_metadata_token_table (token);
5857 int index = mono_metadata_token_index (token);
5858 MonoGenericContext context;
5861 *resolve_error = ResolveTokenError_Other;
5863 /* Validate token */
5864 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5865 (table != MONO_TABLE_TYPESPEC)) {
5866 *resolve_error = ResolveTokenError_BadTable;
5870 if (image_is_dynamic (image)) {
5871 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5872 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5873 return klass ? &klass->byval_arg : NULL;
5876 init_generic_context_from_args (&context, type_args, method_args);
5877 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5878 return klass ? &klass->byval_arg : NULL;
5881 if ((index <= 0) || (index > image->tables [table].rows)) {
5882 *resolve_error = ResolveTokenError_OutOfRange;
5886 init_generic_context_from_args (&context, type_args, method_args);
5887 klass = mono_class_get_checked (image, token, &error);
5889 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5890 if (!mono_error_ok (&error)) {
5891 mono_error_set_pending_exception (&error);
5896 return &klass->byval_arg;
5901 ICALL_EXPORT MonoMethod*
5902 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5905 int table = mono_metadata_token_table (token);
5906 int index = mono_metadata_token_index (token);
5907 MonoGenericContext context;
5910 *resolve_error = ResolveTokenError_Other;
5912 /* Validate token */
5913 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5914 (table != MONO_TABLE_MEMBERREF)) {
5915 *resolve_error = ResolveTokenError_BadTable;
5919 if (image_is_dynamic (image)) {
5920 if (table == MONO_TABLE_METHOD)
5921 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5923 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5924 *resolve_error = ResolveTokenError_BadTable;
5928 init_generic_context_from_args (&context, type_args, method_args);
5929 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5932 if ((index <= 0) || (index > image->tables [table].rows)) {
5933 *resolve_error = ResolveTokenError_OutOfRange;
5936 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5937 *resolve_error = ResolveTokenError_BadTable;
5941 init_generic_context_from_args (&context, type_args, method_args);
5942 method = mono_get_method_checked (image, token, NULL, &context, &error);
5943 mono_error_set_pending_exception (&error);
5948 ICALL_EXPORT MonoString*
5949 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5951 int index = mono_metadata_token_index (token);
5953 *error = ResolveTokenError_Other;
5955 /* Validate token */
5956 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5957 *error = ResolveTokenError_BadTable;
5961 if (image_is_dynamic (image))
5962 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5964 if ((index <= 0) || (index >= image->heap_us.size)) {
5965 *error = ResolveTokenError_OutOfRange;
5969 /* FIXME: What to do if the index points into the middle of a string ? */
5971 return mono_ldstr (mono_domain_get (), image, index);
5974 ICALL_EXPORT MonoClassField*
5975 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5979 int table = mono_metadata_token_table (token);
5980 int index = mono_metadata_token_index (token);
5981 MonoGenericContext context;
5982 MonoClassField *field;
5984 *resolve_error = ResolveTokenError_Other;
5986 /* Validate token */
5987 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5988 *resolve_error = ResolveTokenError_BadTable;
5992 if (image_is_dynamic (image)) {
5993 if (table == MONO_TABLE_FIELD)
5994 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5996 if (mono_memberref_is_method (image, token)) {
5997 *resolve_error = ResolveTokenError_BadTable;
6001 init_generic_context_from_args (&context, type_args, method_args);
6002 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
6005 if ((index <= 0) || (index > image->tables [table].rows)) {
6006 *resolve_error = ResolveTokenError_OutOfRange;
6009 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6010 *resolve_error = ResolveTokenError_BadTable;
6014 init_generic_context_from_args (&context, type_args, method_args);
6015 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6016 mono_error_set_pending_exception (&error);
6022 ICALL_EXPORT MonoObject*
6023 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6027 int table = mono_metadata_token_table (token);
6029 *error = ResolveTokenError_Other;
6032 case MONO_TABLE_TYPEDEF:
6033 case MONO_TABLE_TYPEREF:
6034 case MONO_TABLE_TYPESPEC: {
6035 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6037 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6038 mono_error_raise_exception (&merror);
6045 case MONO_TABLE_METHOD:
6046 case MONO_TABLE_METHODSPEC: {
6047 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6049 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6050 mono_error_raise_exception (&merror);
6056 case MONO_TABLE_FIELD: {
6057 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6059 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6060 mono_error_raise_exception (&merror);
6066 case MONO_TABLE_MEMBERREF:
6067 if (mono_memberref_is_method (image, token)) {
6068 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6070 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6071 mono_error_raise_exception (&merror);
6078 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6080 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6081 mono_error_raise_exception (&merror);
6090 *error = ResolveTokenError_BadTable;
6096 ICALL_EXPORT MonoArray*
6097 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
6099 int table = mono_metadata_token_table (token);
6100 int idx = mono_metadata_token_index (token);
6101 MonoTableInfo *tables = image->tables;
6106 *error = ResolveTokenError_OutOfRange;
6108 /* FIXME: Support other tables ? */
6109 if (table != MONO_TABLE_STANDALONESIG)
6112 if (image_is_dynamic (image))
6115 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6118 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6120 ptr = mono_metadata_blob_heap (image, sig);
6121 len = mono_metadata_decode_blob_size (ptr, &ptr);
6123 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
6124 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6128 ICALL_EXPORT MonoReflectionType*
6129 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6132 MonoReflectionType *ret;
6134 int isbyref = 0, rank;
6135 char *str = mono_string_to_utf8 (smodifiers);
6138 klass = mono_class_from_mono_type (tb->type.type);
6140 /* logic taken from mono_reflection_parse_type(): keep in sync */
6144 if (isbyref) { /* only one level allowed by the spec */
6153 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6154 mono_error_raise_exception (&error);
6158 klass = mono_ptr_class_get (&klass->byval_arg);
6159 mono_class_init (klass);
6170 else if (*p != '*') { /* '*' means unknown lower bound */
6181 klass = mono_array_class_get (klass, rank);
6182 mono_class_init (klass);
6191 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6192 mono_error_raise_exception (&error);
6197 ICALL_EXPORT MonoBoolean
6198 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6204 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6210 check_for_invalid_type (MonoClass *klass, MonoError *error)
6215 mono_error_init (error);
6217 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6220 name = mono_type_get_full_name (klass);
6221 str = mono_string_new (mono_domain_get (), name);
6223 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6226 ICALL_EXPORT MonoReflectionType *
6227 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6230 MonoReflectionType *ret;
6231 MonoClass *klass, *aklass;
6233 klass = mono_class_from_mono_type (type->type);
6234 check_for_invalid_type (klass, &error);
6235 mono_error_raise_exception (&error);
6237 if (rank == 0) //single dimentional array
6238 aklass = mono_array_class_get (klass, 1);
6240 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6242 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6243 mono_error_raise_exception (&error);
6248 ICALL_EXPORT MonoReflectionType *
6249 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6252 MonoReflectionType *ret;
6255 klass = mono_class_from_mono_type (type->type);
6256 mono_class_init_checked (klass, &error);
6257 mono_error_raise_exception (&error);
6258 check_for_invalid_type (klass, &error);
6259 mono_error_raise_exception (&error);
6261 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6262 mono_error_raise_exception (&error);
6267 ICALL_EXPORT MonoReflectionType *
6268 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6271 MonoReflectionType *ret;
6272 MonoClass *klass, *pklass;
6274 klass = mono_class_from_mono_type (type->type);
6275 mono_class_init_checked (klass, &error);
6276 mono_error_raise_exception (&error);
6277 check_for_invalid_type (klass, &error);
6278 mono_error_raise_exception (&error);
6280 pklass = mono_ptr_class_get (type->type);
6282 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6283 mono_error_raise_exception (&error);
6288 ICALL_EXPORT MonoObject *
6289 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6290 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6293 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6294 MonoObject *delegate;
6296 MonoMethod *method = info->method;
6298 mono_class_init_checked (delegate_class, &error);
6299 mono_error_raise_exception (&error);
6301 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6302 /* FIXME improve this exception message */
6303 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6305 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6306 mono_error_set_pending_exception (&error);
6310 if (mono_security_core_clr_enabled ()) {
6311 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6315 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6316 mono_error_raise_exception (&error);
6318 if (method_is_dynamic (method)) {
6319 /* Creating a trampoline would leak memory */
6320 func = mono_compile_method (method);
6322 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6323 method = mono_object_get_virtual_method (target, method);
6324 func = mono_create_ftnptr (mono_domain_get (),
6325 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6328 mono_delegate_ctor_with_method (delegate, target, func, method);
6333 ICALL_EXPORT MonoMulticastDelegate *
6334 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6337 MonoMulticastDelegate *ret;
6339 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6341 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6342 mono_error_raise_exception (&error);
6343 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6348 ICALL_EXPORT MonoReflectionMethod*
6349 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6351 MonoReflectionMethod *ret = NULL;
6353 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6354 mono_error_raise_exception (&error);
6360 static inline gint32
6361 mono_array_get_byte_length (MonoArray *array)
6367 klass = array->obj.vtable->klass;
6369 if (array->bounds == NULL)
6370 length = array->max_length;
6373 for (i = 0; i < klass->rank; ++ i)
6374 length *= array->bounds [i].length;
6377 switch (klass->element_class->byval_arg.type) {
6380 case MONO_TYPE_BOOLEAN:
6384 case MONO_TYPE_CHAR:
6392 return length * sizeof (gpointer);
6403 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6405 return mono_array_get_byte_length (array);
6409 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6411 return mono_array_get (array, gint8, idx);
6415 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6417 mono_array_set (array, gint8, idx, value);
6420 ICALL_EXPORT MonoBoolean
6421 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6423 guint8 *src_buf, *dest_buf;
6426 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6430 g_assert (count >= 0);
6432 /* This is called directly from the class libraries without going through the managed wrapper */
6433 MONO_CHECK_ARG_NULL (src, FALSE);
6434 MONO_CHECK_ARG_NULL (dest, FALSE);
6436 /* watch out for integer overflow */
6437 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6440 src_buf = (guint8 *)src->vector + src_offset;
6441 dest_buf = (guint8 *)dest->vector + dest_offset;
6444 memcpy (dest_buf, src_buf, count);
6446 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6451 #ifndef DISABLE_REMOTING
6452 ICALL_EXPORT MonoObject *
6453 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6456 MonoDomain *domain = mono_object_domain (this_obj);
6458 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6459 MonoTransparentProxy *tp;
6463 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6464 mono_error_raise_exception (&error);
6465 tp = (MonoTransparentProxy*) res;
6467 MONO_OBJECT_SETREF (tp, rp, rp);
6468 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6469 klass = mono_class_from_mono_type (type);
6471 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6472 mono_class_setup_vtable (klass);
6473 if (mono_class_has_failure (klass)) {
6474 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6478 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6479 if (!is_ok (&error)) {
6480 mono_error_set_pending_exception (&error);
6483 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6484 if (!is_ok (&error)) {
6485 mono_error_set_pending_exception (&error);
6489 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6493 ICALL_EXPORT MonoReflectionType *
6494 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6497 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6498 mono_error_raise_exception (&error);
6504 /* System.Environment */
6507 ves_icall_System_Environment_get_UserName (void)
6509 /* using glib is more portable */
6510 return mono_string_new (mono_domain_get (), g_get_user_name ());
6514 ICALL_EXPORT MonoString *
6515 ves_icall_System_Environment_get_MachineName (void)
6517 #if defined (HOST_WIN32)
6522 len = MAX_COMPUTERNAME_LENGTH + 1;
6523 buf = g_new (gunichar2, len);
6526 if (GetComputerName (buf, (PDWORD) &len)) {
6528 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6529 mono_error_raise_exception (&error);
6534 #elif !defined(DISABLE_SOCKETS)
6538 #if defined _SC_HOST_NAME_MAX
6539 n = sysconf (_SC_HOST_NAME_MAX);
6543 buf = g_malloc (n+1);
6545 if (gethostname (buf, n) == 0){
6547 result = mono_string_new (mono_domain_get (), buf);
6554 return mono_string_new (mono_domain_get (), "mono");
6559 ves_icall_System_Environment_get_Platform (void)
6561 #if defined (TARGET_WIN32)
6564 #elif defined(__MACH__)
6567 // Notice that the value is hidden from user code, and only exposed
6568 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6569 // define and making assumptions based on Unix/128/4 values before there
6570 // was a MacOS define. Lots of code would assume that not-Unix meant
6571 // Windows, but in this case, it would be OSX.
6580 ICALL_EXPORT MonoString *
6581 ves_icall_System_Environment_get_NewLine (void)
6583 #if defined (HOST_WIN32)
6584 return mono_string_new (mono_domain_get (), "\r\n");
6586 return mono_string_new (mono_domain_get (), "\n");
6590 ICALL_EXPORT MonoBoolean
6591 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6593 #if SIZEOF_VOID_P == 8
6597 gboolean isWow64Process = FALSE;
6598 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6599 return (MonoBoolean)isWow64Process;
6601 #elif defined(HAVE_SYS_UTSNAME_H)
6602 struct utsname name;
6604 if (uname (&name) >= 0) {
6605 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6612 ICALL_EXPORT MonoString *
6613 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6621 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6622 value = g_getenv (utf8_name);
6629 return mono_string_new (mono_domain_get (), value);
6633 * There is no standard way to get at environ.
6636 #ifndef __MINGW32_VERSION
6637 #if defined(__APPLE__)
6638 #if defined (TARGET_OSX)
6639 /* Apple defines this in crt_externs.h but doesn't provide that header for
6640 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6641 * in fact exist on all implementations (so far)
6643 gchar ***_NSGetEnviron(void);
6644 #define environ (*_NSGetEnviron())
6646 static char *mono_environ[1] = { NULL };
6647 #define environ mono_environ
6648 #endif /* defined (TARGET_OSX) */
6656 ICALL_EXPORT MonoArray *
6657 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6668 env_strings = GetEnvironmentStrings();
6671 env_string = env_strings;
6672 while (*env_string != '\0') {
6673 /* weird case that MS seems to skip */
6674 if (*env_string != '=')
6676 while (*env_string != '\0')
6682 domain = mono_domain_get ();
6683 names = mono_array_new (domain, mono_defaults.string_class, n);
6687 env_string = env_strings;
6688 while (*env_string != '\0') {
6689 /* weird case that MS seems to skip */
6690 if (*env_string != '=') {
6691 equal_str = wcschr(env_string, '=');
6692 g_assert(equal_str);
6694 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6695 mono_error_raise_exception (&error);
6696 mono_array_setref (names, n, str);
6699 while (*env_string != '\0')
6704 FreeEnvironmentStrings (env_strings);
6717 for (e = environ; *e != 0; ++ e)
6720 domain = mono_domain_get ();
6721 names = mono_array_new (domain, mono_defaults.string_class, n);
6724 for (e = environ; *e != 0; ++ e) {
6725 parts = g_strsplit (*e, "=", 2);
6727 str = mono_string_new (domain, *parts);
6728 mono_array_setref (names, n, str);
6741 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6743 #if !GLIB_CHECK_VERSION(2,4,0)
6744 #define g_setenv(a,b,c) setenv(a,b,c)
6745 #define g_unsetenv(a) unsetenv(a)
6749 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6752 gunichar2 *utf16_name, *utf16_value;
6754 gchar *utf8_name, *utf8_value;
6759 utf16_name = mono_string_to_utf16 (name);
6760 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6761 SetEnvironmentVariable (utf16_name, NULL);
6762 g_free (utf16_name);
6766 utf16_value = mono_string_to_utf16 (value);
6768 SetEnvironmentVariable (utf16_name, utf16_value);
6770 g_free (utf16_name);
6771 g_free (utf16_value);
6773 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6775 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6776 g_unsetenv (utf8_name);
6781 utf8_value = mono_string_to_utf8_checked (value, &error);
6782 if (!mono_error_ok (&error)) {
6784 mono_error_set_pending_exception (&error);
6787 g_setenv (utf8_name, utf8_value, TRUE);
6790 g_free (utf8_value);
6795 ves_icall_System_Environment_Exit (int result)
6797 mono_environment_exitcode_set (result);
6799 /* FIXME: There are some cleanup hangs that should be worked out, but
6800 * if the program is going to exit, everything will be cleaned up when
6801 * NaCl exits anyway.
6803 #ifndef __native_client__
6804 if (!mono_runtime_try_shutdown ())
6805 mono_thread_exit ();
6807 /* Suspend all managed threads since the runtime is going away */
6808 mono_thread_suspend_all_other_threads ();
6810 mono_runtime_quit ();
6813 /* we may need to do some cleanup here... */
6817 ICALL_EXPORT MonoString*
6818 ves_icall_System_Environment_GetGacPath (void)
6820 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6823 ICALL_EXPORT MonoString*
6824 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6826 #if defined (HOST_WIN32)
6827 #ifndef CSIDL_FLAG_CREATE
6828 #define CSIDL_FLAG_CREATE 0x8000
6831 WCHAR path [MAX_PATH];
6832 /* Create directory if no existing */
6833 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6838 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6839 mono_error_raise_exception (&error);
6843 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6845 return mono_string_new (mono_domain_get (), "");
6848 ICALL_EXPORT MonoArray *
6849 ves_icall_System_Environment_GetLogicalDrives (void)
6852 gunichar2 buf [256], *ptr, *dname;
6854 guint initial_size = 127, size = 128;
6857 MonoString *drivestr;
6858 MonoDomain *domain = mono_domain_get ();
6864 while (size > initial_size) {
6865 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6866 if (size > initial_size) {
6869 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6870 initial_size = size;
6884 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6889 while (*u16) { u16++; len ++; }
6890 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6891 mono_error_raise_exception (&error);
6892 mono_array_setref (result, ndrives++, drivestr);
6902 ICALL_EXPORT MonoString *
6903 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6905 gunichar2 volume_name [MAX_PATH + 1];
6907 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6909 return mono_string_from_utf16 (volume_name);
6912 ICALL_EXPORT MonoString *
6913 ves_icall_System_Environment_InternalGetHome (void)
6915 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6918 static const char *encodings [] = {
6920 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6921 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6922 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6924 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6925 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6926 "x_unicode_2_0_utf_7",
6928 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6929 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6931 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6934 "unicodefffe", "utf_16be",
6941 * Returns the internal codepage, if the value of "int_code_page" is
6942 * 1 at entry, and we can not compute a suitable code page number,
6943 * returns the code page as a string
6945 ICALL_EXPORT MonoString*
6946 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6951 char *codepage = NULL;
6953 int want_name = *int_code_page;
6956 *int_code_page = -1;
6958 g_get_charset (&cset);
6959 c = codepage = strdup (cset);
6960 for (c = codepage; *c; c++){
6961 if (isascii (*c) && isalpha (*c))
6966 /* g_print ("charset: %s\n", cset); */
6968 /* handle some common aliases */
6971 for (i = 0; p != 0; ){
6974 p = encodings [++i];
6977 if (strcmp (p, codepage) == 0){
6978 *int_code_page = code;
6981 p = encodings [++i];
6984 if (strstr (codepage, "utf_8") != NULL)
6985 *int_code_page |= 0x10000000;
6988 if (want_name && *int_code_page == -1)
6989 return mono_string_new (mono_domain_get (), cset);
6994 ICALL_EXPORT MonoBoolean
6995 ves_icall_System_Environment_get_HasShutdownStarted (void)
6997 if (mono_runtime_is_shutting_down ())
7000 if (mono_domain_is_unloading (mono_domain_get ()))
7007 ves_icall_System_Environment_BroadcastSettingChange (void)
7010 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7015 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7021 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
7022 MonoReflectionMethod *method,
7023 MonoArray *out_args)
7025 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
7028 #ifndef DISABLE_REMOTING
7029 ICALL_EXPORT MonoBoolean
7030 ves_icall_IsTransparentProxy (MonoObject *proxy)
7035 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7041 ICALL_EXPORT MonoReflectionMethod *
7042 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7043 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7045 MonoReflectionMethod *ret = NULL;
7050 MonoMethod **vtable;
7051 MonoMethod *res = NULL;
7053 MONO_CHECK_ARG_NULL (rtype, NULL);
7054 MONO_CHECK_ARG_NULL (rmethod, NULL);
7056 method = rmethod->method;
7057 klass = mono_class_from_mono_type (rtype->type);
7058 mono_class_init_checked (klass, &error);
7059 mono_error_raise_exception (&error);
7061 if (MONO_CLASS_IS_INTERFACE (klass))
7064 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7067 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7068 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7074 mono_class_setup_vtable (klass);
7075 vtable = klass->vtable;
7077 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7078 gboolean variance_used = FALSE;
7079 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7080 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7082 res = vtable [offs + method->slot];
7084 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7087 if (method->slot != -1)
7088 res = vtable [method->slot];
7094 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7095 mono_error_raise_exception (&error);
7100 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7106 klass = mono_class_from_mono_type (type->type);
7107 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7108 if (!is_ok (&error)) {
7109 mono_error_set_pending_exception (&error);
7113 mono_vtable_set_is_remote (vtable, enable);
7116 #else /* DISABLE_REMOTING */
7119 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7121 g_assert_not_reached ();
7126 ICALL_EXPORT MonoObject *
7127 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7134 domain = mono_object_domain (type);
7135 klass = mono_class_from_mono_type (type->type);
7136 mono_class_init_checked (klass, &error);
7137 mono_error_raise_exception (&error);
7139 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7140 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7144 if (klass->rank >= 1) {
7145 g_assert (klass->rank == 1);
7146 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7148 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7149 if (!is_ok (&error)) {
7150 mono_error_set_pending_exception (&error);
7153 /* Bypass remoting object creation check */
7154 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7155 mono_error_set_pending_exception (&error);
7161 ICALL_EXPORT MonoString *
7162 ves_icall_System_IO_get_temp_path (void)
7164 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7167 #ifndef PLATFORM_NO_DRIVEINFO
7168 ICALL_EXPORT MonoBoolean
7169 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7170 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7174 ULARGE_INTEGER wapi_free_bytes_avail;
7175 ULARGE_INTEGER wapi_total_number_of_bytes;
7176 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7178 *error = ERROR_SUCCESS;
7179 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7180 &wapi_total_number_of_free_bytes);
7183 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7184 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7185 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7187 *free_bytes_avail = 0;
7188 *total_number_of_bytes = 0;
7189 *total_number_of_free_bytes = 0;
7190 *error = GetLastError ();
7196 ICALL_EXPORT guint32
7197 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7199 return GetDriveType (mono_string_chars (root_path_name));
7203 ICALL_EXPORT gpointer
7204 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7206 return mono_compile_method (method);
7209 ICALL_EXPORT MonoString *
7210 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7215 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7217 #if defined (HOST_WIN32)
7218 /* Avoid mixing '/' and '\\' */
7221 for (i = strlen (path) - 1; i >= 0; i--)
7222 if (path [i] == '/')
7226 mcpath = mono_string_new (mono_domain_get (), path);
7233 get_bundled_app_config (void)
7235 const gchar *app_config;
7238 gchar *config_file_name, *config_file_path;
7239 gsize len, config_file_path_length, config_ext_length;
7242 domain = mono_domain_get ();
7243 file = domain->setup->configuration_file;
7244 if (!file || file->length == 0)
7247 // Retrieve config file and remove the extension
7248 config_file_name = mono_string_to_utf8 (file);
7249 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7250 if (!config_file_path)
7251 config_file_path = config_file_name;
7253 config_file_path_length = strlen (config_file_path);
7254 config_ext_length = strlen (".config");
7255 if (config_file_path_length <= config_ext_length)
7258 len = config_file_path_length - config_ext_length;
7259 module = (gchar *)g_malloc0 (len + 1);
7260 memcpy (module, config_file_path, len);
7261 // Get the config file from the module name
7262 app_config = mono_config_string_for_assembly_file (module);
7265 if (config_file_name != config_file_path)
7266 g_free (config_file_name);
7267 g_free (config_file_path);
7272 return mono_string_new (mono_domain_get (), app_config);
7276 get_bundled_machine_config (void)
7278 const gchar *machine_config;
7280 machine_config = mono_get_machine_config ();
7282 if (!machine_config)
7285 return mono_string_new (mono_domain_get (), machine_config);
7288 ICALL_EXPORT MonoString *
7289 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7294 path = g_path_get_dirname (mono_get_config_dir ());
7296 #if defined (HOST_WIN32)
7297 /* Avoid mixing '/' and '\\' */
7300 for (i = strlen (path) - 1; i >= 0; i--)
7301 if (path [i] == '/')
7305 ipath = mono_string_new (mono_domain_get (), path);
7311 ICALL_EXPORT gboolean
7312 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7314 MonoPEResourceDataEntry *entry;
7317 if (!assembly || !result || !size)
7322 image = assembly->assembly->image;
7323 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7327 *result = mono_image_rva_map (image, entry->rde_data_offset);
7332 *size = entry->rde_size;
7337 ICALL_EXPORT MonoBoolean
7338 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7340 return mono_is_debugger_attached ();
7343 ICALL_EXPORT MonoBoolean
7344 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7346 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7347 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7353 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7355 if (mono_get_runtime_callbacks ()->debug_log)
7356 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7360 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7362 #if defined (HOST_WIN32)
7363 OutputDebugString (mono_string_chars (message));
7365 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7369 /* Only used for value types */
7370 ICALL_EXPORT MonoObject *
7371 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7378 domain = mono_object_domain (type);
7379 klass = mono_class_from_mono_type (type->type);
7380 mono_class_init_checked (klass, &error);
7381 mono_error_raise_exception (&error);
7383 if (mono_class_is_nullable (klass))
7384 /* No arguments -> null */
7387 result = mono_object_new_checked (domain, klass, &error);
7388 mono_error_raise_exception (&error);
7392 ICALL_EXPORT MonoReflectionMethod *
7393 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7395 MonoReflectionMethod *ret = NULL;
7398 MonoClass *klass, *parent;
7399 MonoGenericContext *generic_inst = NULL;
7400 MonoMethod *method = m->method;
7401 MonoMethod *result = NULL;
7404 if (method->klass == NULL)
7407 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7408 MONO_CLASS_IS_INTERFACE (method->klass) ||
7409 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7412 slot = mono_method_get_vtable_slot (method);
7416 klass = method->klass;
7417 if (klass->generic_class) {
7418 generic_inst = mono_class_get_context (klass);
7419 klass = klass->generic_class->container_class;
7423 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7424 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7425 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7426 or klass is the generic container class and generic_inst is the instantiation.
7428 when we go to the parent, if the parent is an open constructed type, we need to
7429 replace the type parameters by the definitions from the generic_inst, and then take it
7430 apart again into the klass and the generic_inst.
7432 For cases like this:
7433 class C<T> : B<T, int> {
7434 public override void Foo () { ... }
7436 class B<U,V> : A<HashMap<U,V>> {
7437 public override void Foo () { ... }
7440 public virtual void Foo () { ... }
7443 if at each iteration the parent isn't open, we can skip inflating it. if at some
7444 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7447 MonoGenericContext *parent_inst = NULL;
7448 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7450 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7451 if (!mono_error_ok (&error)) {
7452 mono_error_set_pending_exception (&error);
7456 if (parent->generic_class) {
7457 parent_inst = mono_class_get_context (parent);
7458 parent = parent->generic_class->container_class;
7461 mono_class_setup_vtable (parent);
7462 if (parent->vtable_size <= slot)
7465 generic_inst = parent_inst;
7468 klass = klass->parent;
7471 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7472 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7473 if (!mono_error_ok (&error)) {
7474 mono_error_set_pending_exception (&error);
7478 generic_inst = NULL;
7480 if (klass->generic_class) {
7481 generic_inst = mono_class_get_context (klass);
7482 klass = klass->generic_class->container_class;
7488 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7489 if (!mono_error_ok (&error)) {
7490 mono_error_set_pending_exception (&error);
7495 if (klass == method->klass)
7498 /*This is possible if definition == FALSE.
7499 * Do it here to be really sure we don't read invalid memory.
7501 if (slot >= klass->vtable_size)
7504 mono_class_setup_vtable (klass);
7506 result = klass->vtable [slot];
7507 if (result == NULL) {
7508 /* It is an abstract method */
7509 gpointer iter = NULL;
7510 while ((result = mono_class_get_methods (klass, &iter)))
7511 if (result->slot == slot)
7518 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7519 mono_error_raise_exception (&error);
7523 ICALL_EXPORT MonoString*
7524 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7526 MonoMethod *method = m->method;
7528 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7533 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7535 iter->sig = *(MonoMethodSignature**)argsp;
7537 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7538 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7541 /* FIXME: it's not documented what start is exactly... */
7545 iter->args = argsp + sizeof (gpointer);
7547 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7549 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7552 ICALL_EXPORT MonoTypedRef
7553 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7555 guint32 i, arg_size;
7559 i = iter->sig->sentinelpos + iter->next_arg;
7561 g_assert (i < iter->sig->param_count);
7563 res.type = iter->sig->params [i];
7564 res.klass = mono_class_from_mono_type (res.type);
7565 arg_size = mono_type_stack_size (res.type, &align);
7566 #if defined(__arm__) || defined(__mips__)
7567 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7569 res.value = iter->args;
7570 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7571 /* Values are stored as 8 byte register sized objects, but 'value'
7572 * is dereferenced as a pointer in other routines.
7574 res.value = (char*)res.value + 4;
7576 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7577 if (arg_size <= sizeof (gpointer)) {
7579 int padding = arg_size - mono_type_size (res.type, &dummy);
7580 res.value = (guint8*)res.value + padding;
7583 iter->args = (char*)iter->args + arg_size;
7586 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7591 ICALL_EXPORT MonoTypedRef
7592 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7594 guint32 i, arg_size;
7598 i = iter->sig->sentinelpos + iter->next_arg;
7600 g_assert (i < iter->sig->param_count);
7602 while (i < iter->sig->param_count) {
7603 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7605 res.type = iter->sig->params [i];
7606 res.klass = mono_class_from_mono_type (res.type);
7607 /* FIXME: endianess issue... */
7608 arg_size = mono_type_stack_size (res.type, &align);
7609 #if defined(__arm__) || defined(__mips__)
7610 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7612 res.value = iter->args;
7613 iter->args = (char*)iter->args + arg_size;
7615 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7618 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7626 ICALL_EXPORT MonoType*
7627 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7631 i = iter->sig->sentinelpos + iter->next_arg;
7633 g_assert (i < iter->sig->param_count);
7635 return iter->sig->params [i];
7638 ICALL_EXPORT MonoObject*
7639 mono_TypedReference_ToObject (MonoTypedRef* tref)
7642 MonoObject *result = NULL;
7643 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7644 MonoObject** objp = (MonoObject **)tref->value;
7648 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7649 mono_error_set_pending_exception (&error);
7653 ICALL_EXPORT MonoTypedRef
7654 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7657 MonoReflectionField *f;
7659 MonoType *ftype = NULL;
7663 memset (&res, 0, sizeof (res));
7666 g_assert (mono_array_length (fields) > 0);
7668 klass = target->vtable->klass;
7670 for (i = 0; i < mono_array_length (fields); ++i) {
7671 f = mono_array_get (fields, MonoReflectionField*, i);
7673 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7676 if (f->field->parent != klass) {
7677 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7681 p = (guint8*)target + f->field->offset;
7683 p += f->field->offset - sizeof (MonoObject);
7684 klass = mono_class_from_mono_type (f->field->type);
7685 ftype = f->field->type;
7689 res.klass = mono_class_from_mono_type (ftype);
7696 prelink_method (MonoMethod *method, MonoError *error)
7698 const char *exc_class, *exc_arg;
7700 mono_error_init (error);
7701 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7703 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7705 mono_error_set_exception_instance (error,
7706 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7709 /* create the wrapper, too? */
7713 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7717 prelink_method (method->method, &error);
7718 mono_error_raise_exception (&error);
7722 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7725 MonoClass *klass = mono_class_from_mono_type (type->type);
7727 gpointer iter = NULL;
7729 mono_class_init_checked (klass, &error);
7730 mono_error_raise_exception (&error);
7732 while ((m = mono_class_get_methods (klass, &iter))) {
7733 prelink_method (m, &error);
7734 mono_error_raise_exception (&error);
7738 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7740 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7741 gint32 const **exponents,
7742 gunichar2 const **digitLowerTable,
7743 gunichar2 const **digitUpperTable,
7744 gint64 const **tenPowersList,
7745 gint32 const **decHexDigits)
7747 *mantissas = Formatter_MantissaBitsTable;
7748 *exponents = Formatter_TensExponentTable;
7749 *digitLowerTable = Formatter_DigitLowerTable;
7750 *digitUpperTable = Formatter_DigitUpperTable;
7751 *tenPowersList = Formatter_TenPowersList;
7752 *decHexDigits = Formatter_DecHexDigits;
7756 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7757 * and avoid useless allocations.
7760 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7762 MonoReflectionType *rt;
7766 mono_error_init (error);
7767 for (i = 0; i < type->num_mods; ++i) {
7768 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7773 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7775 for (i = 0; i < type->num_mods; ++i) {
7776 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7777 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7778 return_val_if_nok (error, NULL);
7780 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7781 return_val_if_nok (error, NULL);
7783 mono_array_setref (res, count, rt);
7790 ICALL_EXPORT MonoArray*
7791 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7794 MonoType *type = param->ClassImpl->type;
7795 MonoClass *member_class = mono_object_class (param->MemberImpl);
7796 MonoMethod *method = NULL;
7799 MonoMethodSignature *sig;
7802 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7803 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7804 method = rmethod->method;
7805 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7806 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7807 if (!(method = prop->property->get))
7808 method = prop->property->set;
7811 char *type_name = mono_type_get_full_name (member_class);
7812 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7813 MonoException *ex = mono_get_exception_not_supported (msg);
7816 mono_set_pending_exception (ex);
7820 image = method->klass->image;
7821 pos = param->PositionImpl;
7822 sig = mono_method_signature (method);
7826 type = sig->params [pos];
7828 res = type_array_from_modifiers (image, type, optional, &error);
7829 mono_error_raise_exception (&error);
7834 get_property_type (MonoProperty *prop)
7836 MonoMethodSignature *sig;
7838 sig = mono_method_signature (prop->get);
7840 } else if (prop->set) {
7841 sig = mono_method_signature (prop->set);
7842 return sig->params [sig->param_count - 1];
7847 ICALL_EXPORT MonoArray*
7848 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7851 MonoType *type = get_property_type (property->property);
7852 MonoImage *image = property->klass->image;
7857 res = type_array_from_modifiers (image, type, optional, &error);
7858 mono_error_raise_exception (&error);
7863 *Construct a MonoType suited to be used to decode a constant blob object.
7865 * @type is the target type which will be constructed
7866 * @blob_type is the blob type, for example, that comes from the constant table
7867 * @real_type is the expected constructed type.
7870 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7872 type->type = blob_type;
7873 type->data.klass = NULL;
7874 if (blob_type == MONO_TYPE_CLASS)
7875 type->data.klass = mono_defaults.object_class;
7876 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7877 /* For enums, we need to use the base type */
7878 type->type = MONO_TYPE_VALUETYPE;
7879 type->data.klass = mono_class_from_mono_type (real_type);
7881 type->data.klass = mono_class_from_mono_type (real_type);
7884 ICALL_EXPORT MonoObject*
7885 property_info_get_default_value (MonoReflectionProperty *property)
7889 MonoProperty *prop = property->property;
7890 MonoType *type = get_property_type (prop);
7891 MonoDomain *domain = mono_object_domain (property);
7892 MonoTypeEnum def_type;
7893 const char *def_value;
7896 mono_class_init (prop->parent);
7898 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7899 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7903 def_value = mono_class_get_property_default_value (prop, &def_type);
7905 mono_type_from_blob_type (&blob_type, def_type, type);
7906 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7908 mono_error_set_pending_exception (&error);
7912 ICALL_EXPORT MonoBoolean
7913 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7916 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7917 MonoCustomAttrInfo *cinfo;
7920 mono_class_init_checked (attr_class, &error);
7921 mono_error_raise_exception (&error);
7923 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7924 if (!is_ok (&error)) {
7925 mono_error_set_pending_exception (&error);
7930 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7932 mono_custom_attrs_free (cinfo);
7936 ICALL_EXPORT MonoArray*
7937 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7939 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7944 mono_class_init_checked (attr_class, &error);
7945 mono_error_raise_exception (&error);
7948 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7949 if (!mono_error_ok (&error)) {
7950 mono_error_set_pending_exception (&error);
7954 if (mono_loader_get_last_error ()) {
7955 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7962 ICALL_EXPORT MonoArray*
7963 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7967 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7968 mono_error_set_pending_exception (&error);
7973 ICALL_EXPORT MonoString*
7974 ves_icall_Mono_Runtime_GetDisplayName (void)
7977 MonoString *display_name;
7979 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7980 display_name = mono_string_new (mono_domain_get (), info);
7982 return display_name;
7985 ICALL_EXPORT MonoString*
7986 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7989 MonoString *message;
7993 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7994 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7997 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7999 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8000 mono_error_raise_exception (&error);
8007 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
8010 char *path_str = mono_string_to_utf8 (path);
8012 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
8020 ICALL_EXPORT gpointer
8021 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8023 return GetCurrentProcess ();
8026 ICALL_EXPORT MonoBoolean
8027 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8029 return GetExitCodeProcess (handle, (guint32*) exitcode);
8032 ICALL_EXPORT MonoBoolean
8033 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8035 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8036 return CloseHandle (handle);
8038 return CloseProcess (handle);
8042 ICALL_EXPORT MonoBoolean
8043 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8045 return TerminateProcess (handle, exitcode);
8049 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8051 return WaitForInputIdle (handle, milliseconds);
8054 ICALL_EXPORT MonoBoolean
8055 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8057 return GetProcessWorkingSetSize (handle, min, max);
8060 ICALL_EXPORT MonoBoolean
8061 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8063 return SetProcessWorkingSetSize (handle, min, max);
8066 ICALL_EXPORT MonoBoolean
8067 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8069 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8073 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8075 return mono_process_current_pid ();
8079 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8081 return GetPriorityClass (handle);
8084 ICALL_EXPORT MonoBoolean
8085 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8087 return SetPriorityClass (handle, priorityClass);
8090 #ifndef DISABLE_ICALL_TABLES
8092 #define ICALL_TYPE(id,name,first)
8093 #define ICALL(id,name,func) Icall_ ## id,
8096 #include "metadata/icall-def.h"
8102 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8103 #define ICALL(id,name,func)
8105 #include "metadata/icall-def.h"
8111 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8112 #define ICALL(id,name,func)
8114 guint16 first_icall;
8117 static const IcallTypeDesc
8118 icall_type_descs [] = {
8119 #include "metadata/icall-def.h"
8123 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8126 #define ICALL_TYPE(id,name,first)
8129 #ifdef HAVE_ARRAY_ELEM_INIT
8130 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8131 #define MSGSTRFIELD1(line) str##line
8133 static const struct msgstrtn_t {
8134 #define ICALL(id,name,func)
8136 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8137 #include "metadata/icall-def.h"
8139 } icall_type_names_str = {
8140 #define ICALL_TYPE(id,name,first) (name),
8141 #include "metadata/icall-def.h"
8144 static const guint16 icall_type_names_idx [] = {
8145 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8146 #include "metadata/icall-def.h"
8149 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8151 static const struct msgstr_t {
8153 #define ICALL_TYPE(id,name,first)
8154 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8155 #include "metadata/icall-def.h"
8157 } icall_names_str = {
8158 #define ICALL(id,name,func) (name),
8159 #include "metadata/icall-def.h"
8162 static const guint16 icall_names_idx [] = {
8163 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8164 #include "metadata/icall-def.h"
8167 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8173 #define ICALL_TYPE(id,name,first) name,
8174 #define ICALL(id,name,func)
8175 static const char* const
8176 icall_type_names [] = {
8177 #include "metadata/icall-def.h"
8181 #define icall_type_name_get(id) (icall_type_names [(id)])
8185 #define ICALL_TYPE(id,name,first)
8186 #define ICALL(id,name,func) name,
8187 static const char* const
8189 #include "metadata/icall-def.h"
8192 #define icall_name_get(id) icall_names [(id)]
8194 #endif /* !HAVE_ARRAY_ELEM_INIT */
8198 #define ICALL_TYPE(id,name,first)
8199 #define ICALL(id,name,func) func,
8200 static const gconstpointer
8201 icall_functions [] = {
8202 #include "metadata/icall-def.h"
8206 #ifdef ENABLE_ICALL_SYMBOL_MAP
8209 #define ICALL_TYPE(id,name,first)
8210 #define ICALL(id,name,func) #func,
8211 static const gconstpointer
8212 icall_symbols [] = {
8213 #include "metadata/icall-def.h"
8218 #endif /* DISABLE_ICALL_TABLES */
8220 static mono_mutex_t icall_mutex;
8221 static GHashTable *icall_hash = NULL;
8222 static GHashTable *jit_icall_hash_name = NULL;
8223 static GHashTable *jit_icall_hash_addr = NULL;
8226 mono_icall_init (void)
8228 #ifndef DISABLE_ICALL_TABLES
8231 /* check that tables are sorted: disable in release */
8234 const char *prev_class = NULL;
8235 const char *prev_method;
8237 for (i = 0; i < Icall_type_num; ++i) {
8238 const IcallTypeDesc *desc;
8241 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8242 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8243 prev_class = icall_type_name_get (i);
8244 desc = &icall_type_descs [i];
8245 num_icalls = icall_desc_num_icalls (desc);
8246 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8247 for (j = 0; j < num_icalls; ++j) {
8248 const char *methodn = icall_name_get (desc->first_icall + j);
8249 if (prev_method && strcmp (prev_method, methodn) >= 0)
8250 g_print ("method %s should come before method %s\n", methodn, prev_method);
8251 prev_method = methodn;
8257 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8258 mono_os_mutex_init (&icall_mutex);
8262 mono_icall_lock (void)
8264 mono_locks_os_acquire (&icall_mutex, IcallLock);
8268 mono_icall_unlock (void)
8270 mono_locks_os_release (&icall_mutex, IcallLock);
8274 mono_icall_cleanup (void)
8276 g_hash_table_destroy (icall_hash);
8277 g_hash_table_destroy (jit_icall_hash_name);
8278 g_hash_table_destroy (jit_icall_hash_addr);
8279 mono_os_mutex_destroy (&icall_mutex);
8283 * mono_add_internal_call:
8284 * @name: method specification to surface to the managed world
8285 * @method: pointer to a C method to invoke when the method is called
8287 * This method surfaces the C function pointed by @method as a method
8288 * that has been surfaced in managed code with the method specified in
8289 * @name as an internal call.
8291 * Internal calls are surfaced to all app domains loaded and they are
8292 * accessibly by a type with the specified name.
8294 * You must provide a fully qualified type name, that is namespaces
8295 * and type name, followed by a colon and the method name, with an
8296 * optional signature to bind.
8298 * For example, the following are all valid declarations:
8300 * "MyApp.Services.ScriptService:Accelerate"
8301 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8303 * You use method parameters in cases where there might be more than
8304 * one surface method to managed code. That way you can register different
8305 * internal calls for different method overloads.
8307 * The internal calls are invoked with no marshalling. This means that .NET
8308 * types like System.String are exposed as `MonoString *` parameters. This is
8309 * different than the way that strings are surfaced in P/Invoke.
8311 * For more information on how the parameters are marshalled, see the
8312 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8315 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8316 * reference for more information on the format of method descriptions.
8319 mono_add_internal_call (const char *name, gconstpointer method)
8323 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8325 mono_icall_unlock ();
8328 #ifndef DISABLE_ICALL_TABLES
8330 #ifdef HAVE_ARRAY_ELEM_INIT
8332 compare_method_imap (const void *key, const void *elem)
8334 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8335 return strcmp (key, method_name);
8339 find_method_icall (const IcallTypeDesc *imap, const char *name)
8341 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);
8344 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8348 compare_class_imap (const void *key, const void *elem)
8350 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8351 return strcmp (key, class_name);
8354 static const IcallTypeDesc*
8355 find_class_icalls (const char *name)
8357 const guint16 *nameslot = (const guint16 *)mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
8360 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8363 #else /* HAVE_ARRAY_ELEM_INIT */
8366 compare_method_imap (const void *key, const void *elem)
8368 const char** method_name = (const char**)elem;
8369 return strcmp (key, *method_name);
8373 find_method_icall (const IcallTypeDesc *imap, const char *name)
8375 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8378 return (gpointer)icall_functions [(nameslot - icall_names)];
8382 compare_class_imap (const void *key, const void *elem)
8384 const char** class_name = (const char**)elem;
8385 return strcmp (key, *class_name);
8388 static const IcallTypeDesc*
8389 find_class_icalls (const char *name)
8391 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8394 return &icall_type_descs [nameslot - icall_type_names];
8397 #endif /* HAVE_ARRAY_ELEM_INIT */
8399 #endif /* DISABLE_ICALL_TABLES */
8402 * we should probably export this as an helper (handle nested types).
8403 * Returns the number of chars written in buf.
8406 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8408 int nspacelen, cnamelen;
8409 nspacelen = strlen (klass->name_space);
8410 cnamelen = strlen (klass->name);
8411 if (nspacelen + cnamelen + 2 > bufsize)
8414 memcpy (buf, klass->name_space, nspacelen);
8415 buf [nspacelen ++] = '.';
8417 memcpy (buf + nspacelen, klass->name, cnamelen);
8418 buf [nspacelen + cnamelen] = 0;
8419 return nspacelen + cnamelen;
8422 #ifdef DISABLE_ICALL_TABLES
8424 no_icall_table (void)
8426 g_assert_not_reached ();
8431 mono_lookup_internal_call (MonoMethod *method)
8436 int typelen = 0, mlen, siglen;
8438 #ifndef DISABLE_ICALL_TABLES
8439 const IcallTypeDesc *imap = NULL;
8442 g_assert (method != NULL);
8444 if (method->is_inflated)
8445 method = ((MonoMethodInflated *) method)->declaring;
8447 if (method->klass->nested_in) {
8448 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8452 mname [pos++] = '/';
8455 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8461 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8466 #ifndef DISABLE_ICALL_TABLES
8467 imap = find_class_icalls (mname);
8470 mname [typelen] = ':';
8471 mname [typelen + 1] = ':';
8473 mlen = strlen (method->name);
8474 memcpy (mname + typelen + 2, method->name, mlen);
8475 sigstart = mname + typelen + 2 + mlen;
8478 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8479 siglen = strlen (tmpsig);
8480 if (typelen + mlen + siglen + 6 > sizeof (mname))
8483 memcpy (sigstart + 1, tmpsig, siglen);
8484 sigstart [siglen + 1] = ')';
8485 sigstart [siglen + 2] = 0;
8490 res = g_hash_table_lookup (icall_hash, mname);
8492 mono_icall_unlock ();;
8495 /* try without signature */
8497 res = g_hash_table_lookup (icall_hash, mname);
8499 mono_icall_unlock ();
8503 #ifdef DISABLE_ICALL_TABLES
8504 mono_icall_unlock ();
8505 /* Fail only when the result is actually used */
8506 /* mono_marshal_get_native_wrapper () depends on this */
8507 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8508 return ves_icall_System_String_ctor_RedirectToCreateString;
8510 return no_icall_table;
8512 /* it wasn't found in the static call tables */
8514 mono_icall_unlock ();
8517 res = find_method_icall (imap, sigstart - mlen);
8519 mono_icall_unlock ();
8522 /* try _with_ signature */
8524 res = find_method_icall (imap, sigstart - mlen);
8526 mono_icall_unlock ();
8530 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8531 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8532 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8533 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8534 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");
8535 g_print ("If you see other errors or faults after this message they are probably related\n");
8536 g_print ("and you need to fix your mono install first.\n");
8538 mono_icall_unlock ();
8544 #ifdef ENABLE_ICALL_SYMBOL_MAP
8546 func_cmp (gconstpointer key, gconstpointer p)
8548 return (gsize)key - (gsize)*(gsize*)p;
8553 * mono_lookup_icall_symbol:
8555 * Given the icall METHOD, returns its C symbol.
8558 mono_lookup_icall_symbol (MonoMethod *m)
8560 #ifdef DISABLE_ICALL_TABLES
8561 g_assert_not_reached ();
8564 #ifdef ENABLE_ICALL_SYMBOL_MAP
8568 static gconstpointer *functions_sorted;
8569 static const char**symbols_sorted;
8570 static gboolean inited;
8575 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8576 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8577 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8578 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8579 /* Bubble sort the two arrays */
8583 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8584 if (functions_sorted [i] > functions_sorted [i + 1]) {
8587 tmp = functions_sorted [i];
8588 functions_sorted [i] = functions_sorted [i + 1];
8589 functions_sorted [i + 1] = tmp;
8590 tmp = symbols_sorted [i];
8591 symbols_sorted [i] = symbols_sorted [i + 1];
8592 symbols_sorted [i + 1] = tmp;
8599 func = mono_lookup_internal_call (m);
8602 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8606 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8608 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8609 g_assert_not_reached ();
8616 type_from_typename (char *type_name)
8618 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8620 if (!strcmp (type_name, "int"))
8621 klass = mono_defaults.int_class;
8622 else if (!strcmp (type_name, "ptr"))
8623 klass = mono_defaults.int_class;
8624 else if (!strcmp (type_name, "void"))
8625 klass = mono_defaults.void_class;
8626 else if (!strcmp (type_name, "int32"))
8627 klass = mono_defaults.int32_class;
8628 else if (!strcmp (type_name, "uint32"))
8629 klass = mono_defaults.uint32_class;
8630 else if (!strcmp (type_name, "int8"))
8631 klass = mono_defaults.sbyte_class;
8632 else if (!strcmp (type_name, "uint8"))
8633 klass = mono_defaults.byte_class;
8634 else if (!strcmp (type_name, "int16"))
8635 klass = mono_defaults.int16_class;
8636 else if (!strcmp (type_name, "uint16"))
8637 klass = mono_defaults.uint16_class;
8638 else if (!strcmp (type_name, "long"))
8639 klass = mono_defaults.int64_class;
8640 else if (!strcmp (type_name, "ulong"))
8641 klass = mono_defaults.uint64_class;
8642 else if (!strcmp (type_name, "float"))
8643 klass = mono_defaults.single_class;
8644 else if (!strcmp (type_name, "double"))
8645 klass = mono_defaults.double_class;
8646 else if (!strcmp (type_name, "object"))
8647 klass = mono_defaults.object_class;
8648 else if (!strcmp (type_name, "obj"))
8649 klass = mono_defaults.object_class;
8650 else if (!strcmp (type_name, "string"))
8651 klass = mono_defaults.string_class;
8652 else if (!strcmp (type_name, "bool"))
8653 klass = mono_defaults.boolean_class;
8654 else if (!strcmp (type_name, "boolean"))
8655 klass = mono_defaults.boolean_class;
8657 g_error ("%s", type_name);
8658 g_assert_not_reached ();
8660 return &klass->byval_arg;
8664 * LOCKING: Take the corlib image lock.
8666 MonoMethodSignature*
8667 mono_create_icall_signature (const char *sigstr)
8672 MonoMethodSignature *res, *res2;
8673 MonoImage *corlib = mono_defaults.corlib;
8675 mono_image_lock (corlib);
8676 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8677 mono_image_unlock (corlib);
8682 parts = g_strsplit (sigstr, " ", 256);
8691 res = mono_metadata_signature_alloc (corlib, len - 1);
8696 * Under windows, the default pinvoke calling convention is STDCALL but
8699 res->call_convention = MONO_CALL_C;
8702 res->ret = type_from_typename (parts [0]);
8703 for (i = 1; i < len; ++i) {
8704 res->params [i - 1] = type_from_typename (parts [i]);
8709 mono_image_lock (corlib);
8710 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8712 res = res2; /*Value is allocated in the image pool*/
8714 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8715 mono_image_unlock (corlib);
8721 mono_find_jit_icall_by_name (const char *name)
8723 MonoJitICallInfo *info;
8724 g_assert (jit_icall_hash_name);
8727 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8728 mono_icall_unlock ();
8733 mono_find_jit_icall_by_addr (gconstpointer addr)
8735 MonoJitICallInfo *info;
8736 g_assert (jit_icall_hash_addr);
8739 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8740 mono_icall_unlock ();
8746 * mono_get_jit_icall_info:
8748 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8749 * caller should access it while holding the icall lock.
8752 mono_get_jit_icall_info (void)
8754 return jit_icall_hash_name;
8758 * mono_lookup_jit_icall_symbol:
8760 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8763 mono_lookup_jit_icall_symbol (const char *name)
8765 MonoJitICallInfo *info;
8766 const char *res = NULL;
8769 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8771 res = info->c_symbol;
8772 mono_icall_unlock ();
8777 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8780 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8781 mono_icall_unlock ();
8785 * 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
8786 * icalls without wrappers in some cases.
8789 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8791 MonoJitICallInfo *info;
8798 if (!jit_icall_hash_name) {
8799 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8800 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8803 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8804 g_warning ("jit icall already defined \"%s\"\n", name);
8805 g_assert_not_reached ();
8808 info = g_new0 (MonoJitICallInfo, 1);
8813 info->c_symbol = c_symbol;
8814 info->no_raise = no_raise;
8817 info->wrapper = func;
8819 info->wrapper = NULL;
8822 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8823 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8825 mono_icall_unlock ();
8830 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8832 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);