5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
9 * Aleksey Kliger (aleksey@xamarin.com)
11 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
12 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
14 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
25 #ifdef HAVE_SYS_TIME_H
31 #if defined (HOST_WIN32)
34 #if defined (HAVE_WCHAR_H)
38 #include "mono/utils/mono-membar.h"
39 #include <mono/metadata/object.h>
40 #include <mono/metadata/threads.h>
41 #include <mono/metadata/threads-types.h>
42 #include <mono/metadata/threadpool-ms.h>
43 #include <mono/metadata/threadpool-ms-io.h>
44 #include <mono/metadata/monitor.h>
45 #include <mono/metadata/reflection.h>
46 #include <mono/metadata/assembly.h>
47 #include <mono/metadata/tabledefs.h>
48 #include <mono/metadata/exception.h>
49 #include <mono/metadata/exception-internals.h>
50 #include <mono/metadata/file-io.h>
51 #include <mono/metadata/console-io.h>
52 #include <mono/metadata/mono-route.h>
53 #include <mono/metadata/socket-io.h>
54 #include <mono/metadata/mono-endian.h>
55 #include <mono/metadata/tokentype.h>
56 #include <mono/metadata/domain-internals.h>
57 #include <mono/metadata/metadata-internals.h>
58 #include <mono/metadata/class-internals.h>
59 #include <mono/metadata/reflection-internals.h>
60 #include <mono/metadata/marshal.h>
61 #include <mono/metadata/gc-internals.h>
62 #include <mono/metadata/mono-gc.h>
63 #include <mono/metadata/rand.h>
64 #include <mono/metadata/sysmath.h>
65 #include <mono/metadata/string-icalls.h>
66 #include <mono/metadata/debug-helpers.h>
67 #include <mono/metadata/process.h>
68 #include <mono/metadata/environment.h>
69 #include <mono/metadata/profiler-private.h>
70 #include <mono/metadata/locales.h>
71 #include <mono/metadata/filewatcher.h>
72 #include <mono/metadata/security.h>
73 #include <mono/metadata/mono-config.h>
74 #include <mono/metadata/cil-coff.h>
75 #include <mono/metadata/number-formatter.h>
76 #include <mono/metadata/security-manager.h>
77 #include <mono/metadata/security-core-clr.h>
78 #include <mono/metadata/mono-perfcounters.h>
79 #include <mono/metadata/mono-debug.h>
80 #include <mono/metadata/mono-ptr-array.h>
81 #include <mono/metadata/verify-internals.h>
82 #include <mono/metadata/runtime.h>
83 #include <mono/metadata/file-mmap.h>
84 #include <mono/metadata/seq-points-data.h>
85 #include <mono/metadata/handle.h>
86 #include <mono/metadata/w32mutex.h>
87 #include <mono/metadata/w32semaphore.h>
88 #include <mono/metadata/w32event.h>
89 #include <mono/io-layer/io-layer.h>
90 #include <mono/utils/monobitset.h>
91 #include <mono/utils/mono-time.h>
92 #include <mono/utils/mono-proclib.h>
93 #include <mono/utils/mono-string.h>
94 #include <mono/utils/mono-error-internals.h>
95 #include <mono/utils/mono-mmap.h>
96 #include <mono/utils/mono-io-portability.h>
97 #include <mono/utils/mono-digest.h>
98 #include <mono/utils/bsearch.h>
99 #include <mono/utils/mono-os-mutex.h>
100 #include <mono/utils/mono-threads.h>
102 #if defined (HOST_WIN32)
106 #include "decimal-ms.h"
107 #include "number-ms.h"
109 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
110 #include <sys/utsname.h>
113 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
115 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
117 /* Lazy class loading functions */
118 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
119 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
120 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
121 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
122 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
123 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
126 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
128 static inline MonoBoolean
129 is_generic_parameter (MonoType *type)
131 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
135 mono_class_init_checked (MonoClass *klass, MonoError *error)
137 mono_error_init (error);
139 if (!mono_class_init (klass))
140 mono_error_set_for_class_failure (error, klass);
143 ICALL_EXPORT MonoObject *
144 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
150 MonoObject *result = NULL;
152 ac = (MonoClass *)arr->obj.vtable->klass;
154 esize = mono_array_element_size (ac);
155 ea = (gpointer*)((char*)arr->vector + (pos * esize));
157 if (ac->element_class->valuetype) {
158 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
159 mono_error_set_pending_exception (&error);
161 result = (MonoObject *)*ea;
165 ICALL_EXPORT MonoObject *
166 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
172 MONO_CHECK_ARG_NULL (idxs, NULL);
175 ic = (MonoClass *)io->obj.vtable->klass;
177 ac = (MonoClass *)arr->obj.vtable->klass;
179 g_assert (ic->rank == 1);
180 if (io->bounds != NULL || io->max_length != ac->rank) {
181 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
185 ind = (gint32 *)io->vector;
187 if (arr->bounds == NULL) {
188 if (*ind < 0 || *ind >= arr->max_length) {
189 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
193 return ves_icall_System_Array_GetValueImpl (arr, *ind);
196 for (i = 0; i < ac->rank; i++) {
197 if ((ind [i] < arr->bounds [i].lower_bound) ||
198 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
199 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
204 pos = ind [0] - arr->bounds [0].lower_bound;
205 for (i = 1; i < ac->rank; i++)
206 pos = pos * arr->bounds [i].length + ind [i] -
207 arr->bounds [i].lower_bound;
209 return ves_icall_System_Array_GetValueImpl (arr, pos);
213 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
216 MonoClass *ac, *vc, *ec;
225 mono_error_init (&error);
228 vc = value->vtable->klass;
232 ac = arr->obj.vtable->klass;
233 ec = ac->element_class;
235 esize = mono_array_element_size (ac);
236 ea = (gpointer*)((char*)arr->vector + (pos * esize));
237 va = (gpointer*)((char*)value + sizeof (MonoObject));
239 if (mono_class_is_nullable (ec)) {
240 mono_nullable_init ((guint8*)ea, value, ec);
245 mono_gc_bzero_atomic (ea, esize);
249 #define NO_WIDENING_CONVERSION G_STMT_START{\
250 mono_set_pending_exception (mono_get_exception_argument ( \
251 "value", "not a widening conversion")); \
255 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
256 if (esize < vsize + (extra)) { \
257 mono_set_pending_exception (mono_get_exception_argument ( \
258 "value", "not a widening conversion")); \
263 #define INVALID_CAST G_STMT_START{ \
264 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
265 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
269 /* Check element (destination) type. */
270 switch (ec->byval_arg.type) {
271 case MONO_TYPE_STRING:
272 switch (vc->byval_arg.type) {
273 case MONO_TYPE_STRING:
279 case MONO_TYPE_BOOLEAN:
280 switch (vc->byval_arg.type) {
281 case MONO_TYPE_BOOLEAN:
294 NO_WIDENING_CONVERSION;
303 if (!ec->valuetype) {
304 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
305 if (mono_error_set_pending_exception (&error))
309 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
313 if (mono_object_isinst_checked (value, ec, &error)) {
314 if (ec->has_references)
315 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
317 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
320 if (mono_error_set_pending_exception (&error))
326 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
328 et = ec->byval_arg.type;
329 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
330 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
332 vt = vc->byval_arg.type;
333 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
334 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
336 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
342 case MONO_TYPE_CHAR: \
343 CHECK_WIDENING_CONVERSION(0); \
344 *(etype *) ea = (etype) u64; \
346 /* You can't assign a signed value to an unsigned array. */ \
351 /* You can't assign a floating point number to an integer array. */ \
354 NO_WIDENING_CONVERSION; \
358 #define ASSIGN_SIGNED(etype) G_STMT_START{\
364 CHECK_WIDENING_CONVERSION(0); \
365 *(etype *) ea = (etype) i64; \
367 /* You can assign an unsigned value to a signed array if the array's */ \
368 /* element size is larger than the value size. */ \
373 case MONO_TYPE_CHAR: \
374 CHECK_WIDENING_CONVERSION(1); \
375 *(etype *) ea = (etype) u64; \
377 /* You can't assign a floating point number to an integer array. */ \
380 NO_WIDENING_CONVERSION; \
384 #define ASSIGN_REAL(etype) G_STMT_START{\
388 CHECK_WIDENING_CONVERSION(0); \
389 *(etype *) ea = (etype) r64; \
391 /* All integer values fit into a floating point array, so we don't */ \
392 /* need to CHECK_WIDENING_CONVERSION here. */ \
397 *(etype *) ea = (etype) i64; \
403 case MONO_TYPE_CHAR: \
404 *(etype *) ea = (etype) u64; \
411 u64 = *(guint8 *) va;
414 u64 = *(guint16 *) va;
417 u64 = *(guint32 *) va;
420 u64 = *(guint64 *) va;
426 i64 = *(gint16 *) va;
429 i64 = *(gint32 *) va;
432 i64 = *(gint64 *) va;
435 r64 = *(gfloat *) va;
438 r64 = *(gdouble *) va;
441 u64 = *(guint16 *) va;
443 case MONO_TYPE_BOOLEAN:
444 /* Boolean is only compatible with itself. */
457 NO_WIDENING_CONVERSION;
464 /* If we can't do a direct copy, let's try a widening conversion. */
467 ASSIGN_UNSIGNED (guint16);
469 ASSIGN_UNSIGNED (guint8);
471 ASSIGN_UNSIGNED (guint16);
473 ASSIGN_UNSIGNED (guint32);
475 ASSIGN_UNSIGNED (guint64);
477 ASSIGN_SIGNED (gint8);
479 ASSIGN_SIGNED (gint16);
481 ASSIGN_SIGNED (gint32);
483 ASSIGN_SIGNED (gint64);
485 ASSIGN_REAL (gfloat);
487 ASSIGN_REAL (gdouble);
491 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
495 #undef NO_WIDENING_CONVERSION
496 #undef CHECK_WIDENING_CONVERSION
497 #undef ASSIGN_UNSIGNED
503 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
509 MONO_CHECK_ARG_NULL (idxs,);
511 ic = idxs->obj.vtable->klass;
512 ac = arr->obj.vtable->klass;
514 g_assert (ic->rank == 1);
515 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
516 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
520 ind = (gint32 *)idxs->vector;
522 if (arr->bounds == NULL) {
523 if (*ind < 0 || *ind >= arr->max_length) {
524 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
528 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
532 for (i = 0; i < ac->rank; i++)
533 if ((ind [i] < arr->bounds [i].lower_bound) ||
534 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
535 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
539 pos = ind [0] - arr->bounds [0].lower_bound;
540 for (i = 1; i < ac->rank; i++)
541 pos = pos * arr->bounds [i].length + ind [i] -
542 arr->bounds [i].lower_bound;
544 ves_icall_System_Array_SetValueImpl (arr, value, pos);
547 ICALL_EXPORT MonoArray *
548 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
551 MonoClass *aklass, *klass;
554 gboolean bounded = FALSE;
556 MONO_CHECK_ARG_NULL (type, NULL);
557 MONO_CHECK_ARG_NULL (lengths, NULL);
559 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
561 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
563 for (i = 0; i < mono_array_length (lengths); i++) {
564 if (mono_array_get (lengths, gint32, i) < 0) {
565 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
570 klass = mono_class_from_mono_type (type->type);
571 mono_class_init_checked (klass, &error);
572 if (mono_error_set_pending_exception (&error))
575 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
576 /* vectors are not the same as one dimensional arrays with no-zero bounds */
581 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
583 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
584 for (i = 0; i < aklass->rank; ++i) {
585 sizes [i] = mono_array_get (lengths, guint32, i);
587 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
589 sizes [i + aklass->rank] = 0;
592 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
593 mono_error_set_pending_exception (&error);
598 ICALL_EXPORT MonoArray *
599 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
602 MonoClass *aklass, *klass;
605 gboolean bounded = FALSE;
607 MONO_CHECK_ARG_NULL (type, NULL);
608 MONO_CHECK_ARG_NULL (lengths, NULL);
610 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
612 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
614 for (i = 0; i < mono_array_length (lengths); i++) {
615 if ((mono_array_get (lengths, gint64, i) < 0) ||
616 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
617 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
622 klass = mono_class_from_mono_type (type->type);
623 mono_class_init_checked (klass, &error);
624 if (mono_error_set_pending_exception (&error))
627 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
628 /* vectors are not the same as one dimensional arrays with no-zero bounds */
633 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
635 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
636 for (i = 0; i < aklass->rank; ++i) {
637 sizes [i] = mono_array_get (lengths, guint64, i);
639 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
641 sizes [i + aklass->rank] = 0;
644 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
645 mono_error_set_pending_exception (&error);
651 ves_icall_System_Array_GetRank (MonoObject *arr)
653 return arr->vtable->klass->rank;
657 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
659 gint32 rank = arr->obj.vtable->klass->rank;
662 if ((dimension < 0) || (dimension >= rank)) {
663 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
667 if (arr->bounds == NULL)
668 length = arr->max_length;
670 length = arr->bounds [dimension].length;
672 #ifdef MONO_BIG_ARRAYS
673 if (length > G_MAXINT32) {
674 mono_set_pending_exception (mono_get_exception_overflow ());
682 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
684 gint32 rank = arr->obj.vtable->klass->rank;
686 if ((dimension < 0) || (dimension >= rank)) {
687 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
691 if (arr->bounds == NULL)
692 return arr->max_length;
694 return arr->bounds [dimension].length;
698 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
700 gint32 rank = arr->obj.vtable->klass->rank;
702 if ((dimension < 0) || (dimension >= rank)) {
703 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
707 if (arr->bounds == NULL)
710 return arr->bounds [dimension].lower_bound;
714 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
716 int sz = mono_array_element_size (mono_object_class (arr));
717 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
720 ICALL_EXPORT MonoArray*
721 ves_icall_System_Array_Clone (MonoArray *arr)
724 MonoArray *result = mono_array_clone_checked (arr, &error);
725 mono_error_set_pending_exception (&error);
729 ICALL_EXPORT gboolean
730 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
735 MonoVTable *src_vtable;
736 MonoVTable *dest_vtable;
737 MonoClass *src_class;
738 MonoClass *dest_class;
740 src_vtable = source->obj.vtable;
741 dest_vtable = dest->obj.vtable;
743 if (src_vtable->rank != dest_vtable->rank)
746 if (source->bounds || dest->bounds)
749 /* there's no integer overflow since mono_array_length returns an unsigned integer */
750 if ((dest_idx + length > mono_array_length_fast (dest)) ||
751 (source_idx + length > mono_array_length_fast (source)))
754 src_class = src_vtable->klass->element_class;
755 dest_class = dest_vtable->klass->element_class;
758 * Handle common cases.
761 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
762 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
764 if (src_class == mono_defaults.object_class && dest_class->valuetype)
767 /* Check if we're copying a char[] <==> (u)short[] */
768 if (src_class != dest_class) {
769 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
772 /* 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. */
773 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
777 if (dest_class->valuetype) {
778 element_size = mono_array_element_size (source->obj.vtable->klass);
779 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
780 if (dest_class->has_references) {
781 mono_value_copy_array (dest, dest_idx, source_addr, length);
783 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
784 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
787 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
794 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
800 ac = (MonoClass *)arr->obj.vtable->klass;
802 esize = mono_array_element_size (ac);
803 ea = (gpointer*)((char*)arr->vector + (pos * esize));
805 mono_gc_memmove_atomic (value, ea, esize);
809 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
815 ac = (MonoClass *)arr->obj.vtable->klass;
816 ec = ac->element_class;
818 esize = mono_array_element_size (ac);
819 ea = (gpointer*)((char*)arr->vector + (pos * esize));
821 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
822 g_assert (esize == sizeof (gpointer));
823 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
825 g_assert (ec->inited);
826 g_assert (esize == mono_class_value_size (ec, NULL));
827 if (ec->has_references)
828 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
830 mono_gc_memmove_atomic (ea, value, esize);
835 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
837 MonoClass *klass = array->obj.vtable->klass;
838 guint32 size = mono_array_element_size (klass);
839 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
841 const char *field_data;
843 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
844 MonoException *exc = mono_get_exception_argument("array",
845 "Cannot initialize array of non-primitive type.");
846 mono_set_pending_exception (exc);
850 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
851 MonoException *exc = mono_get_exception_argument("field_handle",
852 "Field doesn't have an RVA");
853 mono_set_pending_exception (exc);
857 size *= array->max_length;
858 field_data = mono_field_get_data (field_handle);
860 if (size > mono_type_size (field_handle->type, &align)) {
861 MonoException *exc = mono_get_exception_argument("field_handle",
862 "Field not large enough to fill array");
863 mono_set_pending_exception (exc);
867 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
869 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
870 guint ## n *src = (guint ## n *) field_data; \
872 nEnt = (size / sizeof(guint ## n)); \
874 for (i = 0; i < nEnt; i++) { \
875 data[i] = read ## n (&src[i]); \
879 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
881 switch (type->type) {
898 memcpy (mono_array_addr (array, char, 0), field_data, size);
902 memcpy (mono_array_addr (array, char, 0), field_data, size);
907 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
909 return offsetof (MonoString, chars);
912 ICALL_EXPORT MonoObject *
913 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
915 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
919 MonoObject *ret = mono_object_clone_checked (obj, &error);
920 mono_error_set_pending_exception (&error);
927 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
933 MONO_CHECK_ARG_NULL (handle,);
935 klass = mono_class_from_mono_type (handle);
936 MONO_CHECK_ARG (handle, klass,);
938 if (klass->generic_container)
941 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
942 if (!is_ok (&error)) {
943 mono_error_set_pending_exception (&error);
947 /* This will call the type constructor */
948 if (!mono_runtime_class_init_full (vtable, &error))
949 mono_error_set_pending_exception (&error);
953 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
957 mono_image_check_for_module_cctor (image);
958 if (image->has_module_cctor) {
959 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
960 if (!mono_error_ok (&error)) {
961 mono_error_set_pending_exception (&error);
964 /*It's fine to raise the exception here*/
965 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
966 if (!is_ok (&error)) {
967 mono_error_set_pending_exception (&error);
970 if (!mono_runtime_class_init_full (vtable, &error))
971 mono_error_set_pending_exception (&error);
975 ICALL_EXPORT MonoBoolean
976 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
981 /* later make this configurable and per-arch */
982 int min_size = 4096 * 4 * sizeof (void*);
983 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
984 /* if we have no info we are optimistic and assume there is enough room */
988 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
992 current = (guint8 *)&stack_addr;
993 if (current > stack_addr) {
994 if ((current - stack_addr) < min_size)
997 if (current - (stack_addr - stack_size) < min_size)
1003 ICALL_EXPORT MonoObject *
1004 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
1007 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
1008 mono_error_set_pending_exception (&error);
1014 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1018 MonoObject **values = NULL;
1021 gint32 result = (int)(gsize)mono_defaults.int32_class;
1022 MonoClassField* field;
1025 klass = mono_object_class (this_obj);
1027 if (mono_class_num_fields (klass) == 0)
1031 * Compute the starting value of the hashcode for fields of primitive
1032 * types, and return the remaining fields in an array to the managed side.
1033 * This way, we can avoid costly reflection operations in managed code.
1036 while ((field = mono_class_get_fields (klass, &iter))) {
1037 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1039 if (mono_field_is_deleted (field))
1041 /* FIXME: Add more types */
1042 switch (field->type->type) {
1044 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1046 case MONO_TYPE_STRING: {
1048 s = *(MonoString**)((guint8*)this_obj + field->offset);
1050 result ^= mono_string_hash (s);
1055 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1056 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1057 if (!is_ok (&error)) {
1058 mono_error_set_pending_exception (&error);
1061 values [count++] = o;
1067 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1068 if (mono_error_set_pending_exception (&error))
1070 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1071 for (i = 0; i < count; ++i)
1072 mono_array_setref (*fields, i, values [i]);
1079 ICALL_EXPORT MonoBoolean
1080 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1084 MonoObject **values = NULL;
1086 MonoClassField* field;
1090 MONO_CHECK_ARG_NULL (that, FALSE);
1092 if (this_obj->vtable != that->vtable)
1095 klass = mono_object_class (this_obj);
1097 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1098 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1101 * Do the comparison for fields of primitive type and return a result if
1102 * possible. Otherwise, return the remaining fields in an array to the
1103 * managed side. This way, we can avoid costly reflection operations in
1108 while ((field = mono_class_get_fields (klass, &iter))) {
1109 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1111 if (mono_field_is_deleted (field))
1113 /* FIXME: Add more types */
1114 switch (field->type->type) {
1117 case MONO_TYPE_BOOLEAN:
1118 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1123 case MONO_TYPE_CHAR:
1124 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1129 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1134 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1138 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1142 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1147 case MONO_TYPE_STRING: {
1148 MonoString *s1, *s2;
1149 guint32 s1len, s2len;
1150 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1151 s2 = *(MonoString**)((guint8*)that + field->offset);
1154 if ((s1 == NULL) || (s2 == NULL))
1156 s1len = mono_string_length (s1);
1157 s2len = mono_string_length (s2);
1161 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1167 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1168 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1169 if (!is_ok (&error)) {
1170 mono_error_set_pending_exception (&error);
1173 values [count++] = o;
1174 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1175 if (!is_ok (&error)) {
1176 mono_error_set_pending_exception (&error);
1179 values [count++] = o;
1182 if (klass->enumtype)
1183 /* enums only have one non-static field */
1189 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1190 if (mono_error_set_pending_exception (&error))
1192 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1193 for (i = 0; i < count; ++i)
1194 mono_array_setref_fast (*fields, i, values [i]);
1201 ICALL_EXPORT MonoReflectionType *
1202 ves_icall_System_Object_GetType (MonoObject *obj)
1205 MonoReflectionType *ret;
1206 #ifndef DISABLE_REMOTING
1207 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1208 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1211 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1213 mono_error_set_pending_exception (&error);
1218 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1220 MonoMethod **dest = (MonoMethod **)data;
1222 /* skip unmanaged frames */
1227 if (!strcmp (m->klass->name_space, "System.Reflection"))
1236 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1238 MonoMethod **dest = (MonoMethod **)data;
1240 /* skip unmanaged frames */
1244 if (m->wrapper_type != MONO_WRAPPER_NONE)
1252 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1263 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1265 MonoMethod **dest = (MonoMethod **)data;
1267 /* skip unmanaged frames */
1271 if (m->wrapper_type != MONO_WRAPPER_NONE)
1279 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1280 || (!strcmp (m->klass->name_space, "System"))))
1290 static MonoReflectionType *
1291 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1293 MonoMethod *m, *dest;
1295 MonoType *type = NULL;
1296 MonoAssembly *assembly = NULL;
1297 gboolean type_resolve = FALSE;
1298 MonoImage *rootimage = NULL;
1300 mono_error_init (error);
1303 * We must compute the calling assembly as type loading must happen under a metadata context.
1304 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1305 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1307 m = mono_method_get_last_managed ();
1309 if (m && m->klass->image != mono_defaults.corlib) {
1310 /* Happens with inlining */
1312 /* Ugly hack: type_from_parsed_name is called from
1313 * System.Type.internal_from_name, which is called most
1314 * directly from System.Type.GetType(string,bool,bool) but
1315 * also indirectly from places such as
1316 * System.Type.GetType(string,func,func) (via
1317 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1318 * so we need to skip over all of those to find the true caller.
1320 * It would be nice if we had stack marks.
1322 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1328 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1329 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1330 * to crash. This only seems to happen in some strange remoting
1331 * scenarios and I was unable to figure out what's happening there.
1332 * Dec 10, 2005 - Martin.
1336 assembly = dest->klass->image->assembly;
1337 type_resolve = TRUE;
1338 rootimage = assembly->image;
1340 g_warning (G_STRLOC);
1343 if (info->assembly.name)
1344 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1347 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1348 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1349 return_val_if_nok (error, NULL);
1353 // Say we're looking for System.Generic.Dict<int, Local>
1354 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1355 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1356 // is messed up when we go to construct the Local as the type arg...
1358 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1359 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1360 if (!info->assembly.name && !type) {
1362 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1363 return_val_if_nok (error, NULL);
1365 if (assembly && !type && type_resolve) {
1366 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1367 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1368 return_val_if_nok (error, NULL);
1374 return mono_type_get_object_checked (mono_domain_get (), type, error);
1377 ICALL_EXPORT MonoReflectionType*
1378 ves_icall_System_Type_internal_from_name (MonoString *name,
1379 MonoBoolean throwOnError,
1380 MonoBoolean ignoreCase)
1383 MonoTypeNameParse info;
1384 MonoReflectionType *type = NULL;
1387 char *str = mono_string_to_utf8_checked (name, &error);
1388 if (!is_ok (&error))
1391 parsedOk = mono_reflection_parse_type (str, &info);
1393 /* mono_reflection_parse_type() mangles the string */
1395 mono_reflection_free_type_info (&info);
1397 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1401 type = type_from_parsed_name (&info, ignoreCase, &error);
1403 mono_reflection_free_type_info (&info);
1405 if (!is_ok (&error))
1410 mono_error_set_type_load_name (&error, g_strdup (str), NULL, "");
1417 if (!is_ok (&error)) {
1419 mono_error_set_pending_exception (&error);
1421 mono_error_cleanup (&error);
1429 ICALL_EXPORT MonoReflectionType*
1430 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1433 MonoReflectionType *ret;
1434 MonoDomain *domain = mono_domain_get ();
1436 ret = mono_type_get_object_checked (domain, handle, &error);
1437 mono_error_set_pending_exception (&error);
1442 ICALL_EXPORT MonoType*
1443 ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass)
1445 return mono_class_get_type (klass);
1449 ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array)
1451 g_ptr_array_free (ptr_array, TRUE);
1455 ves_icall_Mono_SafeStringMarshal_GFree (void *c_str)
1461 ves_icall_Mono_SafeStringMarshal_StringToUtf8 (MonoString *s)
1464 char *res = mono_string_to_utf8_checked (s, &error);
1465 mono_error_set_pending_exception (&error);
1469 /* System.TypeCode */
1488 TYPECODE_STRING = 18
1491 ICALL_EXPORT guint32
1492 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1494 int t = type->type->type;
1496 if (type->type->byref)
1497 return TYPECODE_OBJECT;
1501 case MONO_TYPE_VOID:
1502 return TYPECODE_OBJECT;
1503 case MONO_TYPE_BOOLEAN:
1504 return TYPECODE_BOOLEAN;
1506 return TYPECODE_BYTE;
1508 return TYPECODE_SBYTE;
1510 return TYPECODE_UINT16;
1512 return TYPECODE_INT16;
1513 case MONO_TYPE_CHAR:
1514 return TYPECODE_CHAR;
1518 return TYPECODE_OBJECT;
1520 return TYPECODE_UINT32;
1522 return TYPECODE_INT32;
1524 return TYPECODE_UINT64;
1526 return TYPECODE_INT64;
1528 return TYPECODE_SINGLE;
1530 return TYPECODE_DOUBLE;
1531 case MONO_TYPE_VALUETYPE: {
1532 MonoClass *klass = type->type->data.klass;
1534 if (klass->enumtype) {
1535 t = mono_class_enum_basetype (klass)->type;
1537 } else if (mono_is_corlib_image (klass->image)) {
1538 if (strcmp (klass->name_space, "System") == 0) {
1539 if (strcmp (klass->name, "Decimal") == 0)
1540 return TYPECODE_DECIMAL;
1541 else if (strcmp (klass->name, "DateTime") == 0)
1542 return TYPECODE_DATETIME;
1545 return TYPECODE_OBJECT;
1547 case MONO_TYPE_STRING:
1548 return TYPECODE_STRING;
1549 case MONO_TYPE_SZARRAY:
1550 case MONO_TYPE_ARRAY:
1551 case MONO_TYPE_OBJECT:
1553 case MONO_TYPE_MVAR:
1554 case MONO_TYPE_TYPEDBYREF:
1555 return TYPECODE_OBJECT;
1556 case MONO_TYPE_CLASS:
1558 MonoClass *klass = type->type->data.klass;
1559 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1560 if (strcmp (klass->name, "DBNull") == 0)
1561 return TYPECODE_DBNULL;
1564 return TYPECODE_OBJECT;
1565 case MONO_TYPE_GENERICINST:
1566 return TYPECODE_OBJECT;
1568 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1574 mono_type_is_primitive (MonoType *type)
1576 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1577 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1581 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1583 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1584 return mono_class_enum_basetype (type->data.klass);
1585 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1586 return mono_class_enum_basetype (type->data.generic_class->container_class);
1590 ICALL_EXPORT guint32
1591 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1596 g_assert (type != NULL);
1598 klass = mono_class_from_mono_type (type->type);
1599 klassc = mono_class_from_mono_type (c->type);
1601 if (type->type->byref ^ c->type->byref)
1604 if (type->type->byref) {
1605 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1606 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1608 klass = mono_class_from_mono_type (t);
1609 klassc = mono_class_from_mono_type (ot);
1611 if (mono_type_is_primitive (t)) {
1612 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1613 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1614 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1615 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1616 return t->type == ot->type;
1618 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1621 if (klass->valuetype)
1622 return klass == klassc;
1623 return klass->valuetype == klassc->valuetype;
1626 return mono_class_is_assignable_from (klass, klassc);
1629 ICALL_EXPORT guint32
1630 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1633 MonoClass *klass = mono_class_from_mono_type (type->type);
1634 mono_class_init_checked (klass, &error);
1635 if (!is_ok (&error)) {
1636 mono_error_set_pending_exception (&error);
1639 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1640 mono_error_set_pending_exception (&error);
1644 ICALL_EXPORT guint32
1645 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1647 MonoClass *klass = mono_class_from_mono_type (type->type);
1648 return klass->flags;
1651 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1652 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1655 MonoClass *klass = field->field->parent;
1656 MonoMarshalType *info;
1660 if (klass->generic_container ||
1661 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1664 ftype = mono_field_get_type (field->field);
1665 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1668 info = mono_marshal_load_type_info (klass);
1670 for (i = 0; i < info->num_fields; ++i) {
1671 if (info->fields [i].field == field->field) {
1672 if (!info->fields [i].mspec)
1675 MonoReflectionMarshalAsAttribute* obj;
1676 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1677 if (!mono_error_ok (&error))
1678 mono_error_set_pending_exception (&error);
1687 ICALL_EXPORT MonoReflectionField*
1688 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1691 gboolean found = FALSE;
1697 klass = handle->parent;
1699 klass = mono_class_from_mono_type (type);
1701 found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1704 /* The managed code will throw the exception */
1708 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1709 mono_error_set_pending_exception (&error);
1713 ICALL_EXPORT MonoReflectionEvent*
1714 ves_icall_System_Reflection_EventInfo_internal_from_handle_type (MonoEvent *handle, MonoType *type)
1722 klass = handle->parent;
1724 klass = mono_class_from_mono_type (type);
1726 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1728 /* Managed code will throw an exception */
1732 MonoReflectionEvent *result = mono_event_get_object_checked (mono_domain_get (), klass, handle, &error);
1733 mono_error_set_pending_exception (&error);
1738 ICALL_EXPORT MonoReflectionProperty*
1739 ves_icall_System_Reflection_PropertyInfo_internal_from_handle_type (MonoProperty *handle, MonoType *type)
1747 klass = handle->parent;
1749 klass = mono_class_from_mono_type (type);
1751 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1753 /* Managed code will throw an exception */
1757 MonoReflectionProperty *result = mono_property_get_object_checked (mono_domain_get (), klass, handle, &error);
1758 mono_error_set_pending_exception (&error);
1762 ICALL_EXPORT MonoArray*
1763 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1766 MonoType *type = mono_field_get_type_checked (field->field, &error);
1769 if (!mono_error_ok (&error)) {
1770 mono_error_set_pending_exception (&error);
1774 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1775 mono_error_set_pending_exception (&error);
1780 vell_icall_get_method_attributes (MonoMethod *method)
1782 return method->flags;
1786 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1789 MonoReflectionType *rt;
1790 MonoDomain *domain = mono_domain_get ();
1791 MonoMethodSignature* sig;
1793 sig = mono_method_signature_checked (method, &error);
1794 if (!mono_error_ok (&error)) {
1795 mono_error_set_pending_exception (&error);
1799 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1800 if (!mono_error_ok (&error)) {
1801 mono_error_set_pending_exception (&error);
1805 MONO_STRUCT_SETREF (info, parent, rt);
1807 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1808 if (!mono_error_ok (&error)) {
1809 mono_error_set_pending_exception (&error);
1813 MONO_STRUCT_SETREF (info, ret, rt);
1815 info->attrs = method->flags;
1816 info->implattrs = method->iflags;
1817 if (sig->call_convention == MONO_CALL_DEFAULT)
1818 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1820 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1825 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1828 ICALL_EXPORT MonoArray*
1829 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1832 MonoDomain *domain = mono_domain_get ();
1834 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1835 mono_error_set_pending_exception (&error);
1839 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1840 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1843 MonoDomain *domain = mono_domain_get ();
1844 MonoReflectionMarshalAsAttribute* res = NULL;
1845 MonoMarshalSpec **mspecs;
1848 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1849 mono_method_get_marshal_info (method, mspecs);
1852 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1853 if (!mono_error_ok (&error)) {
1854 mono_error_set_pending_exception (&error);
1859 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1861 mono_metadata_free_marshal_spec (mspecs [i]);
1868 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1870 MonoClass *parent = field->field->parent;
1871 if (!parent->size_inited)
1872 mono_class_init (parent);
1873 mono_class_setup_fields_locking (parent);
1875 return field->field->offset - sizeof (MonoObject);
1878 ICALL_EXPORT MonoReflectionType*
1879 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1882 MonoReflectionType *ret;
1885 parent = declaring? field->field->parent: field->klass;
1887 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1888 mono_error_set_pending_exception (&error);
1894 ICALL_EXPORT MonoObject *
1895 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1898 MonoClass *fklass = field->klass;
1899 MonoClassField *cf = field->field;
1900 MonoDomain *domain = mono_object_domain (field);
1902 if (fklass->image->assembly->ref_only) {
1903 mono_set_pending_exception (mono_get_exception_invalid_operation (
1904 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1908 if (mono_security_core_clr_enabled () &&
1909 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1910 mono_error_set_pending_exception (&error);
1914 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1915 mono_error_set_pending_exception (&error);
1920 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1923 MonoClassField *cf = field->field;
1927 if (field->klass->image->assembly->ref_only) {
1928 mono_set_pending_exception (mono_get_exception_invalid_operation (
1929 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1933 if (mono_security_core_clr_enabled () &&
1934 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1935 mono_error_set_pending_exception (&error);
1939 type = mono_field_get_type_checked (cf, &error);
1940 if (!mono_error_ok (&error)) {
1941 mono_error_set_pending_exception (&error);
1945 v = (gchar *) value;
1947 switch (type->type) {
1950 case MONO_TYPE_BOOLEAN:
1953 case MONO_TYPE_CHAR:
1962 case MONO_TYPE_VALUETYPE:
1965 v += sizeof (MonoObject);
1967 case MONO_TYPE_STRING:
1968 case MONO_TYPE_OBJECT:
1969 case MONO_TYPE_CLASS:
1970 case MONO_TYPE_ARRAY:
1971 case MONO_TYPE_SZARRAY:
1974 case MONO_TYPE_GENERICINST: {
1975 MonoGenericClass *gclass = type->data.generic_class;
1976 g_assert (!gclass->context.class_inst->is_open);
1978 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1979 MonoClass *nklass = mono_class_from_mono_type (type);
1980 MonoObject *nullable;
1983 * Convert the boxed vtype into a Nullable structure.
1984 * This is complicated by the fact that Nullables have
1985 * a variable structure.
1987 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1988 if (!mono_error_ok (&error)) {
1989 mono_error_set_pending_exception (&error);
1993 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1995 v = (gchar *)mono_object_unbox (nullable);
1998 if (gclass->container_class->valuetype && (v != NULL))
1999 v += sizeof (MonoObject);
2003 g_error ("type 0x%x not handled in "
2004 "ves_icall_FieldInfo_SetValueInternal", type->type);
2009 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2010 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2011 if (!is_ok (&error)) {
2012 mono_error_set_pending_exception (&error);
2015 if (!vtable->initialized) {
2016 if (!mono_runtime_class_init_full (vtable, &error)) {
2017 mono_error_set_pending_exception (&error);
2021 mono_field_static_set_value (vtable, cf, v);
2023 mono_field_set_value (obj, cf, v);
2028 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2037 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2038 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2042 if (MONO_TYPE_IS_REFERENCE (f->type))
2043 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2045 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2048 ICALL_EXPORT MonoObject *
2049 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2051 MonoObject *o = NULL;
2052 MonoClassField *field = rfield->field;
2054 MonoDomain *domain = mono_object_domain (rfield);
2056 MonoTypeEnum def_type;
2057 const char *def_value;
2061 mono_class_init (field->parent);
2063 t = mono_field_get_type_checked (field, &error);
2064 if (!mono_error_ok (&error)) {
2065 mono_error_set_pending_exception (&error);
2069 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2070 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2074 if (image_is_dynamic (field->parent->image)) {
2075 MonoClass *klass = field->parent;
2076 int fidx = field - klass->fields;
2078 g_assert (fidx >= 0 && fidx < klass->field.count);
2079 g_assert (klass->ext);
2080 g_assert (klass->ext->field_def_values);
2081 def_type = klass->ext->field_def_values [fidx].def_type;
2082 def_value = klass->ext->field_def_values [fidx].data;
2083 if (def_type == MONO_TYPE_END) {
2084 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2088 def_value = mono_class_get_field_default_value (field, &def_type);
2089 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2091 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2096 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2100 case MONO_TYPE_BOOLEAN:
2103 case MONO_TYPE_CHAR:
2111 case MONO_TYPE_R8: {
2114 /* boxed value type */
2115 t = g_new0 (MonoType, 1);
2117 klass = mono_class_from_mono_type (t);
2119 o = mono_object_new_checked (domain, klass, &error);
2120 if (!mono_error_ok (&error)) {
2121 mono_error_set_pending_exception (&error);
2124 v = ((gchar *) o) + sizeof (MonoObject);
2125 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2126 if (mono_error_set_pending_exception (&error))
2130 case MONO_TYPE_STRING:
2131 case MONO_TYPE_CLASS:
2132 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2133 if (mono_error_set_pending_exception (&error))
2137 g_assert_not_reached ();
2143 ICALL_EXPORT MonoReflectionType*
2144 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2147 MonoReflectionType *ret;
2150 type = mono_field_get_type_checked (ref_field->field, &error);
2151 if (!mono_error_ok (&error)) {
2152 mono_error_set_pending_exception (&error);
2156 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2157 if (!mono_error_ok (&error)) {
2158 mono_error_set_pending_exception (&error);
2165 /* From MonoProperty.cs */
2167 PInfo_Attributes = 1,
2168 PInfo_GetMethod = 1 << 1,
2169 PInfo_SetMethod = 1 << 2,
2170 PInfo_ReflectedType = 1 << 3,
2171 PInfo_DeclaringType = 1 << 4,
2176 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2179 MonoReflectionType *rt;
2180 MonoReflectionMethod *rm;
2181 MonoDomain *domain = mono_object_domain (property);
2182 const MonoProperty *pproperty = property->property;
2184 if ((req_info & PInfo_ReflectedType) != 0) {
2185 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2186 if (mono_error_set_pending_exception (&error))
2189 MONO_STRUCT_SETREF (info, parent, rt);
2191 if ((req_info & PInfo_DeclaringType) != 0) {
2192 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2193 if (mono_error_set_pending_exception (&error))
2196 MONO_STRUCT_SETREF (info, declaring_type, rt);
2199 if ((req_info & PInfo_Name) != 0)
2200 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2202 if ((req_info & PInfo_Attributes) != 0)
2203 info->attrs = pproperty->attrs;
2205 if ((req_info & PInfo_GetMethod) != 0) {
2206 if (pproperty->get &&
2207 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2208 pproperty->get->klass == property->klass)) {
2209 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2210 if (mono_error_set_pending_exception (&error))
2216 MONO_STRUCT_SETREF (info, get, rm);
2218 if ((req_info & PInfo_SetMethod) != 0) {
2219 if (pproperty->set &&
2220 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2221 pproperty->set->klass == property->klass)) {
2222 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2223 if (mono_error_set_pending_exception (&error))
2229 MONO_STRUCT_SETREF (info, set, rm);
2232 * There may be other methods defined for properties, though, it seems they are not exposed
2233 * in the reflection API
2238 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2241 MonoReflectionType *rt;
2242 MonoReflectionMethod *rm;
2243 MonoDomain *domain = mono_object_domain (event);
2245 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2246 if (mono_error_set_pending_exception (&error))
2249 MONO_STRUCT_SETREF (info, reflected_type, rt);
2251 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2252 if (mono_error_set_pending_exception (&error))
2255 MONO_STRUCT_SETREF (info, declaring_type, rt);
2257 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2258 info->attrs = event->event->attrs;
2260 if (event->event->add) {
2261 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2262 if (mono_error_set_pending_exception (&error))
2268 MONO_STRUCT_SETREF (info, add_method, rm);
2270 if (event->event->remove) {
2271 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2272 if (mono_error_set_pending_exception (&error))
2278 MONO_STRUCT_SETREF (info, remove_method, rm);
2280 if (event->event->raise) {
2281 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2282 if (mono_error_set_pending_exception (&error))
2288 MONO_STRUCT_SETREF (info, raise_method, rm);
2290 #ifndef MONO_SMALL_CONFIG
2291 if (event->event->other) {
2293 while (event->event->other [n])
2295 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2296 if (mono_error_set_pending_exception (&error))
2298 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2300 for (i = 0; i < n; i++) {
2301 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2302 if (mono_error_set_pending_exception (&error))
2304 mono_array_setref (info->other_methods, i, rm);
2311 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2316 mono_class_setup_interfaces (klass, error);
2317 if (!mono_error_ok (error))
2320 for (i = 0; i < klass->interface_count; i++) {
2321 ic = klass->interfaces [i];
2322 g_hash_table_insert (ifaces, ic, ic);
2324 collect_interfaces (ic, ifaces, error);
2325 if (!mono_error_ok (error))
2331 MonoArray *iface_array;
2332 MonoGenericContext *context;
2336 } FillIfaceArrayData;
2339 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2341 MonoReflectionType *rt;
2342 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2343 MonoClass *ic = (MonoClass *)key;
2344 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2346 if (!mono_error_ok (data->error))
2349 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2350 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2351 if (!mono_error_ok (data->error))
2355 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2356 if (!mono_error_ok (data->error))
2359 mono_array_setref (data->iface_array, data->next_idx++, rt);
2362 mono_metadata_free_type (inflated);
2366 get_interfaces_hash (gconstpointer v1)
2368 MonoClass *k = (MonoClass*)v1;
2370 return k->type_token;
2373 ICALL_EXPORT MonoArray*
2374 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2377 MonoClass *klass = mono_class_from_mono_type (type->type);
2379 FillIfaceArrayData data = { 0 };
2382 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2384 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2385 data.context = mono_class_get_context (klass);
2386 klass = klass->generic_class->container_class;
2389 for (parent = klass; parent; parent = parent->parent) {
2390 mono_class_setup_interfaces (parent, &error);
2391 if (!mono_error_ok (&error))
2393 collect_interfaces (parent, iface_hash, &error);
2394 if (!mono_error_ok (&error))
2398 data.error = &error;
2399 data.domain = mono_object_domain (type);
2401 len = g_hash_table_size (iface_hash);
2403 g_hash_table_destroy (iface_hash);
2404 if (!data.domain->empty_types) {
2405 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2406 if (!is_ok (&error))
2409 return data.domain->empty_types;
2412 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2413 if (!is_ok (&error))
2415 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2416 if (!mono_error_ok (&error))
2419 g_hash_table_destroy (iface_hash);
2420 return data.iface_array;
2423 g_hash_table_destroy (iface_hash);
2424 mono_error_set_pending_exception (&error);
2429 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2431 gboolean variance_used;
2432 MonoClass *klass = mono_class_from_mono_type (type->type);
2433 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2434 MonoReflectionMethod *member;
2437 int i = 0, len, ioffset;
2441 mono_class_init_checked (klass, &error);
2442 if (mono_error_set_pending_exception (&error))
2444 mono_class_init_checked (iclass, &error);
2445 if (mono_error_set_pending_exception (&error))
2448 mono_class_setup_vtable (klass);
2450 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2454 len = mono_class_num_methods (iclass);
2455 domain = mono_object_domain (type);
2456 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2457 if (mono_error_set_pending_exception (&error))
2459 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2460 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2461 if (mono_error_set_pending_exception (&error))
2463 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2465 while ((method = mono_class_get_methods (iclass, &iter))) {
2466 member = mono_method_get_object_checked (domain, method, iclass, &error);
2467 if (mono_error_set_pending_exception (&error))
2469 mono_array_setref (*methods, i, member);
2470 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2471 if (mono_error_set_pending_exception (&error))
2473 mono_array_setref (*targets, i, member);
2480 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2483 MonoClass *klass = mono_class_from_mono_type (type->type);
2485 mono_class_init_checked (klass, &error);
2486 if (mono_error_set_pending_exception (&error))
2489 if (image_is_dynamic (klass->image)) {
2490 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2491 *packing = tb->packing_size;
2492 *size = tb->class_size;
2494 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2498 ICALL_EXPORT MonoReflectionType*
2499 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2502 MonoReflectionType *ret;
2505 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2506 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2507 mono_error_set_pending_exception (&error);
2511 klass = mono_class_from_mono_type (type->type);
2512 mono_class_init_checked (klass, &error);
2513 if (mono_error_set_pending_exception (&error))
2517 // GetElementType should only return a type for:
2518 // Array Pointer PassedByRef
2519 if (type->type->byref)
2520 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2521 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2522 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2523 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2524 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2528 mono_error_set_pending_exception (&error);
2533 ICALL_EXPORT MonoReflectionType*
2534 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2537 MonoReflectionType *ret;
2539 if (type->type->byref)
2542 MonoClass *klass = mono_class_from_mono_type (type->type);
2546 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2547 mono_error_set_pending_exception (&error);
2552 ICALL_EXPORT MonoBoolean
2553 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2555 return type->type->type == MONO_TYPE_PTR;
2558 ICALL_EXPORT MonoBoolean
2559 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2561 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)));
2564 ICALL_EXPORT MonoBoolean
2565 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2567 return type->type->byref;
2570 ICALL_EXPORT MonoBoolean
2571 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2574 MonoClass *klass = mono_class_from_mono_type (type->type);
2575 mono_class_init_checked (klass, &error);
2576 if (mono_error_set_pending_exception (&error))
2579 return mono_class_is_com_object (klass);
2582 ICALL_EXPORT guint32
2583 ves_icall_reflection_get_token (MonoObject* obj)
2586 guint32 result = mono_reflection_get_token_checked (obj, &error);
2587 mono_error_set_pending_exception (&error);
2591 ICALL_EXPORT MonoReflectionModule*
2592 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2595 MonoReflectionModule *result = NULL;
2596 MonoClass *klass = mono_class_from_mono_type (type->type);
2597 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2598 mono_error_set_pending_exception (&error);
2602 ICALL_EXPORT MonoReflectionAssembly*
2603 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2606 MonoDomain *domain = mono_domain_get ();
2607 MonoClass *klass = mono_class_from_mono_type (type->type);
2608 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2609 mono_error_set_pending_exception (&error);
2613 ICALL_EXPORT MonoReflectionType*
2614 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2617 MonoReflectionType *ret;
2618 MonoDomain *domain = mono_domain_get ();
2621 if (type->type->byref)
2623 if (type->type->type == MONO_TYPE_VAR) {
2624 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2625 klass = param ? param->owner.klass : NULL;
2626 } else if (type->type->type == MONO_TYPE_MVAR) {
2627 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2628 klass = param ? param->owner.method->klass : NULL;
2630 klass = mono_class_from_mono_type (type->type)->nested_in;
2636 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2637 mono_error_set_pending_exception (&error);
2642 ICALL_EXPORT MonoStringHandle
2643 ves_icall_RuntimeType_get_Name (MonoReflectionTypeHandle reftype, MonoError *error)
2645 MonoDomain *domain = mono_domain_get ();
2646 MonoType *type = MONO_HANDLE_RAW(reftype)->type;
2647 MonoClass *klass = mono_class_from_mono_type (type);
2650 char *n = g_strdup_printf ("%s&", klass->name);
2651 MonoStringHandle res = mono_string_new_handle (domain, n, error);
2657 return mono_string_new_handle (domain, klass->name, error);
2661 ICALL_EXPORT MonoStringHandle
2662 ves_icall_RuntimeType_get_Namespace (MonoReflectionTypeHandle type, MonoError *error)
2664 MonoDomain *domain = mono_domain_get ();
2665 MonoClass *klass = mono_class_from_mono_type_handle (type);
2667 while (klass->nested_in)
2668 klass = klass->nested_in;
2670 if (klass->name_space [0] == '\0')
2671 return NULL_HANDLE_STRING;
2673 return mono_string_new_handle (domain, klass->name_space, error);
2677 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2681 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2682 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2686 klass = mono_class_from_mono_type (type->type);
2692 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2694 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2697 ICALL_EXPORT MonoArray*
2698 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2701 MonoReflectionType *rt;
2703 MonoClass *klass, *pklass;
2704 MonoDomain *domain = mono_object_domain (type);
2707 klass = mono_class_from_mono_type (type->type);
2709 if (klass->generic_container) {
2710 MonoGenericContainer *container = klass->generic_container;
2711 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2712 if (mono_error_set_pending_exception (&error))
2714 for (i = 0; i < container->type_argc; ++i) {
2715 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2717 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2718 if (mono_error_set_pending_exception (&error))
2721 mono_array_setref (res, i, rt);
2723 } else if (klass->generic_class) {
2724 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2725 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2726 if (mono_error_set_pending_exception (&error))
2728 for (i = 0; i < inst->type_argc; ++i) {
2729 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2730 if (mono_error_set_pending_exception (&error))
2733 mono_array_setref (res, i, rt);
2741 ICALL_EXPORT gboolean
2742 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2746 if (!IS_MONOTYPE (type))
2749 if (type->type->byref)
2752 klass = mono_class_from_mono_type (type->type);
2753 return klass->generic_container != NULL;
2756 ICALL_EXPORT MonoReflectionType*
2757 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2760 MonoReflectionType *ret;
2763 if (type->type->byref)
2766 klass = mono_class_from_mono_type (type->type);
2768 if (klass->generic_container) {
2769 return type; /* check this one */
2771 if (klass->generic_class) {
2772 MonoClass *generic_class = klass->generic_class->container_class;
2775 tb = mono_class_get_ref_info (generic_class);
2777 if (generic_class->wastypebuilder && tb)
2778 return (MonoReflectionType *)tb;
2780 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2781 mono_error_set_pending_exception (&error);
2789 ICALL_EXPORT MonoReflectionType*
2790 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2793 MonoReflectionType *ret;
2795 MonoType *geninst, **types;
2798 g_assert (IS_MONOTYPE (type));
2799 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2800 if (mono_error_set_pending_exception (&error))
2803 count = mono_array_length (type_array);
2804 types = g_new0 (MonoType *, count);
2806 for (i = 0; i < count; i++) {
2807 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2808 types [i] = t->type;
2811 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2814 mono_error_set_pending_exception (&error);
2818 klass = mono_class_from_mono_type (geninst);
2820 /*we might inflate to the GTD*/
2821 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2822 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2826 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2827 mono_error_set_pending_exception (&error);
2832 ICALL_EXPORT gboolean
2833 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2837 if (!IS_MONOTYPE (type))
2840 if (type->type->byref)
2843 klass = mono_class_from_mono_type (type->type);
2844 return klass->generic_class != NULL || klass->generic_container != NULL;
2848 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2850 if (!IS_MONOTYPE (type))
2853 if (is_generic_parameter (type->type))
2854 return mono_type_get_generic_param_num (type->type);
2858 ICALL_EXPORT MonoGenericParamInfo *
2859 ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionType *type)
2861 return mono_generic_param_info (type->type->data.generic_param);
2864 ICALL_EXPORT MonoBoolean
2865 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2867 return is_generic_parameter (type->type);
2870 ICALL_EXPORT MonoReflectionMethod*
2871 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2872 MonoReflectionMethod* generic)
2879 MonoReflectionMethod *ret = NULL;
2881 domain = ((MonoObject *)type)->vtable->domain;
2883 klass = mono_class_from_mono_type (type->type);
2884 mono_class_init_checked (klass, &error);
2885 if (mono_error_set_pending_exception (&error))
2889 while ((method = mono_class_get_methods (klass, &iter))) {
2890 if (method->token == generic->method->token) {
2891 ret = mono_method_get_object_checked (domain, method, klass, &error);
2892 if (mono_error_set_pending_exception (&error))
2900 ICALL_EXPORT MonoReflectionMethod *
2901 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
2904 MonoType *type = ref_type->type;
2906 MonoReflectionMethod *ret = NULL;
2908 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2909 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2912 if (type->type == MONO_TYPE_VAR)
2915 method = mono_type_get_generic_param_owner (type)->owner.method;
2918 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2919 if (!mono_error_ok (&error))
2920 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2924 ICALL_EXPORT MonoBoolean
2925 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2927 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2931 ICALL_EXPORT MonoBoolean
2932 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2934 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2939 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2941 MonoDomain *domain = mono_domain_get ();
2942 MonoImage *image = method->method->klass->image;
2943 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2944 MonoTableInfo *tables = image->tables;
2945 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2946 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2947 guint32 im_cols [MONO_IMPLMAP_SIZE];
2948 guint32 scope_token;
2949 const char *import = NULL;
2950 const char *scope = NULL;
2952 if (image_is_dynamic (image)) {
2953 MonoReflectionMethodAux *method_aux =
2954 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2956 import = method_aux->dllentry;
2957 scope = method_aux->dll;
2960 if (!import || !scope) {
2961 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2966 if (piinfo->implmap_idx) {
2967 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2969 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2970 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2971 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2972 scope = mono_metadata_string_heap (image, scope_token);
2976 *flags = piinfo->piflags;
2977 *entry_point = mono_string_new (domain, import);
2978 *dll_name = mono_string_new (domain, scope);
2981 ICALL_EXPORT MonoReflectionMethod *
2982 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2984 MonoMethodInflated *imethod;
2986 MonoReflectionMethod *ret = NULL;
2989 if (method->method->is_generic)
2992 if (!method->method->is_inflated)
2995 imethod = (MonoMethodInflated *) method->method;
2997 result = imethod->declaring;
2998 /* Not a generic method. */
2999 if (!result->is_generic)
3002 if (image_is_dynamic (method->method->klass->image)) {
3003 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3004 MonoReflectionMethod *res;
3007 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3008 * the dynamic case as well ?
3010 mono_image_lock ((MonoImage*)image);
3011 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3012 mono_image_unlock ((MonoImage*)image);
3018 if (imethod->context.class_inst) {
3019 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3020 /*Generic methods gets the context of the GTD.*/
3021 if (mono_class_get_context (klass)) {
3022 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3023 if (!mono_error_ok (&error))
3028 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3030 if (!mono_error_ok (&error))
3031 mono_error_set_pending_exception (&error);
3035 ICALL_EXPORT gboolean
3036 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3038 return mono_method_signature (method->method)->generic_param_count != 0;
3041 ICALL_EXPORT gboolean
3042 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3044 return method->method->is_generic;
3047 ICALL_EXPORT MonoArray*
3048 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3051 MonoReflectionType *rt;
3056 domain = mono_object_domain (method);
3058 if (method->method->is_inflated) {
3059 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3062 count = inst->type_argc;
3063 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3064 if (mono_error_set_pending_exception (&error))
3067 for (i = 0; i < count; i++) {
3068 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3069 if (mono_error_set_pending_exception (&error))
3072 mono_array_setref (res, i, rt);
3079 count = mono_method_signature (method->method)->generic_param_count;
3080 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3081 if (mono_error_set_pending_exception (&error))
3084 for (i = 0; i < count; i++) {
3085 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3086 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3087 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3089 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3090 if (mono_error_set_pending_exception (&error))
3093 mono_array_setref (res, i, rt);
3099 ICALL_EXPORT MonoObject *
3100 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3104 * Invoke from reflection is supposed to always be a virtual call (the API
3105 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3106 * greater flexibility.
3108 MonoMethod *m = method->method;
3109 MonoMethodSignature *sig = mono_method_signature (m);
3112 void *obj = this_arg;
3116 if (mono_security_core_clr_enabled () &&
3117 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3118 mono_error_set_pending_exception (&error);
3122 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3123 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3124 mono_error_cleanup (&error); /* FIXME does this make sense? */
3125 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3130 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3131 if (!is_ok (&error)) {
3132 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3135 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3136 char *target_name = mono_type_get_full_name (m->klass);
3137 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3138 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3140 g_free (target_name);
3144 m = mono_object_get_virtual_method (this_arg, m);
3145 /* must pass the pointer to the value for valuetype methods */
3146 if (m->klass->valuetype)
3147 obj = mono_object_unbox (this_arg);
3148 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3149 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3154 if (sig->ret->byref) {
3155 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"));
3159 pcount = params? mono_array_length (params): 0;
3160 if (pcount != sig->param_count) {
3161 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3165 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3166 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."));
3170 image = m->klass->image;
3171 if (image->assembly->ref_only) {
3172 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."));
3176 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3177 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3181 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3185 intptr_t *lower_bounds;
3186 pcount = mono_array_length (params);
3187 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3188 /* Note: the synthetized array .ctors have int32 as argument type */
3189 for (i = 0; i < pcount; ++i)
3190 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3192 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3193 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3194 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3195 if (!mono_error_ok (&error)) {
3196 mono_error_set_pending_exception (&error);
3200 for (i = 0; i < mono_array_length (arr); ++i) {
3201 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3202 if (!mono_error_ok (&error)) {
3203 mono_error_set_pending_exception (&error);
3206 mono_array_setref_fast (arr, i, subarray);
3208 return (MonoObject*)arr;
3211 if (m->klass->rank == pcount) {
3212 /* Only lengths provided. */
3213 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3214 if (!mono_error_ok (&error)) {
3215 mono_error_set_pending_exception (&error);
3219 return (MonoObject*)arr;
3221 g_assert (pcount == (m->klass->rank * 2));
3222 /* The arguments are lower-bound-length pairs */
3223 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3225 for (i = 0; i < pcount / 2; ++i) {
3226 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3227 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3230 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3231 if (!mono_error_ok (&error)) {
3232 mono_error_set_pending_exception (&error);
3236 return (MonoObject*)arr;
3239 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3240 mono_error_set_pending_exception (&error);
3244 #ifndef DISABLE_REMOTING
3245 ICALL_EXPORT MonoObject *
3246 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3249 MonoDomain *domain = mono_object_domain (method);
3250 MonoMethod *m = method->method;
3251 MonoMethodSignature *sig = mono_method_signature (m);
3252 MonoArray *out_args;
3254 int i, j, outarg_count = 0;
3256 if (m->klass == mono_defaults.object_class) {
3257 if (!strcmp (m->name, "FieldGetter")) {
3258 MonoClass *k = this_arg->vtable->klass;
3262 /* If this is a proxy, then it must be a CBO */
3263 if (k == mono_defaults.transparent_proxy_class) {
3264 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3265 this_arg = tp->rp->unwrapped_server;
3266 g_assert (this_arg);
3267 k = this_arg->vtable->klass;
3270 name = mono_array_get (params, MonoString *, 1);
3271 str = mono_string_to_utf8_checked (name, &error);
3272 if (mono_error_set_pending_exception (&error))
3276 MonoClassField* field = mono_class_get_field_from_name (k, str);
3279 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3280 if (field_klass->valuetype) {
3281 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3282 if (mono_error_set_pending_exception (&error))
3285 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3287 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3288 if (mono_error_set_pending_exception (&error))
3290 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3291 mono_array_setref (out_args, 0, result);
3298 g_assert_not_reached ();
3300 } else if (!strcmp (m->name, "FieldSetter")) {
3301 MonoClass *k = this_arg->vtable->klass;
3307 /* If this is a proxy, then it must be a CBO */
3308 if (k == mono_defaults.transparent_proxy_class) {
3309 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3310 this_arg = tp->rp->unwrapped_server;
3311 g_assert (this_arg);
3312 k = this_arg->vtable->klass;
3315 name = mono_array_get (params, MonoString *, 1);
3316 str = mono_string_to_utf8_checked (name, &error);
3317 if (mono_error_set_pending_exception (&error))
3321 MonoClassField* field = mono_class_get_field_from_name (k, str);
3324 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3325 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3327 if (field_klass->valuetype) {
3328 size = mono_type_size (field->type, &align);
3329 g_assert (size == mono_class_value_size (field_klass, NULL));
3330 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3332 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3335 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3336 if (mono_error_set_pending_exception (&error))
3338 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3347 g_assert_not_reached ();
3352 for (i = 0; i < mono_array_length (params); i++) {
3353 if (sig->params [i]->byref)
3357 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3358 if (mono_error_set_pending_exception (&error))
3361 /* handle constructors only for objects already allocated */
3362 if (!strcmp (method->method->name, ".ctor"))
3363 g_assert (this_arg);
3365 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3366 g_assert (!method->method->klass->valuetype);
3367 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3368 if (mono_error_set_pending_exception (&error))
3371 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3372 if (sig->params [i]->byref) {
3374 arg = mono_array_get (params, gpointer, i);
3375 mono_array_setref (out_args, j, arg);
3380 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3387 read_enum_value (const char *mem, int type)
3390 case MONO_TYPE_BOOLEAN:
3392 return *(guint8*)mem;
3394 return *(gint8*)mem;
3395 case MONO_TYPE_CHAR:
3397 return read16 (mem);
3399 return (gint16) read16 (mem);
3401 return read32 (mem);
3403 return (gint32) read32 (mem);
3406 return read64 (mem);
3408 g_assert_not_reached ();
3414 write_enum_value (char *mem, int type, guint64 value)
3418 case MONO_TYPE_I1: {
3419 guint8 *p = (guint8*)mem;
3425 case MONO_TYPE_CHAR: {
3426 guint16 *p = (guint16 *)mem;
3431 case MONO_TYPE_I4: {
3432 guint32 *p = (guint32 *)mem;
3437 case MONO_TYPE_I8: {
3438 guint64 *p = (guint64 *)mem;
3443 g_assert_not_reached ();
3448 ICALL_EXPORT MonoObject *
3449 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3457 domain = mono_object_domain (enumType);
3458 enumc = mono_class_from_mono_type (enumType->type);
3460 mono_class_init_checked (enumc, &error);
3461 if (mono_error_set_pending_exception (&error))
3464 etype = mono_class_enum_basetype (enumc);
3466 res = mono_object_new_checked (domain, enumc, &error);
3467 if (mono_error_set_pending_exception (&error))
3469 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3474 ICALL_EXPORT MonoBoolean
3475 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3477 int size = mono_class_value_size (a->vtable->klass, NULL);
3478 guint64 a_val = 0, b_val = 0;
3480 memcpy (&a_val, mono_object_unbox (a), size);
3481 memcpy (&b_val, mono_object_unbox (b), size);
3483 return (a_val & b_val) == b_val;
3486 ICALL_EXPORT MonoObject *
3487 ves_icall_System_Enum_get_value (MonoObject *eobj)
3499 g_assert (eobj->vtable->klass->enumtype);
3501 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3502 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3503 if (mono_error_set_pending_exception (&error))
3505 dst = (char *)res + sizeof (MonoObject);
3506 src = (char *)eobj + sizeof (MonoObject);
3507 size = mono_class_value_size (enumc, NULL);
3509 memcpy (dst, src, size);
3514 ICALL_EXPORT MonoReflectionType *
3515 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3518 MonoReflectionType *ret;
3522 klass = mono_class_from_mono_type (type->type);
3523 mono_class_init_checked (klass, &error);
3524 if (mono_error_set_pending_exception (&error))
3527 etype = mono_class_enum_basetype (klass);
3529 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3533 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3534 mono_error_set_pending_exception (&error);
3540 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3542 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3543 gpointer odata = (char *)other + sizeof (MonoObject);
3544 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3545 g_assert (basetype);
3550 if (eobj->vtable->klass != other->vtable->klass)
3553 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3554 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3555 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3558 return me > other ? 1 : -1; \
3561 switch (basetype->type) {
3563 COMPARE_ENUM_VALUES (guint8);
3565 COMPARE_ENUM_VALUES (gint8);
3566 case MONO_TYPE_CHAR:
3568 COMPARE_ENUM_VALUES (guint16);
3570 COMPARE_ENUM_VALUES (gint16);
3572 COMPARE_ENUM_VALUES (guint32);
3574 COMPARE_ENUM_VALUES (gint32);
3576 COMPARE_ENUM_VALUES (guint64);
3578 COMPARE_ENUM_VALUES (gint64);
3582 #undef COMPARE_ENUM_VALUES
3583 /* indicates that the enum was of an unsupported unerlying type */
3588 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3590 gpointer data = (char *)eobj + sizeof (MonoObject);
3591 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3592 g_assert (basetype);
3594 switch (basetype->type) {
3595 case MONO_TYPE_I1: {
3596 gint8 value = *((gint8*)data);
3597 return ((int)value ^ (int)value << 8);
3600 return *((guint8*)data);
3601 case MONO_TYPE_CHAR:
3603 return *((guint16*)data);
3605 case MONO_TYPE_I2: {
3606 gint16 value = *((gint16*)data);
3607 return ((int)(guint16)value | (((int)value) << 16));
3610 return *((guint32*)data);
3612 return *((gint32*)data);
3614 case MONO_TYPE_I8: {
3615 gint64 value = *((gint64*)data);
3616 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3619 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3624 ICALL_EXPORT MonoBoolean
3625 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3628 MonoDomain *domain = mono_object_domain (type);
3629 MonoClass *enumc = mono_class_from_mono_type (type->type);
3630 guint j = 0, nvalues;
3632 MonoClassField *field;
3634 guint64 field_value, previous_value = 0;
3635 gboolean sorted = TRUE;
3637 mono_class_init_checked (enumc, &error);
3638 if (mono_error_set_pending_exception (&error))
3642 if (!enumc->enumtype) {
3643 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3647 base_type = mono_class_enum_basetype (enumc)->type;
3649 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3650 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3651 if (mono_error_set_pending_exception (&error))
3653 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3654 if (mono_error_set_pending_exception (&error))
3658 while ((field = mono_class_get_fields (enumc, &iter))) {
3660 MonoTypeEnum def_type;
3662 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3664 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3666 if (mono_field_is_deleted (field))
3668 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3670 p = mono_class_get_field_default_value (field, &def_type);
3671 /* len = */ mono_metadata_decode_blob_size (p, &p);
3673 field_value = read_enum_value (p, base_type);
3674 mono_array_set (*values, guint64, j, field_value);
3676 if (previous_value > field_value)
3679 previous_value = field_value;
3687 BFLAGS_IgnoreCase = 1,
3688 BFLAGS_DeclaredOnly = 2,
3689 BFLAGS_Instance = 4,
3691 BFLAGS_Public = 0x10,
3692 BFLAGS_NonPublic = 0x20,
3693 BFLAGS_FlattenHierarchy = 0x40,
3694 BFLAGS_InvokeMethod = 0x100,
3695 BFLAGS_CreateInstance = 0x200,
3696 BFLAGS_GetField = 0x400,
3697 BFLAGS_SetField = 0x800,
3698 BFLAGS_GetProperty = 0x1000,
3699 BFLAGS_SetProperty = 0x2000,
3700 BFLAGS_ExactBinding = 0x10000,
3701 BFLAGS_SuppressChangeType = 0x20000,
3702 BFLAGS_OptionalParamBinding = 0x40000
3705 ICALL_EXPORT GPtrArray*
3706 ves_icall_RuntimeType_GetFields_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
3709 MonoClass *startklass, *klass;
3712 int (*compare_func) (const char *s1, const char *s2) = NULL;
3713 MonoClassField *field;
3715 if (type->type->byref) {
3716 return g_ptr_array_new ();
3719 mono_error_init (&error);
3721 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3723 klass = startklass = mono_class_from_mono_type (type->type);
3725 GPtrArray *ptr_array = g_ptr_array_sized_new (16);
3728 if (mono_class_has_failure (klass)) {
3729 mono_error_set_for_class_failure (&error, klass);
3734 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3735 guint32 flags = mono_field_get_flags (field);
3737 if (mono_field_is_deleted_with_flags (field, flags))
3739 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3740 if (bflags & BFLAGS_Public)
3742 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3743 if (bflags & BFLAGS_NonPublic) {
3750 if (flags & FIELD_ATTRIBUTE_STATIC) {
3751 if (bflags & BFLAGS_Static)
3752 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3755 if (bflags & BFLAGS_Instance)
3762 if (utf8_name != NULL && compare_func (mono_field_get_name (field), utf8_name))
3765 g_ptr_array_add (ptr_array, field);
3767 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3773 g_ptr_array_free (ptr_array, TRUE);
3774 mono_error_set_pending_exception (&error);
3779 method_nonpublic (MonoMethod* method, gboolean start_klass)
3781 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3782 case METHOD_ATTRIBUTE_ASSEM:
3783 return (start_klass || mono_defaults.generic_ilist_class);
3784 case METHOD_ATTRIBUTE_PRIVATE:
3786 case METHOD_ATTRIBUTE_PUBLIC:
3794 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoError *error)
3797 MonoClass *startklass;
3801 /*FIXME, use MonoBitSet*/
3802 guint32 method_slots_default [8];
3803 guint32 *method_slots = NULL;
3804 int (*compare_func) (const char *s1, const char *s2) = NULL;
3806 array = g_ptr_array_new ();
3808 mono_error_init (error);
3811 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3813 /* An optimization for calls made from Delegate:CreateDelegate () */
3814 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3815 method = mono_get_delegate_invoke (klass);
3818 g_ptr_array_add (array, method);
3822 mono_class_setup_methods (klass);
3823 mono_class_setup_vtable (klass);
3824 if (mono_class_has_failure (klass))
3827 if (is_generic_parameter (&klass->byval_arg))
3828 nslots = mono_class_get_vtable_size (klass->parent);
3830 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3831 if (nslots >= sizeof (method_slots_default) * 8) {
3832 method_slots = g_new0 (guint32, nslots / 32 + 1);
3834 method_slots = method_slots_default;
3835 memset (method_slots, 0, sizeof (method_slots_default));
3838 mono_class_setup_methods (klass);
3839 mono_class_setup_vtable (klass);
3840 if (mono_class_has_failure (klass))
3844 while ((method = mono_class_get_methods (klass, &iter))) {
3846 if (method->slot != -1) {
3847 g_assert (method->slot < nslots);
3848 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3850 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3851 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3854 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3856 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3857 if (bflags & BFLAGS_Public)
3859 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3865 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3866 if (bflags & BFLAGS_Static)
3867 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3870 if (bflags & BFLAGS_Instance)
3878 if (compare_func (name, method->name))
3883 g_ptr_array_add (array, method);
3885 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3887 if (method_slots != method_slots_default)
3888 g_free (method_slots);
3893 if (method_slots != method_slots_default)
3894 g_free (method_slots);
3895 g_ptr_array_free (array, TRUE);
3897 g_assert (mono_class_has_failure (klass));
3898 mono_error_set_for_class_failure (error, klass);
3902 ICALL_EXPORT GPtrArray*
3903 ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionType *type, const char *mname, guint32 bflags, MonoBoolean ignore_case)
3906 GPtrArray *method_array;
3909 klass = mono_class_from_mono_type (type->type);
3910 if (type->type->byref) {
3911 return g_ptr_array_new ();
3914 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &error);
3915 mono_error_set_pending_exception (&error);
3916 return method_array;
3919 ICALL_EXPORT GPtrArray*
3920 ves_icall_RuntimeType_GetConstructors_native (MonoReflectionType *type, guint32 bflags)
3922 MonoClass *startklass, *klass;
3925 gpointer iter = NULL;
3926 GPtrArray *res_array;
3929 if (type->type->byref) {
3930 return g_ptr_array_new ();
3933 klass = startklass = mono_class_from_mono_type (type->type);
3935 mono_class_setup_methods (klass);
3936 if (mono_class_has_failure (klass)) {
3937 mono_error_init (&error);
3938 mono_error_set_for_class_failure (&error, klass);
3939 mono_error_set_pending_exception (&error);
3943 res_array = g_ptr_array_sized_new (4); /* FIXME, guestimating */
3946 while ((method = mono_class_get_methods (klass, &iter))) {
3948 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3950 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3951 if (bflags & BFLAGS_Public)
3954 if (bflags & BFLAGS_NonPublic)
3960 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3961 if (bflags & BFLAGS_Static)
3962 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3965 if (bflags & BFLAGS_Instance)
3971 g_ptr_array_add (res_array, method);
3978 property_hash (gconstpointer data)
3980 MonoProperty *prop = (MonoProperty*)data;
3982 return g_str_hash (prop->name);
3986 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
3988 if (method1->slot != -1 && method1->slot == method2->slot)
3991 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
3992 if (method1->is_inflated)
3993 method1 = ((MonoMethodInflated*) method1)->declaring;
3994 if (method2->is_inflated)
3995 method2 = ((MonoMethodInflated*) method2)->declaring;
3998 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4002 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4004 // Properties are hide-by-name-and-signature
4005 if (!g_str_equal (prop1->name, prop2->name))
4008 /* If we see a property in a generic method, we want to
4009 compare the generic signatures, not the inflated signatures
4010 because we might conflate two properties that were
4014 public T this[T t] { getter { return t; } } // method 1
4015 public U this[U u] { getter { return u; } } // method 2
4018 If we see int Foo<int,int>::Item[int] we need to know if
4019 the indexer came from method 1 or from method 2, and we
4020 shouldn't conflate them. (Bugzilla 36283)
4022 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4025 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4032 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4037 return method_nonpublic (accessor, start_klass);
4040 ICALL_EXPORT GPtrArray*
4041 ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionType *type, gchar *propname, guint32 bflags, MonoBoolean ignore_case)
4044 MonoClass *startklass, *klass;
4049 int (*compare_func) (const char *s1, const char *s2) = NULL;
4051 GHashTable *properties = NULL;
4052 GPtrArray *res_array;
4054 if (type->type->byref) {
4055 return g_ptr_array_new ();
4058 mono_error_init (&error);
4060 klass = startklass = mono_class_from_mono_type (type->type);
4062 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4064 res_array = g_ptr_array_sized_new (8); /*This the average for ASP.NET types*/
4066 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4068 mono_class_setup_methods (klass);
4069 mono_class_setup_vtable (klass);
4070 if (mono_class_has_failure (klass)) {
4071 mono_error_set_for_class_failure (&error, klass);
4076 while ((prop = mono_class_get_properties (klass, &iter))) {
4082 flags = method->flags;
4085 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4086 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4087 if (bflags & BFLAGS_Public)
4089 } else if (bflags & BFLAGS_NonPublic) {
4090 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4091 property_accessor_nonpublic(prop->set, startklass == klass)) {
4098 if (flags & METHOD_ATTRIBUTE_STATIC) {
4099 if (bflags & BFLAGS_Static)
4100 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4103 if (bflags & BFLAGS_Instance)
4111 if (propname != NULL && compare_func (propname, prop->name))
4114 if (g_hash_table_lookup (properties, prop))
4117 g_ptr_array_add (res_array, prop);
4119 g_hash_table_insert (properties, prop, prop);
4121 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4124 g_hash_table_destroy (properties);
4131 g_hash_table_destroy (properties);
4132 g_ptr_array_free (res_array, TRUE);
4134 mono_error_set_pending_exception (&error);
4140 event_hash (gconstpointer data)
4142 MonoEvent *event = (MonoEvent*)data;
4144 return g_str_hash (event->name);
4148 event_equal (MonoEvent *event1, MonoEvent *event2)
4150 // Events are hide-by-name
4151 return g_str_equal (event1->name, event2->name);
4154 ICALL_EXPORT GPtrArray*
4155 ves_icall_RuntimeType_GetEvents_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
4158 MonoClass *startklass, *klass;
4163 int (*compare_func) (const char *s1, const char *s2) = NULL;
4164 GHashTable *events = NULL;
4165 GPtrArray *res_array;
4167 if (type->type->byref) {
4168 return g_ptr_array_new ();
4171 mono_error_init (&error);
4173 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4175 res_array = g_ptr_array_sized_new (4);
4177 klass = startklass = mono_class_from_mono_type (type->type);
4179 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4181 mono_class_setup_methods (klass);
4182 mono_class_setup_vtable (klass);
4183 if (mono_class_has_failure (klass)) {
4184 mono_error_set_for_class_failure (&error, klass);
4189 while ((event = mono_class_get_events (klass, &iter))) {
4191 method = event->add;
4193 method = event->remove;
4195 method = event->raise;
4197 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4198 if (bflags & BFLAGS_Public)
4200 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4201 if (bflags & BFLAGS_NonPublic)
4206 if (bflags & BFLAGS_NonPublic)
4212 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4213 if (bflags & BFLAGS_Static)
4214 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4217 if (bflags & BFLAGS_Instance)
4222 if (bflags & BFLAGS_Instance)
4227 if (utf8_name != NULL && compare_func (event->name, utf8_name))
4230 if (g_hash_table_lookup (events, event))
4233 g_ptr_array_add (res_array, event);
4235 g_hash_table_insert (events, event, event);
4237 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4240 g_hash_table_destroy (events);
4246 g_hash_table_destroy (events);
4248 g_ptr_array_free (res_array, TRUE);
4250 mono_error_set_pending_exception (&error);
4254 ICALL_EXPORT GPtrArray *
4255 ves_icall_RuntimeType_GetNestedTypes_native (MonoReflectionType *type, char *str, guint32 bflags)
4261 GPtrArray *res_array;
4263 if (type->type->byref) {
4264 return g_ptr_array_new ();
4267 klass = mono_class_from_mono_type (type->type);
4270 * If a nested type is generic, return its generic type definition.
4271 * Note that this means that the return value is essentially the set
4272 * of nested types of the generic type definition of @klass.
4274 * A note in MSDN claims that a generic type definition can have
4275 * nested types that aren't generic. In any case, the container of that
4276 * nested type would be the generic type definition.
4278 if (klass->generic_class)
4279 klass = klass->generic_class->container_class;
4281 res_array = g_ptr_array_new ();
4284 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4286 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4287 if (bflags & BFLAGS_Public)
4290 if (bflags & BFLAGS_NonPublic)
4296 if (str != NULL && strcmp (nested->name, str))
4299 g_ptr_array_add (res_array, &nested->byval_arg);
4305 ICALL_EXPORT MonoReflectionType*
4306 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4309 MonoReflectionType *ret;
4311 MonoType *type = NULL;
4312 MonoTypeNameParse info;
4313 gboolean type_resolve;
4315 /* On MS.NET, this does not fire a TypeResolve event */
4316 type_resolve = TRUE;
4317 str = mono_string_to_utf8_checked (name, &error);
4318 if (mono_error_set_pending_exception (&error))
4320 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4321 if (!mono_reflection_parse_type (str, &info)) {
4323 mono_reflection_free_type_info (&info);
4325 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4328 /*g_print ("failed parse\n");*/
4332 if (info.assembly.name) {
4334 mono_reflection_free_type_info (&info);
4336 /* 1.0 and 2.0 throw different exceptions */
4337 if (mono_defaults.generic_ilist_class)
4338 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4340 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4346 if (module != NULL) {
4347 if (module->image) {
4348 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4349 if (!is_ok (&error)) {
4351 mono_reflection_free_type_info (&info);
4352 mono_error_set_pending_exception (&error);
4359 if (assembly_is_dynamic (assembly->assembly)) {
4360 /* Enumerate all modules */
4361 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4365 if (abuilder->modules) {
4366 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4367 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4368 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4369 if (!is_ok (&error)) {
4371 mono_reflection_free_type_info (&info);
4372 mono_error_set_pending_exception (&error);
4380 if (!type && abuilder->loaded_modules) {
4381 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4382 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4383 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4384 if (!is_ok (&error)) {
4386 mono_reflection_free_type_info (&info);
4387 mono_error_set_pending_exception (&error);
4396 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4397 if (!is_ok (&error)) {
4399 mono_reflection_free_type_info (&info);
4400 mono_error_set_pending_exception (&error);
4405 mono_reflection_free_type_info (&info);
4407 MonoException *e = NULL;
4410 e = mono_get_exception_type_load (name, NULL);
4413 mono_set_pending_exception (e);
4417 if (type->type == MONO_TYPE_CLASS) {
4418 MonoClass *klass = mono_type_get_class (type);
4420 /* need to report exceptions ? */
4421 if (throwOnError && mono_class_has_failure (klass)) {
4422 /* report SecurityException (or others) that occured when loading the assembly */
4423 MonoException *exc = mono_class_get_exception_for_failure (klass);
4424 mono_set_pending_exception (exc);
4429 /* g_print ("got it\n"); */
4430 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4431 mono_error_set_pending_exception (&error);
4437 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4440 gchar *shadow_ini_file;
4443 /* Check for shadow-copied assembly */
4444 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4445 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4447 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4448 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4454 g_free (shadow_ini_file);
4455 if (content != NULL) {
4458 *filename = content;
4465 ICALL_EXPORT MonoString *
4466 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4468 MonoDomain *domain = mono_object_domain (assembly);
4469 MonoAssembly *mass = assembly->assembly;
4470 MonoString *res = NULL;
4475 if (g_path_is_absolute (mass->image->name)) {
4476 absolute = g_strdup (mass->image->name);
4477 dirname = g_path_get_dirname (absolute);
4479 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4480 dirname = g_strdup (mass->basedir);
4483 replace_shadow_path (domain, dirname, &absolute);
4488 for (i = strlen (absolute) - 1; i >= 0; i--)
4489 if (absolute [i] == '\\')
4494 uri = g_filename_to_uri (absolute, NULL, NULL);
4496 const char *prepend = "file://";
4498 if (*absolute == '/' && *(absolute + 1) == '/') {
4501 prepend = "file:///";
4504 uri = g_strconcat (prepend, absolute, NULL);
4508 res = mono_string_new (domain, uri);
4515 ICALL_EXPORT MonoBoolean
4516 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4518 MonoAssembly *mass = assembly->assembly;
4520 return mass->in_gac;
4523 ICALL_EXPORT MonoReflectionAssembly*
4524 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4529 MonoImageOpenStatus status;
4530 MonoReflectionAssembly* result = NULL;
4532 name = mono_string_to_utf8_checked (mname, &error);
4533 if (mono_error_set_pending_exception (&error))
4535 res = mono_assembly_load_with_partial_name (name, &status);
4541 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4543 mono_error_set_pending_exception (&error);
4547 ICALL_EXPORT MonoStringHandle
4548 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4550 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4551 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4552 return mono_string_new_handle (domain, mono_image_get_filename (assembly->image), error);
4555 ICALL_EXPORT MonoBoolean
4556 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4558 return assembly->assembly->ref_only;
4561 ICALL_EXPORT MonoStringHandle
4562 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4564 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4565 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4567 return mono_string_new_handle (domain, assembly->image->version, error);
4570 ICALL_EXPORT MonoReflectionMethod*
4571 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4574 MonoReflectionMethod *res = NULL;
4577 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4581 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4582 if (!mono_error_ok (&error))
4585 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4588 if (!mono_error_ok (&error))
4589 mono_error_set_pending_exception (&error);
4593 ICALL_EXPORT MonoReflectionModule*
4594 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4597 MonoReflectionModule *result = NULL;
4598 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4599 if (!mono_error_ok (&error))
4600 mono_error_set_pending_exception (&error);
4604 ICALL_EXPORT MonoArray*
4605 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4608 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4609 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4610 if (mono_error_set_pending_exception (&error))
4615 for (i = 0; i < table->rows; ++i) {
4616 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4617 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4622 ICALL_EXPORT MonoStringHandle
4623 ves_icall_System_Reflection_Assembly_GetAotId (MonoError *error)
4626 guint8 aotid_sum = 0;
4627 MonoDomain* domain = mono_domain_get ();
4629 if (!domain->entry_assembly || !domain->entry_assembly->image)
4632 guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
4634 for (i = 0; i < 16; ++i)
4635 aotid_sum |= (*aotid)[i];
4640 gchar *guid = mono_guid_to_string((guint8*) aotid);
4641 MonoStringHandle res = mono_string_new_handle (domain, guid, error);
4647 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4649 static MonoMethod *create_version = NULL;
4653 mono_error_init (error);
4656 if (!create_version) {
4657 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4658 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4659 g_assert (create_version);
4660 mono_method_desc_free (desc);
4666 args [3] = &revision;
4667 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4668 return_val_if_nok (error, NULL);
4670 mono_runtime_invoke_checked (create_version, result, args, error);
4671 return_val_if_nok (error, NULL);
4676 ICALL_EXPORT MonoArray*
4677 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4681 MonoDomain *domain = mono_object_domain (assembly);
4683 static MonoMethod *create_culture = NULL;
4684 MonoImage *image = assembly->assembly->image;
4688 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4691 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4692 if (mono_error_set_pending_exception (&error))
4696 if (count > 0 && !create_culture) {
4697 MonoMethodDesc *desc = mono_method_desc_new (
4698 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4699 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4700 g_assert (create_culture);
4701 mono_method_desc_free (desc);
4704 for (i = 0; i < count; i++) {
4705 MonoObject *version;
4706 MonoReflectionAssemblyName *aname;
4707 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4709 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4711 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4712 domain, mono_class_get_assembly_name_class (), &error);
4713 if (mono_error_set_pending_exception (&error))
4716 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4718 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4719 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4720 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4721 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4722 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4723 aname->versioncompat = 1; /* SameMachine (default) */
4724 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4726 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4727 if (mono_error_set_pending_exception (&error))
4730 MONO_OBJECT_SETREF (aname, version, version);
4732 if (create_culture) {
4734 MonoBoolean assembly_ref = 1;
4735 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4736 args [1] = &assembly_ref;
4738 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4739 if (mono_error_set_pending_exception (&error))
4742 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4745 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4746 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4747 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4749 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4750 /* public key token isn't copied - the class library will
4751 automatically generate it from the public key if required */
4752 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4753 if (mono_error_set_pending_exception (&error))
4756 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4757 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4759 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4760 if (mono_error_set_pending_exception (&error))
4763 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4764 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
4767 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
4768 if (mono_error_set_pending_exception (&error))
4771 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4774 /* note: this function doesn't return the codebase on purpose (i.e. it can
4775 be used under partial trust as path information isn't present). */
4777 mono_array_setref (result, i, aname);
4782 /* move this in some file in mono/util/ */
4784 g_concat_dir_and_file (const char *dir, const char *file)
4786 g_return_val_if_fail (dir != NULL, NULL);
4787 g_return_val_if_fail (file != NULL, NULL);
4790 * If the directory name doesn't have a / on the end, we need
4791 * to add one so we get a proper path to the file
4793 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4794 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4796 return g_strconcat (dir, file, NULL);
4800 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4803 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4805 guint32 cols [MONO_MANIFEST_SIZE];
4806 guint32 impl, file_idx;
4810 char *n = mono_string_to_utf8_checked (name, &error);
4811 if (mono_error_set_pending_exception (&error))
4814 for (i = 0; i < table->rows; ++i) {
4815 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4816 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4817 if (strcmp (val, n) == 0)
4821 if (i == table->rows)
4824 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4827 * this code should only be called after obtaining the
4828 * ResourceInfo and handling the other cases.
4830 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4831 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4833 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4838 module = assembly->assembly->image;
4841 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4842 if (mono_error_set_pending_exception (&error))
4844 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4846 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4849 ICALL_EXPORT gboolean
4850 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4853 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4855 guint32 cols [MONO_MANIFEST_SIZE];
4856 guint32 file_cols [MONO_FILE_SIZE];
4860 n = mono_string_to_utf8_checked (name, &error);
4861 if (mono_error_set_pending_exception (&error))
4863 for (i = 0; i < table->rows; ++i) {
4864 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4865 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4866 if (strcmp (val, n) == 0)
4870 if (i == table->rows)
4873 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4874 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4877 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4878 case MONO_IMPLEMENTATION_FILE:
4879 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4880 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4881 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4882 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4883 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4884 if (file_cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA)
4887 info->location = RESOURCE_LOCATION_EMBEDDED;
4890 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4891 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4892 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4893 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4894 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4895 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4897 mono_set_pending_exception (ex);
4900 MonoReflectionAssembly *assm_obj;
4901 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4903 mono_error_set_pending_exception (&error);
4906 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4908 /* Obtain info recursively */
4909 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4910 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4913 case MONO_IMPLEMENTATION_EXP_TYPE:
4914 g_assert_not_reached ();
4922 ICALL_EXPORT MonoObject*
4923 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4926 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4927 MonoArray *result = NULL;
4932 /* check hash if needed */
4934 n = mono_string_to_utf8_checked (name, &error);
4935 if (mono_error_set_pending_exception (&error))
4938 for (i = 0; i < table->rows; ++i) {
4939 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4940 if (strcmp (val, n) == 0) {
4943 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4944 fn = mono_string_new (mono_object_domain (assembly), n);
4946 return (MonoObject*)fn;
4954 for (i = 0; i < table->rows; ++i) {
4955 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4959 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
4960 if (mono_error_set_pending_exception (&error))
4965 for (i = 0; i < table->rows; ++i) {
4966 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4967 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4968 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4969 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4974 return (MonoObject*)result;
4977 ICALL_EXPORT MonoArray*
4978 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4981 MonoDomain *domain = mono_domain_get();
4984 int i, j, file_count = 0;
4985 MonoImage **modules;
4986 guint32 module_count, real_module_count;
4987 MonoTableInfo *table;
4988 guint32 cols [MONO_FILE_SIZE];
4989 MonoImage *image = assembly->assembly->image;
4991 g_assert (image != NULL);
4992 g_assert (!assembly_is_dynamic (assembly->assembly));
4994 table = &image->tables [MONO_TABLE_FILE];
4995 file_count = table->rows;
4997 modules = image->modules;
4998 module_count = image->module_count;
5000 real_module_count = 0;
5001 for (i = 0; i < module_count; ++i)
5003 real_module_count ++;
5005 klass = mono_class_get_module_class ();
5006 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5007 if (mono_error_set_pending_exception (&error))
5010 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5011 if (mono_error_set_pending_exception (&error))
5014 mono_array_setref (res, 0, image_obj);
5016 for (i = 0; i < module_count; ++i)
5018 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5019 if (mono_error_set_pending_exception (&error))
5021 mono_array_setref (res, j, rm);
5025 for (i = 0; i < file_count; ++i, ++j) {
5026 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5027 if (cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA) {
5028 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5029 if (mono_error_set_pending_exception (&error))
5031 mono_array_setref (res, j, rm);
5034 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5036 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5037 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5040 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5041 if (mono_error_set_pending_exception (&error))
5043 mono_array_setref (res, j, rm);
5050 ICALL_EXPORT MonoReflectionMethod*
5051 ves_icall_GetCurrentMethod (void)
5053 MonoReflectionMethod *res = NULL;
5056 MonoMethod *m = mono_method_get_last_managed ();
5059 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5063 while (m->is_inflated)
5064 m = ((MonoMethodInflated*)m)->declaring;
5066 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5067 mono_error_set_pending_exception (&error);
5073 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5076 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5079 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5080 //method is inflated, we should inflate it on the other class
5081 MonoGenericContext ctx;
5082 ctx.method_inst = inflated->context.method_inst;
5083 ctx.class_inst = inflated->context.class_inst;
5084 if (klass->generic_class)
5085 ctx.class_inst = klass->generic_class->context.class_inst;
5086 else if (klass->generic_container)
5087 ctx.class_inst = klass->generic_container->context.class_inst;
5088 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5089 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5093 mono_class_setup_methods (method->klass);
5094 if (mono_class_has_failure (method->klass))
5096 for (i = 0; i < method->klass->method.count; ++i) {
5097 if (method->klass->methods [i] == method) {
5102 mono_class_setup_methods (klass);
5103 if (mono_class_has_failure (klass))
5105 g_assert (offset >= 0 && offset < klass->method.count);
5106 return klass->methods [offset];
5109 ICALL_EXPORT MonoReflectionMethod*
5110 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check)
5112 MonoReflectionMethod *res = NULL;
5115 if (type && generic_check) {
5116 klass = mono_class_from_mono_type (type);
5117 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5120 if (method->klass != klass) {
5121 method = mono_method_get_equivalent_method (method, klass);
5126 klass = mono_class_from_mono_type (type);
5128 klass = method->klass;
5129 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5130 mono_error_set_pending_exception (&error);
5134 ICALL_EXPORT MonoReflectionMethodBody*
5135 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5138 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5139 mono_error_set_pending_exception (&error);
5143 ICALL_EXPORT MonoReflectionAssembly*
5144 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5147 MonoReflectionAssembly *result;
5148 MonoMethod *dest = NULL;
5150 mono_stack_walk_no_il (get_executing, &dest);
5152 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5154 mono_error_set_pending_exception (&error);
5159 ICALL_EXPORT MonoReflectionAssembly*
5160 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5163 MonoReflectionAssembly *result;
5164 MonoDomain* domain = mono_domain_get ();
5166 if (!domain->entry_assembly)
5169 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5171 mono_error_set_pending_exception (&error);
5175 ICALL_EXPORT MonoReflectionAssembly*
5176 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5181 MonoReflectionAssembly *result;
5184 mono_stack_walk_no_il (get_executing, &dest);
5186 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5190 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5193 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5195 mono_error_set_pending_exception (&error);
5199 ICALL_EXPORT MonoStringHandle
5200 ves_icall_System_RuntimeType_getFullName (MonoReflectionTypeHandle object, gboolean full_name,
5201 gboolean assembly_qualified, MonoError *error)
5203 MonoDomain *domain = mono_object_domain (MONO_HANDLE_RAW (object));
5204 MonoType *type = MONO_HANDLE_RAW (object)->type;
5205 MonoTypeNameFormat format;
5206 MonoStringHandle res;
5210 format = assembly_qualified ?
5211 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5212 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5214 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5216 name = mono_type_get_name_full (type, format);
5218 return NULL_HANDLE_STRING;
5220 if (full_name && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
5222 return NULL_HANDLE_STRING;
5225 res = mono_string_new_handle (domain, name, error);
5232 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5235 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5237 mono_class_init_checked (klass, &error);
5238 mono_error_set_pending_exception (&error);
5239 return mono_security_core_clr_class_level (klass);
5243 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5245 MonoClassField *field = rfield->field;
5246 return mono_security_core_clr_field_level (field, TRUE);
5250 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5252 MonoMethod *method = rfield->method;
5253 return mono_security_core_clr_method_level (method, TRUE);
5257 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)
5259 static MonoMethod *create_culture = NULL;
5263 const char *pkey_ptr;
5265 MonoBoolean assembly_ref = 0;
5267 mono_error_init (error);
5269 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5270 aname->major = name->major;
5271 aname->minor = name->minor;
5272 aname->build = name->build;
5273 aname->flags = name->flags;
5274 aname->revision = name->revision;
5275 aname->hashalg = name->hash_alg;
5276 aname->versioncompat = 1; /* SameMachine (default) */
5277 aname->processor_architecture = name->arch;
5279 if (by_default_version) {
5280 MonoObject *version;
5282 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5283 return_if_nok (error);
5285 MONO_OBJECT_SETREF (aname, version, version);
5289 if (absolute != NULL && *absolute != '\0') {
5290 const gchar *prepend = "file://";
5293 codebase = g_strdup (absolute);
5298 for (i = strlen (codebase) - 1; i >= 0; i--)
5299 if (codebase [i] == '\\')
5302 if (*codebase == '/' && *(codebase + 1) == '/') {
5305 prepend = "file:///";
5309 result = g_strconcat (prepend, codebase, NULL);
5315 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5319 if (!create_culture) {
5320 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5321 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5322 g_assert (create_culture);
5323 mono_method_desc_free (desc);
5326 if (name->culture) {
5327 args [0] = mono_string_new (domain, name->culture);
5328 args [1] = &assembly_ref;
5330 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5331 return_if_nok (error);
5333 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5336 if (name->public_key) {
5337 pkey_ptr = (char*)name->public_key;
5338 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5340 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5341 return_if_nok (error);
5342 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5343 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5344 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5345 } else if (default_publickey) {
5346 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5347 return_if_nok (error);
5348 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5349 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5352 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5353 if (name->public_key_token [0]) {
5357 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5358 return_if_nok (error);
5360 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5361 p = mono_array_addr (keyToken, char, 0);
5363 for (i = 0, j = 0; i < 8; i++) {
5364 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5365 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5368 } else if (default_token) {
5369 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5370 return_if_nok (error);
5371 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5375 ICALL_EXPORT MonoString *
5376 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5378 MonoDomain *domain = mono_object_domain (assembly);
5379 MonoAssembly *mass = assembly->assembly;
5383 name = mono_stringify_assembly_name (&mass->aname);
5384 res = mono_string_new (domain, name);
5390 ICALL_EXPORT MonoAssemblyName *
5391 ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
5393 return &mass->aname;
5397 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5401 MonoImageOpenStatus status = MONO_IMAGE_OK;
5404 MonoAssemblyName name;
5407 filename = mono_string_to_utf8_checked (fname, &error);
5408 if (mono_error_set_pending_exception (&error))
5411 dirname = g_path_get_dirname (filename);
5412 replace_shadow_path (mono_domain_get (), dirname, &filename);
5415 image = mono_image_open (filename, &status);
5421 if (status == MONO_IMAGE_IMAGE_INVALID)
5422 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5424 exc = mono_get_exception_file_not_found2 (NULL, fname);
5425 mono_set_pending_exception (exc);
5429 res = mono_assembly_fill_assembly_name (image, &name);
5431 mono_image_close (image);
5433 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5437 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5438 mono_error_set_pending_exception (&error);
5440 mono_image_close (image);
5444 ICALL_EXPORT MonoBoolean
5445 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5446 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5448 MonoBoolean result = FALSE;
5449 MonoDeclSecurityEntry entry;
5451 /* SecurityAction.RequestMinimum */
5452 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5453 *minimum = entry.blob;
5454 *minLength = entry.size;
5457 /* SecurityAction.RequestOptional */
5458 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5459 *optional = entry.blob;
5460 *optLength = entry.size;
5463 /* SecurityAction.RequestRefuse */
5464 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5465 *refused = entry.blob;
5466 *refLength = entry.size;
5474 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5476 guint32 attrs, visibility;
5478 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5479 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5480 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5483 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5489 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5491 MonoReflectionType *rt;
5494 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5497 mono_error_init (error);
5499 /* we start the count from 1 because we skip the special type <Module> */
5502 for (i = 1; i < tdef->rows; ++i) {
5503 if (mono_module_type_is_visible (tdef, image, i + 1))
5507 count = tdef->rows - 1;
5509 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5510 return_val_if_nok (error, NULL);
5511 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5512 return_val_if_nok (error, NULL);
5514 for (i = 1; i < tdef->rows; ++i) {
5515 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5516 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5519 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5520 return_val_if_nok (error, NULL);
5522 mono_array_setref (res, count, rt);
5524 MonoException *ex = mono_error_convert_to_exception (error);
5525 mono_array_setref (*exceptions, count, ex);
5534 ICALL_EXPORT MonoArray*
5535 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5538 MonoArray *res = NULL;
5539 MonoArray *exceptions = NULL;
5540 MonoImage *image = NULL;
5541 MonoTableInfo *table = NULL;
5544 int i, len, ex_count;
5546 domain = mono_object_domain (assembly);
5548 g_assert (!assembly_is_dynamic (assembly->assembly));
5549 image = assembly->assembly->image;
5550 table = &image->tables [MONO_TABLE_FILE];
5551 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5552 if (mono_error_set_pending_exception (&error))
5555 /* Append data from all modules in the assembly */
5556 for (i = 0; i < table->rows; ++i) {
5557 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5558 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5563 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5564 if (mono_error_set_pending_exception (&error))
5568 /* Append the new types to the end of the array */
5569 if (mono_array_length (res2) > 0) {
5571 MonoArray *res3, *ex3;
5573 len1 = mono_array_length (res);
5574 len2 = mono_array_length (res2);
5576 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5577 if (mono_error_set_pending_exception (&error))
5579 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5580 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5583 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5584 if (mono_error_set_pending_exception (&error))
5586 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5587 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5594 /* the ReflectionTypeLoadException must have all the types (Types property),
5595 * NULL replacing types which throws an exception. The LoaderException must
5596 * contain all exceptions for NULL items.
5599 len = mono_array_length (res);
5602 for (i = 0; i < len; i++) {
5603 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5607 klass = mono_type_get_class (t->type);
5608 if ((klass != NULL) && mono_class_has_failure (klass)) {
5609 /* keep the class in the list */
5610 list = g_list_append (list, klass);
5611 /* and replace Type with NULL */
5612 mono_array_setref (res, i, NULL);
5619 if (list || ex_count) {
5621 MonoException *exc = NULL;
5622 MonoArray *exl = NULL;
5623 int j, length = g_list_length (list) + ex_count;
5625 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5626 if (mono_error_set_pending_exception (&error)) {
5630 /* Types for which mono_class_get_checked () succeeded */
5631 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5632 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5633 mono_array_setref (exl, i, exc);
5635 /* Types for which it don't */
5636 for (j = 0; j < mono_array_length (exceptions); ++j) {
5637 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5639 g_assert (i < length);
5640 mono_array_setref (exl, i, exc);
5647 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5648 if (!is_ok (&error)) {
5649 mono_error_set_pending_exception (&error);
5652 mono_set_pending_exception (exc);
5660 ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname)
5662 mono_assembly_name_free (aname);
5665 ICALL_EXPORT gboolean
5666 ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, gboolean *is_version_definited, gboolean *is_token_defined)
5668 *is_version_definited = *is_token_defined = FALSE;
5670 return mono_assembly_name_parse_full (name, aname, TRUE, is_version_definited, is_token_defined);
5673 ICALL_EXPORT MonoReflectionType*
5674 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5677 MonoReflectionType *ret;
5678 MonoDomain *domain = mono_object_domain (module);
5681 g_assert (module->image);
5683 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5684 /* These images do not have a global type */
5687 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5688 if (!mono_error_ok (&error)) {
5689 mono_error_set_pending_exception (&error);
5693 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5694 if (!mono_error_ok (&error)) {
5695 mono_error_set_pending_exception (&error);
5703 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5705 /*if (module->image)
5706 mono_image_close (module->image);*/
5709 ICALL_EXPORT MonoStringHandle
5710 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModuleHandle refmodule, MonoError *error)
5712 MonoDomain *domain = MONO_HANDLE_DOMAIN (refmodule);
5713 MonoImage *image = MONO_HANDLE_RAW (refmodule)->image;
5716 return mono_string_new_handle (domain, image->guid, error);
5719 ICALL_EXPORT gpointer
5720 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5723 if (module->image && module->image->is_module_handle)
5724 return module->image->raw_data;
5727 return (gpointer) (-1);
5731 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5733 if (image_is_dynamic (image)) {
5734 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5735 *pe_kind = dyn->pe_kind;
5736 *machine = dyn->machine;
5739 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5740 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5745 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5747 return (image->md_version_major << 16) | (image->md_version_minor);
5750 ICALL_EXPORT MonoArray*
5751 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5754 MonoArray *exceptions;
5757 if (!module->image) {
5758 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
5759 mono_error_set_pending_exception (&error);
5764 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5765 if (mono_error_set_pending_exception (&error))
5768 for (i = 0; i < mono_array_length (exceptions); ++i) {
5769 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5771 mono_set_pending_exception (ex);
5780 mono_memberref_is_method (MonoImage *image, guint32 token)
5782 if (!image_is_dynamic (image)) {
5783 guint32 cols [MONO_MEMBERREF_SIZE];
5785 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5786 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5787 mono_metadata_decode_blob_size (sig, &sig);
5788 return (*sig != 0x6);
5791 MonoClass *handle_class;
5793 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5794 mono_error_cleanup (&error); /* just probing, ignore error */
5798 return mono_defaults.methodhandle_class == handle_class;
5803 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5806 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5807 mono_array_addr (type_args, MonoType*, 0));
5809 context->class_inst = NULL;
5811 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5812 mono_array_addr (method_args, MonoType*, 0));
5814 context->method_inst = NULL;
5817 ICALL_EXPORT MonoType*
5818 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5821 int table = mono_metadata_token_table (token);
5822 int index = mono_metadata_token_index (token);
5823 MonoGenericContext context;
5826 *resolve_error = ResolveTokenError_Other;
5828 /* Validate token */
5829 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5830 (table != MONO_TABLE_TYPESPEC)) {
5831 *resolve_error = ResolveTokenError_BadTable;
5835 if (image_is_dynamic (image)) {
5836 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5837 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5838 mono_error_cleanup (&error);
5839 return klass ? &klass->byval_arg : NULL;
5842 init_generic_context_from_args (&context, type_args, method_args);
5843 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5844 mono_error_cleanup (&error);
5845 return klass ? &klass->byval_arg : NULL;
5848 if ((index <= 0) || (index > image->tables [table].rows)) {
5849 *resolve_error = ResolveTokenError_OutOfRange;
5853 init_generic_context_from_args (&context, type_args, method_args);
5854 klass = mono_class_get_checked (image, token, &error);
5856 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5857 if (!mono_error_ok (&error)) {
5858 mono_error_set_pending_exception (&error);
5863 return &klass->byval_arg;
5868 ICALL_EXPORT MonoMethod*
5869 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5872 int table = mono_metadata_token_table (token);
5873 int index = mono_metadata_token_index (token);
5874 MonoGenericContext context;
5877 *resolve_error = ResolveTokenError_Other;
5879 /* Validate token */
5880 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5881 (table != MONO_TABLE_MEMBERREF)) {
5882 *resolve_error = ResolveTokenError_BadTable;
5886 if (image_is_dynamic (image)) {
5887 if (table == MONO_TABLE_METHOD) {
5888 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5889 mono_error_cleanup (&error);
5893 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5894 *resolve_error = ResolveTokenError_BadTable;
5898 init_generic_context_from_args (&context, type_args, method_args);
5899 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5900 mono_error_cleanup (&error);
5904 if ((index <= 0) || (index > image->tables [table].rows)) {
5905 *resolve_error = ResolveTokenError_OutOfRange;
5908 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5909 *resolve_error = ResolveTokenError_BadTable;
5913 init_generic_context_from_args (&context, type_args, method_args);
5914 method = mono_get_method_checked (image, token, NULL, &context, &error);
5915 mono_error_set_pending_exception (&error);
5920 ICALL_EXPORT MonoString*
5921 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5924 int index = mono_metadata_token_index (token);
5926 *resolve_error = ResolveTokenError_Other;
5928 /* Validate token */
5929 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5930 *resolve_error = ResolveTokenError_BadTable;
5934 if (image_is_dynamic (image)) {
5935 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5936 mono_error_cleanup (&error);
5940 if ((index <= 0) || (index >= image->heap_us.size)) {
5941 *resolve_error = ResolveTokenError_OutOfRange;
5945 /* FIXME: What to do if the index points into the middle of a string ? */
5947 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
5948 mono_error_set_pending_exception (&error);
5952 ICALL_EXPORT MonoClassField*
5953 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5957 int table = mono_metadata_token_table (token);
5958 int index = mono_metadata_token_index (token);
5959 MonoGenericContext context;
5960 MonoClassField *field;
5962 *resolve_error = ResolveTokenError_Other;
5964 /* Validate token */
5965 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5966 *resolve_error = ResolveTokenError_BadTable;
5970 if (image_is_dynamic (image)) {
5971 if (table == MONO_TABLE_FIELD) {
5972 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5973 mono_error_cleanup (&error);
5977 if (mono_memberref_is_method (image, token)) {
5978 *resolve_error = ResolveTokenError_BadTable;
5982 init_generic_context_from_args (&context, type_args, method_args);
5983 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5984 mono_error_cleanup (&error);
5988 if ((index <= 0) || (index > image->tables [table].rows)) {
5989 *resolve_error = ResolveTokenError_OutOfRange;
5992 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5993 *resolve_error = ResolveTokenError_BadTable;
5997 init_generic_context_from_args (&context, type_args, method_args);
5998 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5999 mono_error_set_pending_exception (&error);
6005 ICALL_EXPORT MonoObject*
6006 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6010 int table = mono_metadata_token_table (token);
6012 *error = ResolveTokenError_Other;
6015 case MONO_TABLE_TYPEDEF:
6016 case MONO_TABLE_TYPEREF:
6017 case MONO_TABLE_TYPESPEC: {
6018 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6020 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6021 mono_error_set_pending_exception (&merror);
6028 case MONO_TABLE_METHOD:
6029 case MONO_TABLE_METHODSPEC: {
6030 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6032 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6033 mono_error_set_pending_exception (&merror);
6039 case MONO_TABLE_FIELD: {
6040 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6042 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6043 mono_error_set_pending_exception (&merror);
6049 case MONO_TABLE_MEMBERREF:
6050 if (mono_memberref_is_method (image, token)) {
6051 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6053 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6054 mono_error_set_pending_exception (&merror);
6061 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6063 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6064 mono_error_set_pending_exception (&merror);
6073 *error = ResolveTokenError_BadTable;
6079 ICALL_EXPORT MonoArray*
6080 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6083 int table = mono_metadata_token_table (token);
6084 int idx = mono_metadata_token_index (token);
6085 MonoTableInfo *tables = image->tables;
6090 *resolve_error = ResolveTokenError_OutOfRange;
6092 /* FIXME: Support other tables ? */
6093 if (table != MONO_TABLE_STANDALONESIG)
6096 if (image_is_dynamic (image))
6099 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6102 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6104 ptr = mono_metadata_blob_heap (image, sig);
6105 len = mono_metadata_decode_blob_size (ptr, &ptr);
6107 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6108 if (mono_error_set_pending_exception (&error))
6110 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6114 ICALL_EXPORT MonoBoolean
6115 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6121 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6127 check_for_invalid_type (MonoClass *klass, MonoError *error)
6132 mono_error_init (error);
6134 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6137 name = mono_type_get_full_name (klass);
6138 str = mono_string_new (mono_domain_get (), name);
6140 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6143 ICALL_EXPORT MonoReflectionType *
6144 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6147 MonoReflectionType *ret;
6148 MonoClass *klass, *aklass;
6150 klass = mono_class_from_mono_type (type->type);
6151 check_for_invalid_type (klass, &error);
6152 mono_error_set_pending_exception (&error);
6154 if (rank == 0) //single dimentional array
6155 aklass = mono_array_class_get (klass, 1);
6157 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6159 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6160 mono_error_set_pending_exception (&error);
6165 ICALL_EXPORT MonoReflectionType *
6166 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6169 MonoReflectionType *ret;
6172 klass = mono_class_from_mono_type (type->type);
6173 mono_class_init_checked (klass, &error);
6174 if (mono_error_set_pending_exception (&error))
6177 check_for_invalid_type (klass, &error);
6178 if (mono_error_set_pending_exception (&error))
6181 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6182 mono_error_set_pending_exception (&error);
6187 ICALL_EXPORT MonoReflectionType *
6188 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6191 MonoReflectionType *ret;
6192 MonoClass *klass, *pklass;
6194 klass = mono_class_from_mono_type (type->type);
6195 mono_class_init_checked (klass, &error);
6196 if (mono_error_set_pending_exception (&error))
6198 check_for_invalid_type (klass, &error);
6199 if (mono_error_set_pending_exception (&error))
6202 pklass = mono_ptr_class_get (type->type);
6204 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6205 mono_error_set_pending_exception (&error);
6210 ICALL_EXPORT MonoObject *
6211 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6212 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6215 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6216 MonoObject *delegate;
6218 MonoMethod *method = info->method;
6219 MonoMethodSignature *sig = mono_method_signature(method);
6221 mono_class_init_checked (delegate_class, &error);
6222 if (mono_error_set_pending_exception (&error))
6225 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6226 /* FIXME improve this exception message */
6227 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6229 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6230 mono_error_set_pending_exception (&error);
6234 if (mono_security_core_clr_enabled ()) {
6235 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6236 if (throwOnBindFailure)
6237 mono_error_set_pending_exception (&error);
6239 mono_error_cleanup (&error);
6244 if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
6245 if (!method->is_inflated) {
6246 mono_set_pending_exception(mono_get_exception_argument("method", " Cannot bind to the target method because its signature differs from that of the delegate type"));
6251 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6252 if (mono_error_set_pending_exception (&error))
6255 if (method_is_dynamic (method)) {
6256 /* Creating a trampoline would leak memory */
6257 func = mono_compile_method_checked (method, &error);
6258 if (mono_error_set_pending_exception (&error))
6261 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6262 method = mono_object_get_virtual_method (target, method);
6263 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6264 if (mono_error_set_pending_exception (&error))
6266 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6269 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6270 if (mono_error_set_pending_exception (&error))
6275 ICALL_EXPORT MonoMulticastDelegate *
6276 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6279 MonoMulticastDelegate *ret;
6281 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6283 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6284 if (mono_error_set_pending_exception (&error))
6287 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6292 ICALL_EXPORT MonoReflectionMethod*
6293 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6295 MonoReflectionMethod *ret = NULL;
6297 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6298 mono_error_set_pending_exception (&error);
6304 static inline gint32
6305 mono_array_get_byte_length (MonoArray *array)
6311 klass = array->obj.vtable->klass;
6313 if (array->bounds == NULL)
6314 length = array->max_length;
6317 for (i = 0; i < klass->rank; ++ i)
6318 length *= array->bounds [i].length;
6321 switch (klass->element_class->byval_arg.type) {
6324 case MONO_TYPE_BOOLEAN:
6328 case MONO_TYPE_CHAR:
6336 return length * sizeof (gpointer);
6347 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6349 return mono_array_get_byte_length (array);
6353 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6355 return mono_array_get (array, gint8, idx);
6359 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6361 mono_array_set (array, gint8, idx, value);
6364 ICALL_EXPORT MonoBoolean
6365 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6367 guint8 *src_buf, *dest_buf;
6370 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6374 g_assert (count >= 0);
6376 /* This is called directly from the class libraries without going through the managed wrapper */
6377 MONO_CHECK_ARG_NULL (src, FALSE);
6378 MONO_CHECK_ARG_NULL (dest, FALSE);
6380 /* watch out for integer overflow */
6381 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6384 src_buf = (guint8 *)src->vector + src_offset;
6385 dest_buf = (guint8 *)dest->vector + dest_offset;
6388 memcpy (dest_buf, src_buf, count);
6390 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6395 #ifndef DISABLE_REMOTING
6396 ICALL_EXPORT MonoObject *
6397 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6400 MonoDomain *domain = mono_object_domain (this_obj);
6402 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6403 MonoTransparentProxy *tp;
6407 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6408 if (mono_error_set_pending_exception (&error))
6411 tp = (MonoTransparentProxy*) res;
6413 MONO_OBJECT_SETREF (tp, rp, rp);
6414 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6415 klass = mono_class_from_mono_type (type);
6417 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6418 mono_class_setup_vtable (klass);
6419 if (mono_class_has_failure (klass)) {
6420 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6424 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6425 if (mono_error_set_pending_exception (&error))
6427 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6428 if (mono_error_set_pending_exception (&error))
6431 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6432 if (mono_error_set_pending_exception (&error))
6437 ICALL_EXPORT MonoReflectionType *
6438 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6441 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6442 mono_error_set_pending_exception (&error);
6448 /* System.Environment */
6451 ves_icall_System_Environment_get_UserName (void)
6453 /* using glib is more portable */
6454 return mono_string_new (mono_domain_get (), g_get_user_name ());
6458 ICALL_EXPORT MonoString *
6459 ves_icall_System_Environment_get_MachineName (void)
6461 #if defined (HOST_WIN32)
6466 len = MAX_COMPUTERNAME_LENGTH + 1;
6467 buf = g_new (gunichar2, len);
6470 if (GetComputerName (buf, (PDWORD) &len)) {
6472 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6473 mono_error_set_pending_exception (&error);
6478 #elif !defined(DISABLE_SOCKETS)
6482 #if defined _SC_HOST_NAME_MAX
6483 n = sysconf (_SC_HOST_NAME_MAX);
6487 buf = g_malloc (n+1);
6489 if (gethostname (buf, n) == 0){
6491 result = mono_string_new (mono_domain_get (), buf);
6498 return mono_string_new (mono_domain_get (), "mono");
6503 ves_icall_System_Environment_get_Platform (void)
6505 #if defined (TARGET_WIN32)
6508 #elif defined(__MACH__)
6511 // Notice that the value is hidden from user code, and only exposed
6512 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6513 // define and making assumptions based on Unix/128/4 values before there
6514 // was a MacOS define. Lots of code would assume that not-Unix meant
6515 // Windows, but in this case, it would be OSX.
6524 ICALL_EXPORT MonoString *
6525 ves_icall_System_Environment_get_NewLine (void)
6527 #if defined (HOST_WIN32)
6528 return mono_string_new (mono_domain_get (), "\r\n");
6530 return mono_string_new (mono_domain_get (), "\n");
6534 ICALL_EXPORT MonoBoolean
6535 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6537 #if SIZEOF_VOID_P == 8
6541 gboolean isWow64Process = FALSE;
6542 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6543 return (MonoBoolean)isWow64Process;
6545 #elif defined(HAVE_SYS_UTSNAME_H)
6546 struct utsname name;
6548 if (uname (&name) >= 0) {
6549 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6556 ICALL_EXPORT MonoStringHandle
6557 ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
6561 if (utf8_name == NULL)
6562 return NULL_HANDLE_STRING;
6564 value = g_getenv (utf8_name);
6567 return NULL_HANDLE_STRING;
6569 return mono_string_new_handle (mono_domain_get (), value, error);
6573 * There is no standard way to get at environ.
6576 #ifndef __MINGW32_VERSION
6577 #if defined(__APPLE__)
6578 #if defined (TARGET_OSX)
6579 /* Apple defines this in crt_externs.h but doesn't provide that header for
6580 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6581 * in fact exist on all implementations (so far)
6583 gchar ***_NSGetEnviron(void);
6584 #define environ (*_NSGetEnviron())
6586 static char *mono_environ[1] = { NULL };
6587 #define environ mono_environ
6588 #endif /* defined (TARGET_OSX) */
6596 ICALL_EXPORT MonoArray *
6597 ves_icall_System_Environment_GetCoomandLineArgs (void)
6600 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6601 mono_error_set_pending_exception (&error);
6605 ICALL_EXPORT MonoArray *
6606 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6618 env_strings = GetEnvironmentStrings();
6621 env_string = env_strings;
6622 while (*env_string != '\0') {
6623 /* weird case that MS seems to skip */
6624 if (*env_string != '=')
6626 while (*env_string != '\0')
6632 domain = mono_domain_get ();
6633 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6634 if (mono_error_set_pending_exception (&error))
6639 env_string = env_strings;
6640 while (*env_string != '\0') {
6641 /* weird case that MS seems to skip */
6642 if (*env_string != '=') {
6643 equal_str = wcschr(env_string, '=');
6644 g_assert(equal_str);
6646 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6647 if (mono_error_set_pending_exception (&error))
6650 mono_array_setref (names, n, str);
6653 while (*env_string != '\0')
6658 FreeEnvironmentStrings (env_strings);
6672 for (e = environ; *e != 0; ++ e)
6675 domain = mono_domain_get ();
6676 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6677 if (mono_error_set_pending_exception (&error))
6681 for (e = environ; *e != 0; ++ e) {
6682 parts = g_strsplit (*e, "=", 2);
6684 str = mono_string_new (domain, *parts);
6685 mono_array_setref (names, n, str);
6698 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6701 gunichar2 *utf16_name, *utf16_value;
6703 gchar *utf8_name, *utf8_value;
6708 utf16_name = mono_string_to_utf16 (name);
6709 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6710 SetEnvironmentVariable (utf16_name, NULL);
6711 g_free (utf16_name);
6715 utf16_value = mono_string_to_utf16 (value);
6717 SetEnvironmentVariable (utf16_name, utf16_value);
6719 g_free (utf16_name);
6720 g_free (utf16_value);
6722 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6723 if (mono_error_set_pending_exception (&error))
6726 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6727 g_unsetenv (utf8_name);
6732 utf8_value = mono_string_to_utf8_checked (value, &error);
6733 if (!mono_error_ok (&error)) {
6735 mono_error_set_pending_exception (&error);
6738 g_setenv (utf8_name, utf8_value, TRUE);
6741 g_free (utf8_value);
6746 ves_icall_System_Environment_Exit (int result)
6748 mono_environment_exitcode_set (result);
6750 /* FIXME: There are some cleanup hangs that should be worked out, but
6751 * if the program is going to exit, everything will be cleaned up when
6752 * NaCl exits anyway.
6754 #ifndef __native_client__
6755 if (!mono_runtime_try_shutdown ())
6756 mono_thread_exit ();
6758 /* Suspend all managed threads since the runtime is going away */
6759 mono_thread_suspend_all_other_threads ();
6761 mono_runtime_quit ();
6764 /* we may need to do some cleanup here... */
6768 ICALL_EXPORT MonoStringHandle
6769 ves_icall_System_Environment_GetGacPath (MonoError *error)
6771 return mono_string_new_handle (mono_domain_get (), mono_assembly_getrootdir (), error);
6774 ICALL_EXPORT MonoString*
6775 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6777 #if defined (HOST_WIN32)
6778 #ifndef CSIDL_FLAG_CREATE
6779 #define CSIDL_FLAG_CREATE 0x8000
6782 WCHAR path [MAX_PATH];
6783 /* Create directory if no existing */
6784 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6789 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6790 mono_error_set_pending_exception (&error);
6794 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6796 return mono_string_new (mono_domain_get (), "");
6799 ICALL_EXPORT MonoArray *
6800 ves_icall_System_Environment_GetLogicalDrives (void)
6803 gunichar2 buf [256], *ptr, *dname;
6805 guint initial_size = 127, size = 128;
6808 MonoString *drivestr;
6809 MonoDomain *domain = mono_domain_get ();
6815 while (size > initial_size) {
6816 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6817 if (size > initial_size) {
6820 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6821 initial_size = size;
6835 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
6836 if (mono_error_set_pending_exception (&error))
6843 while (*u16) { u16++; len ++; }
6844 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6845 if (mono_error_set_pending_exception (&error))
6848 mono_array_setref (result, ndrives++, drivestr);
6859 ICALL_EXPORT MonoString *
6860 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6863 gunichar2 volume_name [MAX_PATH + 1];
6865 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6867 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
6868 mono_error_set_pending_exception (&error);
6872 ICALL_EXPORT MonoStringHandle
6873 ves_icall_System_Environment_InternalGetHome (MonoError *error)
6875 return mono_string_new_handle (mono_domain_get (), g_get_home_dir (), error);
6878 static const char *encodings [] = {
6880 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6881 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6882 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6884 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6885 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6886 "x_unicode_2_0_utf_7",
6888 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6889 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6891 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6894 "unicodefffe", "utf_16be",
6901 * Returns the internal codepage, if the value of "int_code_page" is
6902 * 1 at entry, and we can not compute a suitable code page number,
6903 * returns the code page as a string
6905 ICALL_EXPORT MonoString*
6906 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6911 char *codepage = NULL;
6913 int want_name = *int_code_page;
6916 *int_code_page = -1;
6918 g_get_charset (&cset);
6919 c = codepage = strdup (cset);
6920 for (c = codepage; *c; c++){
6921 if (isascii (*c) && isalpha (*c))
6926 /* g_print ("charset: %s\n", cset); */
6928 /* handle some common aliases */
6931 for (i = 0; p != 0; ){
6934 p = encodings [++i];
6937 if (strcmp (p, codepage) == 0){
6938 *int_code_page = code;
6941 p = encodings [++i];
6944 if (strstr (codepage, "utf_8") != NULL)
6945 *int_code_page |= 0x10000000;
6948 if (want_name && *int_code_page == -1)
6949 return mono_string_new (mono_domain_get (), cset);
6954 ICALL_EXPORT MonoBoolean
6955 ves_icall_System_Environment_get_HasShutdownStarted (void)
6957 if (mono_runtime_is_shutting_down ())
6960 if (mono_domain_is_unloading (mono_domain_get ()))
6967 ves_icall_System_Environment_BroadcastSettingChange (void)
6970 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6976 ves_icall_System_Environment_get_TickCount (void)
6978 /* this will overflow after ~24 days */
6979 return (gint32) (mono_msec_boottime () & 0xffffffff);
6983 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6988 #ifndef DISABLE_REMOTING
6989 ICALL_EXPORT MonoBoolean
6990 ves_icall_IsTransparentProxy (MonoObject *proxy)
6995 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7001 ICALL_EXPORT MonoReflectionMethod *
7002 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7003 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7005 MonoReflectionMethod *ret = NULL;
7010 MonoMethod **vtable;
7011 MonoMethod *res = NULL;
7013 MONO_CHECK_ARG_NULL (rtype, NULL);
7014 MONO_CHECK_ARG_NULL (rmethod, NULL);
7016 method = rmethod->method;
7017 klass = mono_class_from_mono_type (rtype->type);
7018 mono_class_init_checked (klass, &error);
7019 if (mono_error_set_pending_exception (&error))
7022 if (MONO_CLASS_IS_INTERFACE (klass))
7025 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7028 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7029 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7035 mono_class_setup_vtable (klass);
7036 vtable = klass->vtable;
7038 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7039 gboolean variance_used = FALSE;
7040 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7041 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7043 res = vtable [offs + method->slot];
7045 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7048 if (method->slot != -1)
7049 res = vtable [method->slot];
7055 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7056 mono_error_set_pending_exception (&error);
7061 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7067 klass = mono_class_from_mono_type (type->type);
7068 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7069 if (!is_ok (&error)) {
7070 mono_error_set_pending_exception (&error);
7074 mono_vtable_set_is_remote (vtable, enable);
7077 #else /* DISABLE_REMOTING */
7080 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7082 g_assert_not_reached ();
7087 ICALL_EXPORT MonoObject *
7088 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7095 domain = mono_object_domain (type);
7096 klass = mono_class_from_mono_type (type->type);
7097 mono_class_init_checked (klass, &error);
7098 if (mono_error_set_pending_exception (&error))
7101 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7102 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7106 if (klass->rank >= 1) {
7107 g_assert (klass->rank == 1);
7108 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7109 mono_error_set_pending_exception (&error);
7112 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7113 if (!is_ok (&error)) {
7114 mono_error_set_pending_exception (&error);
7117 /* Bypass remoting object creation check */
7118 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7119 mono_error_set_pending_exception (&error);
7125 ICALL_EXPORT MonoStringHandle
7126 ves_icall_System_IO_get_temp_path (MonoError *error)
7128 return mono_string_new_handle (mono_domain_get (), g_get_tmp_dir (), error);
7131 #ifndef PLATFORM_NO_DRIVEINFO
7132 ICALL_EXPORT MonoBoolean
7133 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7134 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7138 ULARGE_INTEGER wapi_free_bytes_avail;
7139 ULARGE_INTEGER wapi_total_number_of_bytes;
7140 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7142 *error = ERROR_SUCCESS;
7143 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7144 &wapi_total_number_of_free_bytes);
7147 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7148 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7149 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7151 *free_bytes_avail = 0;
7152 *total_number_of_bytes = 0;
7153 *total_number_of_free_bytes = 0;
7154 *error = GetLastError ();
7160 ICALL_EXPORT guint32
7161 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7163 return GetDriveType (mono_string_chars (root_path_name));
7167 ICALL_EXPORT gpointer
7168 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7171 gpointer result = mono_compile_method_checked (method, &error);
7172 mono_error_set_pending_exception (&error);
7176 ICALL_EXPORT MonoString *
7177 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7182 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7184 #if defined (HOST_WIN32)
7185 /* Avoid mixing '/' and '\\' */
7188 for (i = strlen (path) - 1; i >= 0; i--)
7189 if (path [i] == '/')
7193 mcpath = mono_string_new (mono_domain_get (), path);
7199 /* this is an icall */
7201 get_bundled_app_config (void)
7204 const gchar *app_config;
7207 gchar *config_file_name, *config_file_path;
7208 gsize len, config_file_path_length, config_ext_length;
7211 domain = mono_domain_get ();
7212 file = domain->setup->configuration_file;
7213 if (!file || file->length == 0)
7216 // Retrieve config file and remove the extension
7217 config_file_name = mono_string_to_utf8_checked (file, &error);
7218 if (mono_error_set_pending_exception (&error))
7220 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7221 if (!config_file_path)
7222 config_file_path = config_file_name;
7224 config_file_path_length = strlen (config_file_path);
7225 config_ext_length = strlen (".config");
7226 if (config_file_path_length <= config_ext_length)
7229 len = config_file_path_length - config_ext_length;
7230 module = (gchar *)g_malloc0 (len + 1);
7231 memcpy (module, config_file_path, len);
7232 // Get the config file from the module name
7233 app_config = mono_config_string_for_assembly_file (module);
7236 if (config_file_name != config_file_path)
7237 g_free (config_file_name);
7238 g_free (config_file_path);
7243 return mono_string_new (mono_domain_get (), app_config);
7246 /* this is an icall */
7247 static MonoStringHandle
7248 get_bundled_machine_config (MonoError *error)
7250 const gchar *machine_config;
7252 machine_config = mono_get_machine_config ();
7254 if (!machine_config)
7255 return NULL_HANDLE_STRING;
7257 return mono_string_new_handle (mono_domain_get (), machine_config, error);
7260 ICALL_EXPORT MonoString *
7261 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7266 path = g_path_get_dirname (mono_get_config_dir ());
7268 #if defined (HOST_WIN32)
7269 /* Avoid mixing '/' and '\\' */
7272 for (i = strlen (path) - 1; i >= 0; i--)
7273 if (path [i] == '/')
7277 ipath = mono_string_new (mono_domain_get (), path);
7283 ICALL_EXPORT gboolean
7284 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7286 MonoPEResourceDataEntry *entry;
7289 if (!assembly || !result || !size)
7294 image = assembly->assembly->image;
7295 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7299 *result = mono_image_rva_map (image, entry->rde_data_offset);
7304 *size = entry->rde_size;
7309 ICALL_EXPORT MonoBoolean
7310 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7312 return mono_is_debugger_attached ();
7315 ICALL_EXPORT MonoBoolean
7316 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7318 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7319 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7325 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7327 if (mono_get_runtime_callbacks ()->debug_log)
7328 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7332 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7334 #if defined (HOST_WIN32)
7335 OutputDebugString (mono_string_chars (message));
7337 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7341 /* Only used for value types */
7342 ICALL_EXPORT MonoObject *
7343 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7350 domain = mono_object_domain (type);
7351 klass = mono_class_from_mono_type (type->type);
7352 mono_class_init_checked (klass, &error);
7353 if (mono_error_set_pending_exception (&error))
7356 if (mono_class_is_nullable (klass))
7357 /* No arguments -> null */
7360 result = mono_object_new_checked (domain, klass, &error);
7361 mono_error_set_pending_exception (&error);
7365 ICALL_EXPORT MonoReflectionMethod *
7366 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7368 MonoReflectionMethod *ret = NULL;
7371 MonoClass *klass, *parent;
7372 MonoGenericContext *generic_inst = NULL;
7373 MonoMethod *method = m->method;
7374 MonoMethod *result = NULL;
7377 if (method->klass == NULL)
7380 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7381 MONO_CLASS_IS_INTERFACE (method->klass) ||
7382 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7385 slot = mono_method_get_vtable_slot (method);
7389 klass = method->klass;
7390 if (klass->generic_class) {
7391 generic_inst = mono_class_get_context (klass);
7392 klass = klass->generic_class->container_class;
7396 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7397 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7398 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7399 or klass is the generic container class and generic_inst is the instantiation.
7401 when we go to the parent, if the parent is an open constructed type, we need to
7402 replace the type parameters by the definitions from the generic_inst, and then take it
7403 apart again into the klass and the generic_inst.
7405 For cases like this:
7406 class C<T> : B<T, int> {
7407 public override void Foo () { ... }
7409 class B<U,V> : A<HashMap<U,V>> {
7410 public override void Foo () { ... }
7413 public virtual void Foo () { ... }
7416 if at each iteration the parent isn't open, we can skip inflating it. if at some
7417 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7420 MonoGenericContext *parent_inst = NULL;
7421 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7422 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7423 if (!mono_error_ok (&error)) {
7424 mono_error_set_pending_exception (&error);
7428 if (parent->generic_class) {
7429 parent_inst = mono_class_get_context (parent);
7430 parent = parent->generic_class->container_class;
7433 mono_class_setup_vtable (parent);
7434 if (parent->vtable_size <= slot)
7437 generic_inst = parent_inst;
7440 klass = klass->parent;
7443 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7444 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7445 if (!mono_error_ok (&error)) {
7446 mono_error_set_pending_exception (&error);
7450 generic_inst = NULL;
7452 if (klass->generic_class) {
7453 generic_inst = mono_class_get_context (klass);
7454 klass = klass->generic_class->container_class;
7460 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7461 if (!mono_error_ok (&error)) {
7462 mono_error_set_pending_exception (&error);
7467 if (klass == method->klass)
7470 /*This is possible if definition == FALSE.
7471 * Do it here to be really sure we don't read invalid memory.
7473 if (slot >= klass->vtable_size)
7476 mono_class_setup_vtable (klass);
7478 result = klass->vtable [slot];
7479 if (result == NULL) {
7480 /* It is an abstract method */
7481 gpointer iter = NULL;
7482 while ((result = mono_class_get_methods (klass, &iter)))
7483 if (result->slot == slot)
7490 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7491 mono_error_set_pending_exception (&error);
7495 ICALL_EXPORT MonoString*
7496 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7498 MonoMethod *method = m->method;
7500 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7505 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7507 iter->sig = *(MonoMethodSignature**)argsp;
7509 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7510 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7513 /* FIXME: it's not documented what start is exactly... */
7517 iter->args = argsp + sizeof (gpointer);
7519 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7521 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7524 ICALL_EXPORT MonoTypedRef
7525 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7527 guint32 i, arg_size;
7531 i = iter->sig->sentinelpos + iter->next_arg;
7533 g_assert (i < iter->sig->param_count);
7535 res.type = iter->sig->params [i];
7536 res.klass = mono_class_from_mono_type (res.type);
7537 arg_size = mono_type_stack_size (res.type, &align);
7538 #if defined(__arm__) || defined(__mips__)
7539 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7541 res.value = iter->args;
7542 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7543 /* Values are stored as 8 byte register sized objects, but 'value'
7544 * is dereferenced as a pointer in other routines.
7546 res.value = (char*)res.value + 4;
7548 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7549 if (arg_size <= sizeof (gpointer)) {
7551 int padding = arg_size - mono_type_size (res.type, &dummy);
7552 res.value = (guint8*)res.value + padding;
7555 iter->args = (char*)iter->args + arg_size;
7558 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7563 ICALL_EXPORT MonoTypedRef
7564 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7566 guint32 i, arg_size;
7570 i = iter->sig->sentinelpos + iter->next_arg;
7572 g_assert (i < iter->sig->param_count);
7574 while (i < iter->sig->param_count) {
7575 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7577 res.type = iter->sig->params [i];
7578 res.klass = mono_class_from_mono_type (res.type);
7579 /* FIXME: endianess issue... */
7580 arg_size = mono_type_stack_size (res.type, &align);
7581 #if defined(__arm__) || defined(__mips__)
7582 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7584 res.value = iter->args;
7585 iter->args = (char*)iter->args + arg_size;
7587 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7590 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7598 ICALL_EXPORT MonoType*
7599 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7603 i = iter->sig->sentinelpos + iter->next_arg;
7605 g_assert (i < iter->sig->param_count);
7607 return iter->sig->params [i];
7610 ICALL_EXPORT MonoObject*
7611 mono_TypedReference_ToObject (MonoTypedRef* tref)
7614 MonoObject *result = NULL;
7615 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7616 MonoObject** objp = (MonoObject **)tref->value;
7620 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7621 mono_error_set_pending_exception (&error);
7625 ICALL_EXPORT MonoTypedRef
7626 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7629 MonoReflectionField *f;
7631 MonoType *ftype = NULL;
7635 memset (&res, 0, sizeof (res));
7638 g_assert (mono_array_length (fields) > 0);
7640 klass = target->vtable->klass;
7642 for (i = 0; i < mono_array_length (fields); ++i) {
7643 f = mono_array_get (fields, MonoReflectionField*, i);
7645 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7648 if (f->field->parent != klass) {
7649 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7653 p = (guint8*)target + f->field->offset;
7655 p += f->field->offset - sizeof (MonoObject);
7656 klass = mono_class_from_mono_type (f->field->type);
7657 ftype = f->field->type;
7661 res.klass = mono_class_from_mono_type (ftype);
7668 prelink_method (MonoMethod *method, MonoError *error)
7670 const char *exc_class, *exc_arg;
7672 mono_error_init (error);
7673 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7675 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7677 mono_error_set_exception_instance (error,
7678 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7681 /* create the wrapper, too? */
7685 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7689 prelink_method (method->method, &error);
7690 mono_error_set_pending_exception (&error);
7694 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7697 MonoClass *klass = mono_class_from_mono_type (type->type);
7699 gpointer iter = NULL;
7701 mono_class_init_checked (klass, &error);
7702 if (mono_error_set_pending_exception (&error))
7705 while ((m = mono_class_get_methods (klass, &iter))) {
7706 prelink_method (m, &error);
7707 if (mono_error_set_pending_exception (&error))
7712 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7714 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7715 gint32 const **exponents,
7716 gunichar2 const **digitLowerTable,
7717 gunichar2 const **digitUpperTable,
7718 gint64 const **tenPowersList,
7719 gint32 const **decHexDigits)
7721 *mantissas = Formatter_MantissaBitsTable;
7722 *exponents = Formatter_TensExponentTable;
7723 *digitLowerTable = Formatter_DigitLowerTable;
7724 *digitUpperTable = Formatter_DigitUpperTable;
7725 *tenPowersList = Formatter_TenPowersList;
7726 *decHexDigits = Formatter_DecHexDigits;
7730 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7731 * and avoid useless allocations.
7734 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7736 MonoReflectionType *rt;
7740 mono_error_init (error);
7741 for (i = 0; i < type->num_mods; ++i) {
7742 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7747 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7748 return_val_if_nok (error, NULL);
7750 for (i = 0; i < type->num_mods; ++i) {
7751 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7752 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7753 return_val_if_nok (error, NULL);
7755 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7756 return_val_if_nok (error, NULL);
7758 mono_array_setref (res, count, rt);
7765 ICALL_EXPORT MonoArray*
7766 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7769 MonoType *type = param->ClassImpl->type;
7770 MonoClass *member_class = mono_object_class (param->MemberImpl);
7771 MonoMethod *method = NULL;
7774 MonoMethodSignature *sig;
7777 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7778 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7779 method = rmethod->method;
7780 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7781 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7782 if (!(method = prop->property->get))
7783 method = prop->property->set;
7786 char *type_name = mono_type_get_full_name (member_class);
7787 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7788 MonoException *ex = mono_get_exception_not_supported (msg);
7791 mono_set_pending_exception (ex);
7795 image = method->klass->image;
7796 pos = param->PositionImpl;
7797 sig = mono_method_signature (method);
7801 type = sig->params [pos];
7803 res = type_array_from_modifiers (image, type, optional, &error);
7804 mono_error_set_pending_exception (&error);
7809 get_property_type (MonoProperty *prop)
7811 MonoMethodSignature *sig;
7813 sig = mono_method_signature (prop->get);
7815 } else if (prop->set) {
7816 sig = mono_method_signature (prop->set);
7817 return sig->params [sig->param_count - 1];
7822 ICALL_EXPORT MonoArray*
7823 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7826 MonoType *type = get_property_type (property->property);
7827 MonoImage *image = property->klass->image;
7832 res = type_array_from_modifiers (image, type, optional, &error);
7833 mono_error_set_pending_exception (&error);
7838 *Construct a MonoType suited to be used to decode a constant blob object.
7840 * @type is the target type which will be constructed
7841 * @blob_type is the blob type, for example, that comes from the constant table
7842 * @real_type is the expected constructed type.
7845 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7847 type->type = blob_type;
7848 type->data.klass = NULL;
7849 if (blob_type == MONO_TYPE_CLASS)
7850 type->data.klass = mono_defaults.object_class;
7851 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7852 /* For enums, we need to use the base type */
7853 type->type = MONO_TYPE_VALUETYPE;
7854 type->data.klass = mono_class_from_mono_type (real_type);
7856 type->data.klass = mono_class_from_mono_type (real_type);
7859 ICALL_EXPORT MonoObject*
7860 property_info_get_default_value (MonoReflectionProperty *property)
7864 MonoProperty *prop = property->property;
7865 MonoType *type = get_property_type (prop);
7866 MonoDomain *domain = mono_object_domain (property);
7867 MonoTypeEnum def_type;
7868 const char *def_value;
7871 mono_class_init (prop->parent);
7873 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7874 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7878 def_value = mono_class_get_property_default_value (prop, &def_type);
7880 mono_type_from_blob_type (&blob_type, def_type, type);
7881 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7883 mono_error_set_pending_exception (&error);
7887 ICALL_EXPORT MonoBoolean
7888 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7891 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7892 MonoCustomAttrInfo *cinfo;
7895 mono_class_init_checked (attr_class, &error);
7896 if (mono_error_set_pending_exception (&error))
7899 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7900 if (!is_ok (&error)) {
7901 mono_error_set_pending_exception (&error);
7906 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7908 mono_custom_attrs_free (cinfo);
7912 ICALL_EXPORT MonoArray*
7913 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7915 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7920 mono_class_init_checked (attr_class, &error);
7921 if (mono_error_set_pending_exception (&error))
7925 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7926 if (!mono_error_ok (&error)) {
7927 mono_error_set_pending_exception (&error);
7934 ICALL_EXPORT MonoArray*
7935 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7939 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7940 mono_error_set_pending_exception (&error);
7945 ICALL_EXPORT MonoString*
7946 ves_icall_Mono_Runtime_GetDisplayName (void)
7949 MonoString *display_name;
7951 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7952 display_name = mono_string_new (mono_domain_get (), info);
7954 return display_name;
7957 ICALL_EXPORT MonoString*
7958 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7961 MonoString *message;
7965 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7966 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7969 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7971 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7972 if (mono_error_set_pending_exception (&error))
7979 ICALL_EXPORT gpointer
7980 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
7982 return GetCurrentProcess ();
7985 ICALL_EXPORT MonoBoolean
7986 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
7988 return GetExitCodeProcess (handle, (guint32*) exitcode);
7991 ICALL_EXPORT MonoBoolean
7992 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
7994 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
7995 return CloseHandle (handle);
7997 return CloseProcess (handle);
8001 ICALL_EXPORT MonoBoolean
8002 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8004 return TerminateProcess (handle, exitcode);
8008 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8011 return WaitForInputIdle (handle, milliseconds);
8013 /*TODO: Not implemented*/
8014 return WAIT_TIMEOUT;
8018 ICALL_EXPORT MonoBoolean
8019 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8021 return GetProcessWorkingSetSize (handle, min, max);
8024 ICALL_EXPORT MonoBoolean
8025 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8027 return SetProcessWorkingSetSize (handle, min, max);
8030 ICALL_EXPORT MonoBoolean
8031 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8033 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8037 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8039 return mono_process_current_pid ();
8043 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8045 return GetPriorityClass (handle);
8048 ICALL_EXPORT MonoBoolean
8049 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8051 return SetPriorityClass (handle, priorityClass);
8054 #ifndef DISABLE_ICALL_TABLES
8056 #define ICALL_TYPE(id,name,first)
8057 #define ICALL(id,name,func) Icall_ ## id,
8058 #define HANDLES(inner) inner
8061 #include "metadata/icall-def.h"
8067 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8068 #define ICALL(id,name,func)
8070 #define HANDLES(inner) inner
8072 #include "metadata/icall-def.h"
8078 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8079 #define ICALL(id,name,func)
8081 #define HANDLES(inner) inner
8083 guint16 first_icall;
8086 static const IcallTypeDesc
8087 icall_type_descs [] = {
8088 #include "metadata/icall-def.h"
8092 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8095 #define HANDLES(inner) inner
8097 #define ICALL_TYPE(id,name,first)
8100 #ifdef HAVE_ARRAY_ELEM_INIT
8101 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8102 #define MSGSTRFIELD1(line) str##line
8104 static const struct msgstrtn_t {
8105 #define ICALL(id,name,func)
8107 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8108 #include "metadata/icall-def.h"
8110 } icall_type_names_str = {
8111 #define ICALL_TYPE(id,name,first) (name),
8112 #include "metadata/icall-def.h"
8115 static const guint16 icall_type_names_idx [] = {
8116 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8117 #include "metadata/icall-def.h"
8120 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8122 static const struct msgstr_t {
8124 #define ICALL_TYPE(id,name,first)
8125 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8126 #include "metadata/icall-def.h"
8128 } icall_names_str = {
8129 #define ICALL(id,name,func) (name),
8130 #include "metadata/icall-def.h"
8133 static const guint16 icall_names_idx [] = {
8134 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8135 #include "metadata/icall-def.h"
8138 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8144 #define ICALL_TYPE(id,name,first) name,
8145 #define ICALL(id,name,func)
8146 static const char* const
8147 icall_type_names [] = {
8148 #include "metadata/icall-def.h"
8152 #define icall_type_name_get(id) (icall_type_names [(id)])
8156 #define ICALL_TYPE(id,name,first)
8157 #define ICALL(id,name,func) name,
8158 static const char* const
8160 #include "metadata/icall-def.h"
8163 #define icall_name_get(id) icall_names [(id)]
8165 #endif /* !HAVE_ARRAY_ELEM_INIT */
8168 #define HANDLES(inner) inner
8171 #define ICALL_TYPE(id,name,first)
8172 #define ICALL(id,name,func) func,
8173 static const gconstpointer
8174 icall_functions [] = {
8175 #include "metadata/icall-def.h"
8179 #ifdef ENABLE_ICALL_SYMBOL_MAP
8181 #define HANDLES(inner) inner
8184 #define ICALL_TYPE(id,name,first)
8185 #define ICALL(id,name,func) #func,
8186 static const gconstpointer
8187 icall_symbols [] = {
8188 #include "metadata/icall-def.h"
8195 #define ICALL_TYPE(id,name,first)
8196 #define ICALL(id,name,func) 0,
8198 #define HANDLES(inner) 1,
8200 icall_uses_handles [] = {
8201 #include "metadata/icall-def.h"
8206 #endif /* DISABLE_ICALL_TABLES */
8208 static mono_mutex_t icall_mutex;
8209 static GHashTable *icall_hash = NULL;
8210 static GHashTable *jit_icall_hash_name = NULL;
8211 static GHashTable *jit_icall_hash_addr = NULL;
8214 mono_icall_init (void)
8216 #ifndef DISABLE_ICALL_TABLES
8219 /* check that tables are sorted: disable in release */
8222 const char *prev_class = NULL;
8223 const char *prev_method;
8225 for (i = 0; i < Icall_type_num; ++i) {
8226 const IcallTypeDesc *desc;
8229 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8230 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8231 prev_class = icall_type_name_get (i);
8232 desc = &icall_type_descs [i];
8233 num_icalls = icall_desc_num_icalls (desc);
8234 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8235 for (j = 0; j < num_icalls; ++j) {
8236 const char *methodn = icall_name_get (desc->first_icall + j);
8237 if (prev_method && strcmp (prev_method, methodn) >= 0)
8238 g_print ("method %s should come before method %s\n", methodn, prev_method);
8239 prev_method = methodn;
8245 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8246 mono_os_mutex_init (&icall_mutex);
8250 mono_icall_lock (void)
8252 mono_locks_os_acquire (&icall_mutex, IcallLock);
8256 mono_icall_unlock (void)
8258 mono_locks_os_release (&icall_mutex, IcallLock);
8262 mono_icall_cleanup (void)
8264 g_hash_table_destroy (icall_hash);
8265 g_hash_table_destroy (jit_icall_hash_name);
8266 g_hash_table_destroy (jit_icall_hash_addr);
8267 mono_os_mutex_destroy (&icall_mutex);
8271 * mono_add_internal_call:
8272 * @name: method specification to surface to the managed world
8273 * @method: pointer to a C method to invoke when the method is called
8275 * This method surfaces the C function pointed by @method as a method
8276 * that has been surfaced in managed code with the method specified in
8277 * @name as an internal call.
8279 * Internal calls are surfaced to all app domains loaded and they are
8280 * accessibly by a type with the specified name.
8282 * You must provide a fully qualified type name, that is namespaces
8283 * and type name, followed by a colon and the method name, with an
8284 * optional signature to bind.
8286 * For example, the following are all valid declarations:
8288 * "MyApp.Services.ScriptService:Accelerate"
8289 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8291 * You use method parameters in cases where there might be more than
8292 * one surface method to managed code. That way you can register different
8293 * internal calls for different method overloads.
8295 * The internal calls are invoked with no marshalling. This means that .NET
8296 * types like System.String are exposed as `MonoString *` parameters. This is
8297 * different than the way that strings are surfaced in P/Invoke.
8299 * For more information on how the parameters are marshalled, see the
8300 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8303 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8304 * reference for more information on the format of method descriptions.
8307 mono_add_internal_call (const char *name, gconstpointer method)
8311 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8313 mono_icall_unlock ();
8316 #ifndef DISABLE_ICALL_TABLES
8318 #ifdef HAVE_ARRAY_ELEM_INIT
8320 compare_method_imap (const void *key, const void *elem)
8322 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8323 return strcmp (key, method_name);
8327 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8329 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);
8332 return (nameslot - &icall_names_idx [0]);
8336 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8338 gsize slotnum = find_slot_icall (imap, name);
8341 return (gboolean)icall_uses_handles [slotnum];
8345 find_method_icall (const IcallTypeDesc *imap, const char *name)
8347 gsize slotnum = find_slot_icall (imap, name);
8350 return (gpointer)icall_functions [slotnum];
8354 compare_class_imap (const void *key, const void *elem)
8356 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8357 return strcmp (key, class_name);
8360 static const IcallTypeDesc*
8361 find_class_icalls (const char *name)
8363 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);
8366 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8369 #else /* HAVE_ARRAY_ELEM_INIT */
8372 compare_method_imap (const void *key, const void *elem)
8374 const char** method_name = (const char**)elem;
8375 return strcmp (key, *method_name);
8379 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8381 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8384 return nameslot - icall_names;
8388 find_method_icall (const IcallTypeDesc *imap, const char *name)
8390 gsize slotnum = find_slot_icall (imap, name);
8393 return (gpointer)icall_functions [slotnum];
8397 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8399 gsize slotnum = find_slot_icall (imap, name);
8402 return (gboolean)icall_uses_handles [slotnum];
8406 compare_class_imap (const void *key, const void *elem)
8408 const char** class_name = (const char**)elem;
8409 return strcmp (key, *class_name);
8412 static const IcallTypeDesc*
8413 find_class_icalls (const char *name)
8415 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8418 return &icall_type_descs [nameslot - icall_type_names];
8421 #endif /* HAVE_ARRAY_ELEM_INIT */
8423 #endif /* DISABLE_ICALL_TABLES */
8426 * we should probably export this as an helper (handle nested types).
8427 * Returns the number of chars written in buf.
8430 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8432 int nspacelen, cnamelen;
8433 nspacelen = strlen (klass->name_space);
8434 cnamelen = strlen (klass->name);
8435 if (nspacelen + cnamelen + 2 > bufsize)
8438 memcpy (buf, klass->name_space, nspacelen);
8439 buf [nspacelen ++] = '.';
8441 memcpy (buf + nspacelen, klass->name, cnamelen);
8442 buf [nspacelen + cnamelen] = 0;
8443 return nspacelen + cnamelen;
8446 #ifdef DISABLE_ICALL_TABLES
8448 no_icall_table (void)
8450 g_assert_not_reached ();
8455 * mono_lookup_internal_call_full:
8456 * @method: the method to look up
8457 * @uses_handles: out argument if method needs handles around managed objects.
8459 * Returns a pointer to the icall code for the given method. If
8460 * uses_handles is not NULL, it will be set to TRUE if the method
8461 * needs managed objects wrapped using the infrastructure in handle.h
8463 * If the method is not found, warns and returns NULL.
8466 mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
8471 int typelen = 0, mlen, siglen;
8473 #ifndef DISABLE_ICALL_TABLES
8474 const IcallTypeDesc *imap = NULL;
8477 g_assert (method != NULL);
8479 if (method->is_inflated)
8480 method = ((MonoMethodInflated *) method)->declaring;
8482 if (method->klass->nested_in) {
8483 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8487 mname [pos++] = '/';
8490 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8496 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8501 #ifndef DISABLE_ICALL_TABLES
8502 imap = find_class_icalls (mname);
8505 mname [typelen] = ':';
8506 mname [typelen + 1] = ':';
8508 mlen = strlen (method->name);
8509 memcpy (mname + typelen + 2, method->name, mlen);
8510 sigstart = mname + typelen + 2 + mlen;
8513 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8514 siglen = strlen (tmpsig);
8515 if (typelen + mlen + siglen + 6 > sizeof (mname))
8518 memcpy (sigstart + 1, tmpsig, siglen);
8519 sigstart [siglen + 1] = ')';
8520 sigstart [siglen + 2] = 0;
8525 res = g_hash_table_lookup (icall_hash, mname);
8528 *uses_handles = FALSE;
8529 mono_icall_unlock ();;
8532 /* try without signature */
8534 res = g_hash_table_lookup (icall_hash, mname);
8537 *uses_handles = FALSE;
8538 mono_icall_unlock ();
8542 #ifdef DISABLE_ICALL_TABLES
8543 mono_icall_unlock ();
8544 /* Fail only when the result is actually used */
8545 /* mono_marshal_get_native_wrapper () depends on this */
8546 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8547 return ves_icall_System_String_ctor_RedirectToCreateString;
8549 return no_icall_table;
8551 /* it wasn't found in the static call tables */
8554 *uses_handles = FALSE;
8555 mono_icall_unlock ();
8558 res = find_method_icall (imap, sigstart - mlen);
8561 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8562 mono_icall_unlock ();
8565 /* try _with_ signature */
8567 res = find_method_icall (imap, sigstart - mlen);
8570 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8571 mono_icall_unlock ();
8575 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8576 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8577 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8578 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8579 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");
8580 g_print ("If you see other errors or faults after this message they are probably related\n");
8581 g_print ("and you need to fix your mono install first.\n");
8583 mono_icall_unlock ();
8590 mono_lookup_internal_call (MonoMethod *method)
8592 return mono_lookup_internal_call_full (method, NULL);
8595 #ifdef ENABLE_ICALL_SYMBOL_MAP
8597 func_cmp (gconstpointer key, gconstpointer p)
8599 return (gsize)key - (gsize)*(gsize*)p;
8604 * mono_lookup_icall_symbol:
8606 * Given the icall METHOD, returns its C symbol.
8609 mono_lookup_icall_symbol (MonoMethod *m)
8611 #ifdef DISABLE_ICALL_TABLES
8612 g_assert_not_reached ();
8615 #ifdef ENABLE_ICALL_SYMBOL_MAP
8619 static gconstpointer *functions_sorted;
8620 static const char**symbols_sorted;
8621 static gboolean inited;
8626 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8627 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8628 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8629 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8630 /* Bubble sort the two arrays */
8634 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8635 if (functions_sorted [i] > functions_sorted [i + 1]) {
8638 tmp = functions_sorted [i];
8639 functions_sorted [i] = functions_sorted [i + 1];
8640 functions_sorted [i + 1] = tmp;
8641 tmp = symbols_sorted [i];
8642 symbols_sorted [i] = symbols_sorted [i + 1];
8643 symbols_sorted [i + 1] = tmp;
8650 func = mono_lookup_internal_call (m);
8653 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8657 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8659 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8660 g_assert_not_reached ();
8667 type_from_typename (char *type_name)
8669 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8671 if (!strcmp (type_name, "int"))
8672 klass = mono_defaults.int_class;
8673 else if (!strcmp (type_name, "ptr"))
8674 klass = mono_defaults.int_class;
8675 else if (!strcmp (type_name, "void"))
8676 klass = mono_defaults.void_class;
8677 else if (!strcmp (type_name, "int32"))
8678 klass = mono_defaults.int32_class;
8679 else if (!strcmp (type_name, "uint32"))
8680 klass = mono_defaults.uint32_class;
8681 else if (!strcmp (type_name, "int8"))
8682 klass = mono_defaults.sbyte_class;
8683 else if (!strcmp (type_name, "uint8"))
8684 klass = mono_defaults.byte_class;
8685 else if (!strcmp (type_name, "int16"))
8686 klass = mono_defaults.int16_class;
8687 else if (!strcmp (type_name, "uint16"))
8688 klass = mono_defaults.uint16_class;
8689 else if (!strcmp (type_name, "long"))
8690 klass = mono_defaults.int64_class;
8691 else if (!strcmp (type_name, "ulong"))
8692 klass = mono_defaults.uint64_class;
8693 else if (!strcmp (type_name, "float"))
8694 klass = mono_defaults.single_class;
8695 else if (!strcmp (type_name, "double"))
8696 klass = mono_defaults.double_class;
8697 else if (!strcmp (type_name, "object"))
8698 klass = mono_defaults.object_class;
8699 else if (!strcmp (type_name, "obj"))
8700 klass = mono_defaults.object_class;
8701 else if (!strcmp (type_name, "string"))
8702 klass = mono_defaults.string_class;
8703 else if (!strcmp (type_name, "bool"))
8704 klass = mono_defaults.boolean_class;
8705 else if (!strcmp (type_name, "boolean"))
8706 klass = mono_defaults.boolean_class;
8708 g_error ("%s", type_name);
8709 g_assert_not_reached ();
8711 return &klass->byval_arg;
8715 * LOCKING: Take the corlib image lock.
8717 MonoMethodSignature*
8718 mono_create_icall_signature (const char *sigstr)
8723 MonoMethodSignature *res, *res2;
8724 MonoImage *corlib = mono_defaults.corlib;
8726 mono_image_lock (corlib);
8727 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8728 mono_image_unlock (corlib);
8733 parts = g_strsplit (sigstr, " ", 256);
8742 res = mono_metadata_signature_alloc (corlib, len - 1);
8747 * Under windows, the default pinvoke calling convention is STDCALL but
8750 res->call_convention = MONO_CALL_C;
8753 res->ret = type_from_typename (parts [0]);
8754 for (i = 1; i < len; ++i) {
8755 res->params [i - 1] = type_from_typename (parts [i]);
8760 mono_image_lock (corlib);
8761 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8763 res = res2; /*Value is allocated in the image pool*/
8765 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8766 mono_image_unlock (corlib);
8772 mono_find_jit_icall_by_name (const char *name)
8774 MonoJitICallInfo *info;
8775 g_assert (jit_icall_hash_name);
8778 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8779 mono_icall_unlock ();
8784 mono_find_jit_icall_by_addr (gconstpointer addr)
8786 MonoJitICallInfo *info;
8787 g_assert (jit_icall_hash_addr);
8790 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8791 mono_icall_unlock ();
8797 * mono_get_jit_icall_info:
8799 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8800 * caller should access it while holding the icall lock.
8803 mono_get_jit_icall_info (void)
8805 return jit_icall_hash_name;
8809 * mono_lookup_jit_icall_symbol:
8811 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8814 mono_lookup_jit_icall_symbol (const char *name)
8816 MonoJitICallInfo *info;
8817 const char *res = NULL;
8820 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8822 res = info->c_symbol;
8823 mono_icall_unlock ();
8828 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8831 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8832 mono_icall_unlock ();
8836 * 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
8837 * icalls without wrappers in some cases.
8840 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8842 MonoJitICallInfo *info;
8849 if (!jit_icall_hash_name) {
8850 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8851 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8854 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8855 g_warning ("jit icall already defined \"%s\"\n", name);
8856 g_assert_not_reached ();
8859 info = g_new0 (MonoJitICallInfo, 1);
8864 info->c_symbol = c_symbol;
8865 info->no_raise = no_raise;
8868 info->wrapper = func;
8870 info->wrapper = NULL;
8873 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8874 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8876 mono_icall_unlock ();
8881 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8883 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);