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 */
987 current = (guint8 *)&stack_addr;
988 if (current > stack_addr) {
989 if ((current - stack_addr) < min_size)
992 if (current - (stack_addr - stack_size) < min_size)
998 ICALL_EXPORT MonoObject *
999 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
1002 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
1003 mono_error_set_pending_exception (&error);
1009 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1013 MonoObject **values = NULL;
1016 gint32 result = (int)(gsize)mono_defaults.int32_class;
1017 MonoClassField* field;
1020 klass = mono_object_class (this_obj);
1022 if (mono_class_num_fields (klass) == 0)
1026 * Compute the starting value of the hashcode for fields of primitive
1027 * types, and return the remaining fields in an array to the managed side.
1028 * This way, we can avoid costly reflection operations in managed code.
1031 while ((field = mono_class_get_fields (klass, &iter))) {
1032 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1034 if (mono_field_is_deleted (field))
1036 /* FIXME: Add more types */
1037 switch (field->type->type) {
1039 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1041 case MONO_TYPE_STRING: {
1043 s = *(MonoString**)((guint8*)this_obj + field->offset);
1045 result ^= mono_string_hash (s);
1050 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1051 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1052 if (!is_ok (&error)) {
1053 mono_error_set_pending_exception (&error);
1056 values [count++] = o;
1062 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1063 if (mono_error_set_pending_exception (&error))
1065 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1066 for (i = 0; i < count; ++i)
1067 mono_array_setref (*fields, i, values [i]);
1074 ICALL_EXPORT MonoBoolean
1075 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1079 MonoObject **values = NULL;
1081 MonoClassField* field;
1085 MONO_CHECK_ARG_NULL (that, FALSE);
1087 if (this_obj->vtable != that->vtable)
1090 klass = mono_object_class (this_obj);
1092 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1093 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1096 * Do the comparison for fields of primitive type and return a result if
1097 * possible. Otherwise, return the remaining fields in an array to the
1098 * managed side. This way, we can avoid costly reflection operations in
1103 while ((field = mono_class_get_fields (klass, &iter))) {
1104 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1106 if (mono_field_is_deleted (field))
1108 /* FIXME: Add more types */
1109 switch (field->type->type) {
1112 case MONO_TYPE_BOOLEAN:
1113 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1118 case MONO_TYPE_CHAR:
1119 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1124 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1129 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1133 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1137 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1142 case MONO_TYPE_STRING: {
1143 MonoString *s1, *s2;
1144 guint32 s1len, s2len;
1145 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1146 s2 = *(MonoString**)((guint8*)that + field->offset);
1149 if ((s1 == NULL) || (s2 == NULL))
1151 s1len = mono_string_length (s1);
1152 s2len = mono_string_length (s2);
1156 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1162 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1163 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1164 if (!is_ok (&error)) {
1165 mono_error_set_pending_exception (&error);
1168 values [count++] = o;
1169 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1170 if (!is_ok (&error)) {
1171 mono_error_set_pending_exception (&error);
1174 values [count++] = o;
1177 if (klass->enumtype)
1178 /* enums only have one non-static field */
1184 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1185 if (mono_error_set_pending_exception (&error))
1187 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1188 for (i = 0; i < count; ++i)
1189 mono_array_setref_fast (*fields, i, values [i]);
1196 ICALL_EXPORT MonoReflectionType *
1197 ves_icall_System_Object_GetType (MonoObject *obj)
1200 MonoReflectionType *ret;
1201 #ifndef DISABLE_REMOTING
1202 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1203 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1206 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1208 mono_error_set_pending_exception (&error);
1213 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1215 MonoMethod **dest = (MonoMethod **)data;
1217 /* skip unmanaged frames */
1222 if (!strcmp (m->klass->name_space, "System.Reflection"))
1231 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1233 MonoMethod **dest = (MonoMethod **)data;
1235 /* skip unmanaged frames */
1239 if (m->wrapper_type != MONO_WRAPPER_NONE)
1247 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1258 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1260 MonoMethod **dest = (MonoMethod **)data;
1262 /* skip unmanaged frames */
1266 if (m->wrapper_type != MONO_WRAPPER_NONE)
1274 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1275 || (!strcmp (m->klass->name_space, "System"))))
1285 static MonoReflectionType *
1286 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1288 MonoMethod *m, *dest;
1290 MonoType *type = NULL;
1291 MonoAssembly *assembly = NULL;
1292 gboolean type_resolve = FALSE;
1293 MonoImage *rootimage = NULL;
1295 mono_error_init (error);
1298 * We must compute the calling assembly as type loading must happen under a metadata context.
1299 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1300 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1302 m = mono_method_get_last_managed ();
1304 if (m && m->klass->image != mono_defaults.corlib) {
1305 /* Happens with inlining */
1307 /* Ugly hack: type_from_parsed_name is called from
1308 * System.Type.internal_from_name, which is called most
1309 * directly from System.Type.GetType(string,bool,bool) but
1310 * also indirectly from places such as
1311 * System.Type.GetType(string,func,func) (via
1312 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1313 * so we need to skip over all of those to find the true caller.
1315 * It would be nice if we had stack marks.
1317 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1323 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1324 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1325 * to crash. This only seems to happen in some strange remoting
1326 * scenarios and I was unable to figure out what's happening there.
1327 * Dec 10, 2005 - Martin.
1331 assembly = dest->klass->image->assembly;
1332 type_resolve = TRUE;
1333 rootimage = assembly->image;
1335 g_warning (G_STRLOC);
1338 if (info->assembly.name)
1339 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1342 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1343 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1344 return_val_if_nok (error, NULL);
1348 // Say we're looking for System.Generic.Dict<int, Local>
1349 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1350 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1351 // is messed up when we go to construct the Local as the type arg...
1353 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1354 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1355 if (!info->assembly.name && !type) {
1357 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1358 return_val_if_nok (error, NULL);
1360 if (assembly && !type && type_resolve) {
1361 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1362 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1363 return_val_if_nok (error, NULL);
1369 return mono_type_get_object_checked (mono_domain_get (), type, error);
1372 ICALL_EXPORT MonoReflectionType*
1373 ves_icall_System_Type_internal_from_name (MonoString *name,
1374 MonoBoolean throwOnError,
1375 MonoBoolean ignoreCase)
1378 MonoTypeNameParse info;
1379 MonoReflectionType *type = NULL;
1382 char *str = mono_string_to_utf8_checked (name, &error);
1383 if (!is_ok (&error))
1386 parsedOk = mono_reflection_parse_type (str, &info);
1388 /* mono_reflection_parse_type() mangles the string */
1390 mono_reflection_free_type_info (&info);
1392 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1396 type = type_from_parsed_name (&info, ignoreCase, &error);
1398 mono_reflection_free_type_info (&info);
1400 if (!is_ok (&error))
1405 mono_error_set_type_load_name (&error, g_strdup (str), NULL, "");
1412 if (!is_ok (&error)) {
1414 mono_error_set_pending_exception (&error);
1416 mono_error_cleanup (&error);
1424 ICALL_EXPORT MonoReflectionType*
1425 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1428 MonoReflectionType *ret;
1429 MonoDomain *domain = mono_domain_get ();
1431 ret = mono_type_get_object_checked (domain, handle, &error);
1432 mono_error_set_pending_exception (&error);
1437 ICALL_EXPORT MonoType*
1438 ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass)
1440 return mono_class_get_type (klass);
1444 ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array)
1446 g_ptr_array_free (ptr_array, TRUE);
1450 ves_icall_Mono_SafeStringMarshal_GFree (void *c_str)
1456 ves_icall_Mono_SafeStringMarshal_StringToUtf8 (MonoString *s)
1459 char *res = mono_string_to_utf8_checked (s, &error);
1460 mono_error_set_pending_exception (&error);
1464 /* System.TypeCode */
1483 TYPECODE_STRING = 18
1486 ICALL_EXPORT guint32
1487 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1489 int t = type->type->type;
1491 if (type->type->byref)
1492 return TYPECODE_OBJECT;
1496 case MONO_TYPE_VOID:
1497 return TYPECODE_OBJECT;
1498 case MONO_TYPE_BOOLEAN:
1499 return TYPECODE_BOOLEAN;
1501 return TYPECODE_BYTE;
1503 return TYPECODE_SBYTE;
1505 return TYPECODE_UINT16;
1507 return TYPECODE_INT16;
1508 case MONO_TYPE_CHAR:
1509 return TYPECODE_CHAR;
1513 return TYPECODE_OBJECT;
1515 return TYPECODE_UINT32;
1517 return TYPECODE_INT32;
1519 return TYPECODE_UINT64;
1521 return TYPECODE_INT64;
1523 return TYPECODE_SINGLE;
1525 return TYPECODE_DOUBLE;
1526 case MONO_TYPE_VALUETYPE: {
1527 MonoClass *klass = type->type->data.klass;
1529 if (klass->enumtype) {
1530 t = mono_class_enum_basetype (klass)->type;
1532 } else if (mono_is_corlib_image (klass->image)) {
1533 if (strcmp (klass->name_space, "System") == 0) {
1534 if (strcmp (klass->name, "Decimal") == 0)
1535 return TYPECODE_DECIMAL;
1536 else if (strcmp (klass->name, "DateTime") == 0)
1537 return TYPECODE_DATETIME;
1540 return TYPECODE_OBJECT;
1542 case MONO_TYPE_STRING:
1543 return TYPECODE_STRING;
1544 case MONO_TYPE_SZARRAY:
1545 case MONO_TYPE_ARRAY:
1546 case MONO_TYPE_OBJECT:
1548 case MONO_TYPE_MVAR:
1549 case MONO_TYPE_TYPEDBYREF:
1550 return TYPECODE_OBJECT;
1551 case MONO_TYPE_CLASS:
1553 MonoClass *klass = type->type->data.klass;
1554 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1555 if (strcmp (klass->name, "DBNull") == 0)
1556 return TYPECODE_DBNULL;
1559 return TYPECODE_OBJECT;
1560 case MONO_TYPE_GENERICINST:
1561 return TYPECODE_OBJECT;
1563 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1569 mono_type_is_primitive (MonoType *type)
1571 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1572 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1576 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1578 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1579 return mono_class_enum_basetype (type->data.klass);
1580 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1581 return mono_class_enum_basetype (type->data.generic_class->container_class);
1585 ICALL_EXPORT guint32
1586 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1591 g_assert (type != NULL);
1593 klass = mono_class_from_mono_type (type->type);
1594 klassc = mono_class_from_mono_type (c->type);
1596 if (type->type->byref ^ c->type->byref)
1599 if (type->type->byref) {
1600 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1601 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1603 klass = mono_class_from_mono_type (t);
1604 klassc = mono_class_from_mono_type (ot);
1606 if (mono_type_is_primitive (t)) {
1607 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1608 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1609 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1610 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1611 return t->type == ot->type;
1613 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1616 if (klass->valuetype)
1617 return klass == klassc;
1618 return klass->valuetype == klassc->valuetype;
1621 return mono_class_is_assignable_from (klass, klassc);
1624 ICALL_EXPORT guint32
1625 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1628 MonoClass *klass = mono_class_from_mono_type (type->type);
1629 mono_class_init_checked (klass, &error);
1630 if (!is_ok (&error)) {
1631 mono_error_set_pending_exception (&error);
1634 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1635 mono_error_set_pending_exception (&error);
1639 ICALL_EXPORT guint32
1640 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1642 MonoClass *klass = mono_class_from_mono_type (type->type);
1643 return klass->flags;
1646 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1647 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1650 MonoClass *klass = field->field->parent;
1651 MonoMarshalType *info;
1655 if (klass->generic_container ||
1656 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1659 ftype = mono_field_get_type (field->field);
1660 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1663 info = mono_marshal_load_type_info (klass);
1665 for (i = 0; i < info->num_fields; ++i) {
1666 if (info->fields [i].field == field->field) {
1667 if (!info->fields [i].mspec)
1670 MonoReflectionMarshalAsAttribute* obj;
1671 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1672 if (!mono_error_ok (&error))
1673 mono_error_set_pending_exception (&error);
1682 ICALL_EXPORT MonoReflectionField*
1683 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1686 gboolean found = FALSE;
1692 klass = handle->parent;
1694 klass = mono_class_from_mono_type (type);
1696 found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1699 /* The managed code will throw the exception */
1703 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1704 mono_error_set_pending_exception (&error);
1708 ICALL_EXPORT MonoReflectionEvent*
1709 ves_icall_System_Reflection_EventInfo_internal_from_handle_type (MonoEvent *handle, MonoType *type)
1717 klass = handle->parent;
1719 klass = mono_class_from_mono_type (type);
1721 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1723 /* Managed code will throw an exception */
1727 MonoReflectionEvent *result = mono_event_get_object_checked (mono_domain_get (), klass, handle, &error);
1728 mono_error_set_pending_exception (&error);
1733 ICALL_EXPORT MonoReflectionProperty*
1734 ves_icall_System_Reflection_PropertyInfo_internal_from_handle_type (MonoProperty *handle, MonoType *type)
1742 klass = handle->parent;
1744 klass = mono_class_from_mono_type (type);
1746 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1748 /* Managed code will throw an exception */
1752 MonoReflectionProperty *result = mono_property_get_object_checked (mono_domain_get (), klass, handle, &error);
1753 mono_error_set_pending_exception (&error);
1757 ICALL_EXPORT MonoArray*
1758 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1761 MonoType *type = mono_field_get_type_checked (field->field, &error);
1764 if (!mono_error_ok (&error)) {
1765 mono_error_set_pending_exception (&error);
1769 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1770 mono_error_set_pending_exception (&error);
1775 vell_icall_get_method_attributes (MonoMethod *method)
1777 return method->flags;
1781 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1784 MonoReflectionType *rt;
1785 MonoDomain *domain = mono_domain_get ();
1786 MonoMethodSignature* sig;
1788 sig = mono_method_signature_checked (method, &error);
1789 if (!mono_error_ok (&error)) {
1790 mono_error_set_pending_exception (&error);
1794 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1795 if (!mono_error_ok (&error)) {
1796 mono_error_set_pending_exception (&error);
1800 MONO_STRUCT_SETREF (info, parent, rt);
1802 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1803 if (!mono_error_ok (&error)) {
1804 mono_error_set_pending_exception (&error);
1808 MONO_STRUCT_SETREF (info, ret, rt);
1810 info->attrs = method->flags;
1811 info->implattrs = method->iflags;
1812 if (sig->call_convention == MONO_CALL_DEFAULT)
1813 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1815 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1820 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1823 ICALL_EXPORT MonoArray*
1824 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1827 MonoDomain *domain = mono_domain_get ();
1829 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1830 mono_error_set_pending_exception (&error);
1834 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1835 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1838 MonoDomain *domain = mono_domain_get ();
1839 MonoReflectionMarshalAsAttribute* res = NULL;
1840 MonoMarshalSpec **mspecs;
1843 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1844 mono_method_get_marshal_info (method, mspecs);
1847 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1848 if (!mono_error_ok (&error)) {
1849 mono_error_set_pending_exception (&error);
1854 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1856 mono_metadata_free_marshal_spec (mspecs [i]);
1863 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1865 MonoClass *parent = field->field->parent;
1866 if (!parent->size_inited)
1867 mono_class_init (parent);
1868 mono_class_setup_fields_locking (parent);
1870 return field->field->offset - sizeof (MonoObject);
1873 ICALL_EXPORT MonoReflectionType*
1874 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1877 MonoReflectionType *ret;
1880 parent = declaring? field->field->parent: field->klass;
1882 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1883 mono_error_set_pending_exception (&error);
1889 ICALL_EXPORT MonoObject *
1890 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1893 MonoClass *fklass = field->klass;
1894 MonoClassField *cf = field->field;
1895 MonoDomain *domain = mono_object_domain (field);
1897 if (fklass->image->assembly->ref_only) {
1898 mono_set_pending_exception (mono_get_exception_invalid_operation (
1899 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1903 if (mono_security_core_clr_enabled () &&
1904 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1905 mono_error_set_pending_exception (&error);
1909 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1910 mono_error_set_pending_exception (&error);
1915 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1918 MonoClassField *cf = field->field;
1922 if (field->klass->image->assembly->ref_only) {
1923 mono_set_pending_exception (mono_get_exception_invalid_operation (
1924 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1928 if (mono_security_core_clr_enabled () &&
1929 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1930 mono_error_set_pending_exception (&error);
1934 type = mono_field_get_type_checked (cf, &error);
1935 if (!mono_error_ok (&error)) {
1936 mono_error_set_pending_exception (&error);
1940 v = (gchar *) value;
1942 switch (type->type) {
1945 case MONO_TYPE_BOOLEAN:
1948 case MONO_TYPE_CHAR:
1957 case MONO_TYPE_VALUETYPE:
1960 v += sizeof (MonoObject);
1962 case MONO_TYPE_STRING:
1963 case MONO_TYPE_OBJECT:
1964 case MONO_TYPE_CLASS:
1965 case MONO_TYPE_ARRAY:
1966 case MONO_TYPE_SZARRAY:
1969 case MONO_TYPE_GENERICINST: {
1970 MonoGenericClass *gclass = type->data.generic_class;
1971 g_assert (!gclass->context.class_inst->is_open);
1973 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1974 MonoClass *nklass = mono_class_from_mono_type (type);
1975 MonoObject *nullable;
1978 * Convert the boxed vtype into a Nullable structure.
1979 * This is complicated by the fact that Nullables have
1980 * a variable structure.
1982 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1983 if (!mono_error_ok (&error)) {
1984 mono_error_set_pending_exception (&error);
1988 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1990 v = (gchar *)mono_object_unbox (nullable);
1993 if (gclass->container_class->valuetype && (v != NULL))
1994 v += sizeof (MonoObject);
1998 g_error ("type 0x%x not handled in "
1999 "ves_icall_FieldInfo_SetValueInternal", type->type);
2004 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2005 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2006 if (!is_ok (&error)) {
2007 mono_error_set_pending_exception (&error);
2010 if (!vtable->initialized) {
2011 if (!mono_runtime_class_init_full (vtable, &error)) {
2012 mono_error_set_pending_exception (&error);
2016 mono_field_static_set_value (vtable, cf, v);
2018 mono_field_set_value (obj, cf, v);
2023 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2032 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2033 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2037 if (MONO_TYPE_IS_REFERENCE (f->type))
2038 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2040 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2043 ICALL_EXPORT MonoObject *
2044 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2046 MonoObject *o = NULL;
2047 MonoClassField *field = rfield->field;
2049 MonoDomain *domain = mono_object_domain (rfield);
2051 MonoTypeEnum def_type;
2052 const char *def_value;
2056 mono_class_init (field->parent);
2058 t = mono_field_get_type_checked (field, &error);
2059 if (!mono_error_ok (&error)) {
2060 mono_error_set_pending_exception (&error);
2064 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2065 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2069 if (image_is_dynamic (field->parent->image)) {
2070 MonoClass *klass = field->parent;
2071 int fidx = field - klass->fields;
2073 g_assert (fidx >= 0 && fidx < klass->field.count);
2074 g_assert (klass->ext);
2075 g_assert (klass->ext->field_def_values);
2076 def_type = klass->ext->field_def_values [fidx].def_type;
2077 def_value = klass->ext->field_def_values [fidx].data;
2078 if (def_type == MONO_TYPE_END) {
2079 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2083 def_value = mono_class_get_field_default_value (field, &def_type);
2084 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2086 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2091 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2095 case MONO_TYPE_BOOLEAN:
2098 case MONO_TYPE_CHAR:
2106 case MONO_TYPE_R8: {
2109 /* boxed value type */
2110 t = g_new0 (MonoType, 1);
2112 klass = mono_class_from_mono_type (t);
2114 o = mono_object_new_checked (domain, klass, &error);
2115 if (!mono_error_ok (&error)) {
2116 mono_error_set_pending_exception (&error);
2119 v = ((gchar *) o) + sizeof (MonoObject);
2120 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2121 if (mono_error_set_pending_exception (&error))
2125 case MONO_TYPE_STRING:
2126 case MONO_TYPE_CLASS:
2127 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2128 if (mono_error_set_pending_exception (&error))
2132 g_assert_not_reached ();
2138 ICALL_EXPORT MonoReflectionType*
2139 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2142 MonoReflectionType *ret;
2145 type = mono_field_get_type_checked (ref_field->field, &error);
2146 if (!mono_error_ok (&error)) {
2147 mono_error_set_pending_exception (&error);
2151 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2152 if (!mono_error_ok (&error)) {
2153 mono_error_set_pending_exception (&error);
2160 /* From MonoProperty.cs */
2162 PInfo_Attributes = 1,
2163 PInfo_GetMethod = 1 << 1,
2164 PInfo_SetMethod = 1 << 2,
2165 PInfo_ReflectedType = 1 << 3,
2166 PInfo_DeclaringType = 1 << 4,
2171 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2174 MonoReflectionType *rt;
2175 MonoReflectionMethod *rm;
2176 MonoDomain *domain = mono_object_domain (property);
2177 const MonoProperty *pproperty = property->property;
2179 if ((req_info & PInfo_ReflectedType) != 0) {
2180 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2181 if (mono_error_set_pending_exception (&error))
2184 MONO_STRUCT_SETREF (info, parent, rt);
2186 if ((req_info & PInfo_DeclaringType) != 0) {
2187 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2188 if (mono_error_set_pending_exception (&error))
2191 MONO_STRUCT_SETREF (info, declaring_type, rt);
2194 if ((req_info & PInfo_Name) != 0)
2195 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2197 if ((req_info & PInfo_Attributes) != 0)
2198 info->attrs = pproperty->attrs;
2200 if ((req_info & PInfo_GetMethod) != 0) {
2201 if (pproperty->get &&
2202 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2203 pproperty->get->klass == property->klass)) {
2204 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2205 if (mono_error_set_pending_exception (&error))
2211 MONO_STRUCT_SETREF (info, get, rm);
2213 if ((req_info & PInfo_SetMethod) != 0) {
2214 if (pproperty->set &&
2215 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2216 pproperty->set->klass == property->klass)) {
2217 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2218 if (mono_error_set_pending_exception (&error))
2224 MONO_STRUCT_SETREF (info, set, rm);
2227 * There may be other methods defined for properties, though, it seems they are not exposed
2228 * in the reflection API
2233 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2236 MonoReflectionType *rt;
2237 MonoReflectionMethod *rm;
2238 MonoDomain *domain = mono_object_domain (event);
2240 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2241 if (mono_error_set_pending_exception (&error))
2244 MONO_STRUCT_SETREF (info, reflected_type, rt);
2246 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2247 if (mono_error_set_pending_exception (&error))
2250 MONO_STRUCT_SETREF (info, declaring_type, rt);
2252 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2253 info->attrs = event->event->attrs;
2255 if (event->event->add) {
2256 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2257 if (mono_error_set_pending_exception (&error))
2263 MONO_STRUCT_SETREF (info, add_method, rm);
2265 if (event->event->remove) {
2266 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2267 if (mono_error_set_pending_exception (&error))
2273 MONO_STRUCT_SETREF (info, remove_method, rm);
2275 if (event->event->raise) {
2276 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2277 if (mono_error_set_pending_exception (&error))
2283 MONO_STRUCT_SETREF (info, raise_method, rm);
2285 #ifndef MONO_SMALL_CONFIG
2286 if (event->event->other) {
2288 while (event->event->other [n])
2290 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2291 if (mono_error_set_pending_exception (&error))
2293 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2295 for (i = 0; i < n; i++) {
2296 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2297 if (mono_error_set_pending_exception (&error))
2299 mono_array_setref (info->other_methods, i, rm);
2306 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2311 mono_class_setup_interfaces (klass, error);
2312 if (!mono_error_ok (error))
2315 for (i = 0; i < klass->interface_count; i++) {
2316 ic = klass->interfaces [i];
2317 g_hash_table_insert (ifaces, ic, ic);
2319 collect_interfaces (ic, ifaces, error);
2320 if (!mono_error_ok (error))
2326 MonoArray *iface_array;
2327 MonoGenericContext *context;
2331 } FillIfaceArrayData;
2334 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2336 MonoReflectionType *rt;
2337 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2338 MonoClass *ic = (MonoClass *)key;
2339 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2341 if (!mono_error_ok (data->error))
2344 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2345 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2346 if (!mono_error_ok (data->error))
2350 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2351 if (!mono_error_ok (data->error))
2354 mono_array_setref (data->iface_array, data->next_idx++, rt);
2357 mono_metadata_free_type (inflated);
2361 get_interfaces_hash (gconstpointer v1)
2363 MonoClass *k = (MonoClass*)v1;
2365 return k->type_token;
2368 ICALL_EXPORT MonoArray*
2369 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2372 MonoClass *klass = mono_class_from_mono_type (type->type);
2374 FillIfaceArrayData data = { 0 };
2377 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2379 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2380 data.context = mono_class_get_context (klass);
2381 klass = klass->generic_class->container_class;
2384 for (parent = klass; parent; parent = parent->parent) {
2385 mono_class_setup_interfaces (parent, &error);
2386 if (!mono_error_ok (&error))
2388 collect_interfaces (parent, iface_hash, &error);
2389 if (!mono_error_ok (&error))
2393 data.error = &error;
2394 data.domain = mono_object_domain (type);
2396 len = g_hash_table_size (iface_hash);
2398 g_hash_table_destroy (iface_hash);
2399 if (!data.domain->empty_types) {
2400 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2401 if (!is_ok (&error))
2404 return data.domain->empty_types;
2407 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2408 if (!is_ok (&error))
2410 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2411 if (!mono_error_ok (&error))
2414 g_hash_table_destroy (iface_hash);
2415 return data.iface_array;
2418 g_hash_table_destroy (iface_hash);
2419 mono_error_set_pending_exception (&error);
2424 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2426 gboolean variance_used;
2427 MonoClass *klass = mono_class_from_mono_type (type->type);
2428 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2429 MonoReflectionMethod *member;
2432 int i = 0, len, ioffset;
2436 mono_class_init_checked (klass, &error);
2437 if (mono_error_set_pending_exception (&error))
2439 mono_class_init_checked (iclass, &error);
2440 if (mono_error_set_pending_exception (&error))
2443 mono_class_setup_vtable (klass);
2445 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2449 len = mono_class_num_methods (iclass);
2450 domain = mono_object_domain (type);
2451 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2452 if (mono_error_set_pending_exception (&error))
2454 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2455 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2456 if (mono_error_set_pending_exception (&error))
2458 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2460 while ((method = mono_class_get_methods (iclass, &iter))) {
2461 member = mono_method_get_object_checked (domain, method, iclass, &error);
2462 if (mono_error_set_pending_exception (&error))
2464 mono_array_setref (*methods, i, member);
2465 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2466 if (mono_error_set_pending_exception (&error))
2468 mono_array_setref (*targets, i, member);
2475 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2478 MonoClass *klass = mono_class_from_mono_type (type->type);
2480 mono_class_init_checked (klass, &error);
2481 if (mono_error_set_pending_exception (&error))
2484 if (image_is_dynamic (klass->image)) {
2485 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2486 *packing = tb->packing_size;
2487 *size = tb->class_size;
2489 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2493 ICALL_EXPORT MonoReflectionType*
2494 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2497 MonoReflectionType *ret;
2500 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2501 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2502 mono_error_set_pending_exception (&error);
2506 klass = mono_class_from_mono_type (type->type);
2507 mono_class_init_checked (klass, &error);
2508 if (mono_error_set_pending_exception (&error))
2512 // GetElementType should only return a type for:
2513 // Array Pointer PassedByRef
2514 if (type->type->byref)
2515 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2516 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2517 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2518 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2519 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2523 mono_error_set_pending_exception (&error);
2528 ICALL_EXPORT MonoReflectionType*
2529 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2532 MonoReflectionType *ret;
2534 if (type->type->byref)
2537 MonoClass *klass = mono_class_from_mono_type (type->type);
2541 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2542 mono_error_set_pending_exception (&error);
2547 ICALL_EXPORT MonoBoolean
2548 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2550 return type->type->type == MONO_TYPE_PTR;
2553 ICALL_EXPORT MonoBoolean
2554 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2556 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)));
2559 ICALL_EXPORT MonoBoolean
2560 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2562 return type->type->byref;
2565 ICALL_EXPORT MonoBoolean
2566 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2569 MonoClass *klass = mono_class_from_mono_type (type->type);
2570 mono_class_init_checked (klass, &error);
2571 if (mono_error_set_pending_exception (&error))
2574 return mono_class_is_com_object (klass);
2577 ICALL_EXPORT guint32
2578 ves_icall_reflection_get_token (MonoObject* obj)
2581 guint32 result = mono_reflection_get_token_checked (obj, &error);
2582 mono_error_set_pending_exception (&error);
2586 ICALL_EXPORT MonoReflectionModule*
2587 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2590 MonoReflectionModule *result = NULL;
2591 MonoClass *klass = mono_class_from_mono_type (type->type);
2592 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2593 mono_error_set_pending_exception (&error);
2597 ICALL_EXPORT MonoReflectionAssembly*
2598 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2601 MonoDomain *domain = mono_domain_get ();
2602 MonoClass *klass = mono_class_from_mono_type (type->type);
2603 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2604 mono_error_set_pending_exception (&error);
2608 ICALL_EXPORT MonoReflectionType*
2609 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2612 MonoReflectionType *ret;
2613 MonoDomain *domain = mono_domain_get ();
2616 if (type->type->byref)
2618 if (type->type->type == MONO_TYPE_VAR) {
2619 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2620 klass = param ? param->owner.klass : NULL;
2621 } else if (type->type->type == MONO_TYPE_MVAR) {
2622 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2623 klass = param ? param->owner.method->klass : NULL;
2625 klass = mono_class_from_mono_type (type->type)->nested_in;
2631 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2632 mono_error_set_pending_exception (&error);
2637 ICALL_EXPORT MonoStringHandle
2638 ves_icall_RuntimeType_get_Name (MonoReflectionTypeHandle reftype, MonoError *error)
2640 MonoDomain *domain = mono_domain_get ();
2641 MonoType *type = MONO_HANDLE_RAW(reftype)->type;
2642 MonoClass *klass = mono_class_from_mono_type (type);
2645 char *n = g_strdup_printf ("%s&", klass->name);
2646 MonoStringHandle res = mono_string_new_handle (domain, n, error);
2652 return mono_string_new_handle (domain, klass->name, error);
2656 ICALL_EXPORT MonoStringHandle
2657 ves_icall_RuntimeType_get_Namespace (MonoReflectionTypeHandle type, MonoError *error)
2659 MonoDomain *domain = mono_domain_get ();
2660 MonoClass *klass = mono_class_from_mono_type_handle (type);
2662 while (klass->nested_in)
2663 klass = klass->nested_in;
2665 if (klass->name_space [0] == '\0')
2666 return NULL_HANDLE_STRING;
2668 return mono_string_new_handle (domain, klass->name_space, error);
2672 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2676 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2677 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2681 klass = mono_class_from_mono_type (type->type);
2687 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2689 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2692 ICALL_EXPORT MonoArray*
2693 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2696 MonoReflectionType *rt;
2698 MonoClass *klass, *pklass;
2699 MonoDomain *domain = mono_object_domain (type);
2702 klass = mono_class_from_mono_type (type->type);
2704 if (klass->generic_container) {
2705 MonoGenericContainer *container = klass->generic_container;
2706 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2707 if (mono_error_set_pending_exception (&error))
2709 for (i = 0; i < container->type_argc; ++i) {
2710 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2712 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2713 if (mono_error_set_pending_exception (&error))
2716 mono_array_setref (res, i, rt);
2718 } else if (klass->generic_class) {
2719 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2720 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2721 if (mono_error_set_pending_exception (&error))
2723 for (i = 0; i < inst->type_argc; ++i) {
2724 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2725 if (mono_error_set_pending_exception (&error))
2728 mono_array_setref (res, i, rt);
2736 ICALL_EXPORT gboolean
2737 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2741 if (!IS_MONOTYPE (type))
2744 if (type->type->byref)
2747 klass = mono_class_from_mono_type (type->type);
2748 return klass->generic_container != NULL;
2751 ICALL_EXPORT MonoReflectionType*
2752 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2755 MonoReflectionType *ret;
2758 if (type->type->byref)
2761 klass = mono_class_from_mono_type (type->type);
2763 if (klass->generic_container) {
2764 return type; /* check this one */
2766 if (klass->generic_class) {
2767 MonoClass *generic_class = klass->generic_class->container_class;
2770 tb = mono_class_get_ref_info (generic_class);
2772 if (generic_class->wastypebuilder && tb)
2773 return (MonoReflectionType *)tb;
2775 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2776 mono_error_set_pending_exception (&error);
2784 ICALL_EXPORT MonoReflectionType*
2785 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2788 MonoReflectionType *ret;
2790 MonoType *geninst, **types;
2793 g_assert (IS_MONOTYPE (type));
2794 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2795 if (mono_error_set_pending_exception (&error))
2798 count = mono_array_length (type_array);
2799 types = g_new0 (MonoType *, count);
2801 for (i = 0; i < count; i++) {
2802 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2803 types [i] = t->type;
2806 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2809 mono_error_set_pending_exception (&error);
2813 klass = mono_class_from_mono_type (geninst);
2815 /*we might inflate to the GTD*/
2816 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2817 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2821 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2822 mono_error_set_pending_exception (&error);
2827 ICALL_EXPORT gboolean
2828 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2832 if (!IS_MONOTYPE (type))
2835 if (type->type->byref)
2838 klass = mono_class_from_mono_type (type->type);
2839 return klass->generic_class != NULL || klass->generic_container != NULL;
2843 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2845 if (!IS_MONOTYPE (type))
2848 if (is_generic_parameter (type->type))
2849 return mono_type_get_generic_param_num (type->type);
2853 ICALL_EXPORT MonoGenericParamInfo *
2854 ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionType *type)
2856 return mono_generic_param_info (type->type->data.generic_param);
2859 ICALL_EXPORT MonoBoolean
2860 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2862 return is_generic_parameter (type->type);
2865 ICALL_EXPORT MonoReflectionMethod*
2866 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2867 MonoReflectionMethod* generic)
2874 MonoReflectionMethod *ret = NULL;
2876 domain = ((MonoObject *)type)->vtable->domain;
2878 klass = mono_class_from_mono_type (type->type);
2879 mono_class_init_checked (klass, &error);
2880 if (mono_error_set_pending_exception (&error))
2884 while ((method = mono_class_get_methods (klass, &iter))) {
2885 if (method->token == generic->method->token) {
2886 ret = mono_method_get_object_checked (domain, method, klass, &error);
2887 if (mono_error_set_pending_exception (&error))
2895 ICALL_EXPORT MonoReflectionMethod *
2896 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
2899 MonoType *type = ref_type->type;
2901 MonoReflectionMethod *ret = NULL;
2903 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2904 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2907 if (type->type == MONO_TYPE_VAR)
2910 method = mono_type_get_generic_param_owner (type)->owner.method;
2913 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2914 if (!mono_error_ok (&error))
2915 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2919 ICALL_EXPORT MonoBoolean
2920 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2922 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2926 ICALL_EXPORT MonoBoolean
2927 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2929 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2934 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2936 MonoDomain *domain = mono_domain_get ();
2937 MonoImage *image = method->method->klass->image;
2938 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2939 MonoTableInfo *tables = image->tables;
2940 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2941 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2942 guint32 im_cols [MONO_IMPLMAP_SIZE];
2943 guint32 scope_token;
2944 const char *import = NULL;
2945 const char *scope = NULL;
2947 if (image_is_dynamic (image)) {
2948 MonoReflectionMethodAux *method_aux =
2949 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2951 import = method_aux->dllentry;
2952 scope = method_aux->dll;
2955 if (!import || !scope) {
2956 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2961 if (piinfo->implmap_idx) {
2962 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2964 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2965 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2966 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2967 scope = mono_metadata_string_heap (image, scope_token);
2971 *flags = piinfo->piflags;
2972 *entry_point = mono_string_new (domain, import);
2973 *dll_name = mono_string_new (domain, scope);
2976 ICALL_EXPORT MonoReflectionMethod *
2977 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2979 MonoMethodInflated *imethod;
2981 MonoReflectionMethod *ret = NULL;
2984 if (method->method->is_generic)
2987 if (!method->method->is_inflated)
2990 imethod = (MonoMethodInflated *) method->method;
2992 result = imethod->declaring;
2993 /* Not a generic method. */
2994 if (!result->is_generic)
2997 if (image_is_dynamic (method->method->klass->image)) {
2998 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2999 MonoReflectionMethod *res;
3002 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3003 * the dynamic case as well ?
3005 mono_image_lock ((MonoImage*)image);
3006 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3007 mono_image_unlock ((MonoImage*)image);
3013 if (imethod->context.class_inst) {
3014 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3015 /*Generic methods gets the context of the GTD.*/
3016 if (mono_class_get_context (klass)) {
3017 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3018 if (!mono_error_ok (&error))
3023 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3025 if (!mono_error_ok (&error))
3026 mono_error_set_pending_exception (&error);
3030 ICALL_EXPORT gboolean
3031 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3033 return mono_method_signature (method->method)->generic_param_count != 0;
3036 ICALL_EXPORT gboolean
3037 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3039 return method->method->is_generic;
3042 ICALL_EXPORT MonoArray*
3043 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3046 MonoReflectionType *rt;
3051 domain = mono_object_domain (method);
3053 if (method->method->is_inflated) {
3054 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3057 count = inst->type_argc;
3058 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3059 if (mono_error_set_pending_exception (&error))
3062 for (i = 0; i < count; i++) {
3063 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3064 if (mono_error_set_pending_exception (&error))
3067 mono_array_setref (res, i, rt);
3074 count = mono_method_signature (method->method)->generic_param_count;
3075 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3076 if (mono_error_set_pending_exception (&error))
3079 for (i = 0; i < count; i++) {
3080 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3081 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3082 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3084 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3085 if (mono_error_set_pending_exception (&error))
3088 mono_array_setref (res, i, rt);
3094 ICALL_EXPORT MonoObject *
3095 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3099 * Invoke from reflection is supposed to always be a virtual call (the API
3100 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3101 * greater flexibility.
3103 MonoMethod *m = method->method;
3104 MonoMethodSignature *sig = mono_method_signature (m);
3107 void *obj = this_arg;
3111 if (mono_security_core_clr_enabled () &&
3112 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3113 mono_error_set_pending_exception (&error);
3117 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3118 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3119 mono_error_cleanup (&error); /* FIXME does this make sense? */
3120 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3125 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3126 if (!is_ok (&error)) {
3127 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3130 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3131 char *target_name = mono_type_get_full_name (m->klass);
3132 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3133 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3135 g_free (target_name);
3139 m = mono_object_get_virtual_method (this_arg, m);
3140 /* must pass the pointer to the value for valuetype methods */
3141 if (m->klass->valuetype)
3142 obj = mono_object_unbox (this_arg);
3143 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3144 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3149 if (sig->ret->byref) {
3150 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"));
3154 pcount = params? mono_array_length (params): 0;
3155 if (pcount != sig->param_count) {
3156 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3160 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3161 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."));
3165 image = m->klass->image;
3166 if (image->assembly->ref_only) {
3167 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."));
3171 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3172 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3176 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3180 intptr_t *lower_bounds;
3181 pcount = mono_array_length (params);
3182 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3183 /* Note: the synthetized array .ctors have int32 as argument type */
3184 for (i = 0; i < pcount; ++i)
3185 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3187 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3188 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3189 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3190 if (!mono_error_ok (&error)) {
3191 mono_error_set_pending_exception (&error);
3195 for (i = 0; i < mono_array_length (arr); ++i) {
3196 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3197 if (!mono_error_ok (&error)) {
3198 mono_error_set_pending_exception (&error);
3201 mono_array_setref_fast (arr, i, subarray);
3203 return (MonoObject*)arr;
3206 if (m->klass->rank == pcount) {
3207 /* Only lengths provided. */
3208 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3209 if (!mono_error_ok (&error)) {
3210 mono_error_set_pending_exception (&error);
3214 return (MonoObject*)arr;
3216 g_assert (pcount == (m->klass->rank * 2));
3217 /* The arguments are lower-bound-length pairs */
3218 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3220 for (i = 0; i < pcount / 2; ++i) {
3221 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3222 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3225 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3226 if (!mono_error_ok (&error)) {
3227 mono_error_set_pending_exception (&error);
3231 return (MonoObject*)arr;
3234 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3235 mono_error_set_pending_exception (&error);
3239 #ifndef DISABLE_REMOTING
3240 ICALL_EXPORT MonoObject *
3241 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3244 MonoDomain *domain = mono_object_domain (method);
3245 MonoMethod *m = method->method;
3246 MonoMethodSignature *sig = mono_method_signature (m);
3247 MonoArray *out_args;
3249 int i, j, outarg_count = 0;
3251 if (m->klass == mono_defaults.object_class) {
3252 if (!strcmp (m->name, "FieldGetter")) {
3253 MonoClass *k = this_arg->vtable->klass;
3257 /* If this is a proxy, then it must be a CBO */
3258 if (k == mono_defaults.transparent_proxy_class) {
3259 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3260 this_arg = tp->rp->unwrapped_server;
3261 g_assert (this_arg);
3262 k = this_arg->vtable->klass;
3265 name = mono_array_get (params, MonoString *, 1);
3266 str = mono_string_to_utf8_checked (name, &error);
3267 if (mono_error_set_pending_exception (&error))
3271 MonoClassField* field = mono_class_get_field_from_name (k, str);
3274 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3275 if (field_klass->valuetype) {
3276 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3277 if (mono_error_set_pending_exception (&error))
3280 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3282 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3283 if (mono_error_set_pending_exception (&error))
3285 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3286 mono_array_setref (out_args, 0, result);
3293 g_assert_not_reached ();
3295 } else if (!strcmp (m->name, "FieldSetter")) {
3296 MonoClass *k = this_arg->vtable->klass;
3302 /* If this is a proxy, then it must be a CBO */
3303 if (k == mono_defaults.transparent_proxy_class) {
3304 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3305 this_arg = tp->rp->unwrapped_server;
3306 g_assert (this_arg);
3307 k = this_arg->vtable->klass;
3310 name = mono_array_get (params, MonoString *, 1);
3311 str = mono_string_to_utf8_checked (name, &error);
3312 if (mono_error_set_pending_exception (&error))
3316 MonoClassField* field = mono_class_get_field_from_name (k, str);
3319 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3320 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3322 if (field_klass->valuetype) {
3323 size = mono_type_size (field->type, &align);
3324 g_assert (size == mono_class_value_size (field_klass, NULL));
3325 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3327 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3330 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3331 if (mono_error_set_pending_exception (&error))
3333 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3342 g_assert_not_reached ();
3347 for (i = 0; i < mono_array_length (params); i++) {
3348 if (sig->params [i]->byref)
3352 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3353 if (mono_error_set_pending_exception (&error))
3356 /* handle constructors only for objects already allocated */
3357 if (!strcmp (method->method->name, ".ctor"))
3358 g_assert (this_arg);
3360 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3361 g_assert (!method->method->klass->valuetype);
3362 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3363 if (mono_error_set_pending_exception (&error))
3366 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3367 if (sig->params [i]->byref) {
3369 arg = mono_array_get (params, gpointer, i);
3370 mono_array_setref (out_args, j, arg);
3375 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3382 read_enum_value (const char *mem, int type)
3385 case MONO_TYPE_BOOLEAN:
3387 return *(guint8*)mem;
3389 return *(gint8*)mem;
3390 case MONO_TYPE_CHAR:
3392 return read16 (mem);
3394 return (gint16) read16 (mem);
3396 return read32 (mem);
3398 return (gint32) read32 (mem);
3401 return read64 (mem);
3403 g_assert_not_reached ();
3409 write_enum_value (char *mem, int type, guint64 value)
3413 case MONO_TYPE_I1: {
3414 guint8 *p = (guint8*)mem;
3420 case MONO_TYPE_CHAR: {
3421 guint16 *p = (guint16 *)mem;
3426 case MONO_TYPE_I4: {
3427 guint32 *p = (guint32 *)mem;
3432 case MONO_TYPE_I8: {
3433 guint64 *p = (guint64 *)mem;
3438 g_assert_not_reached ();
3443 ICALL_EXPORT MonoObject *
3444 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3452 domain = mono_object_domain (enumType);
3453 enumc = mono_class_from_mono_type (enumType->type);
3455 mono_class_init_checked (enumc, &error);
3456 if (mono_error_set_pending_exception (&error))
3459 etype = mono_class_enum_basetype (enumc);
3461 res = mono_object_new_checked (domain, enumc, &error);
3462 if (mono_error_set_pending_exception (&error))
3464 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3469 ICALL_EXPORT MonoBoolean
3470 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3472 int size = mono_class_value_size (a->vtable->klass, NULL);
3473 guint64 a_val = 0, b_val = 0;
3475 memcpy (&a_val, mono_object_unbox (a), size);
3476 memcpy (&b_val, mono_object_unbox (b), size);
3478 return (a_val & b_val) == b_val;
3481 ICALL_EXPORT MonoObject *
3482 ves_icall_System_Enum_get_value (MonoObject *eobj)
3494 g_assert (eobj->vtable->klass->enumtype);
3496 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3497 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3498 if (mono_error_set_pending_exception (&error))
3500 dst = (char *)res + sizeof (MonoObject);
3501 src = (char *)eobj + sizeof (MonoObject);
3502 size = mono_class_value_size (enumc, NULL);
3504 memcpy (dst, src, size);
3509 ICALL_EXPORT MonoReflectionType *
3510 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3513 MonoReflectionType *ret;
3517 klass = mono_class_from_mono_type (type->type);
3518 mono_class_init_checked (klass, &error);
3519 if (mono_error_set_pending_exception (&error))
3522 etype = mono_class_enum_basetype (klass);
3524 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3528 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3529 mono_error_set_pending_exception (&error);
3535 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3537 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3538 gpointer odata = (char *)other + sizeof (MonoObject);
3539 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3540 g_assert (basetype);
3545 if (eobj->vtable->klass != other->vtable->klass)
3548 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3549 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3550 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3553 return me > other ? 1 : -1; \
3556 switch (basetype->type) {
3558 COMPARE_ENUM_VALUES (guint8);
3560 COMPARE_ENUM_VALUES (gint8);
3561 case MONO_TYPE_CHAR:
3563 COMPARE_ENUM_VALUES (guint16);
3565 COMPARE_ENUM_VALUES (gint16);
3567 COMPARE_ENUM_VALUES (guint32);
3569 COMPARE_ENUM_VALUES (gint32);
3571 COMPARE_ENUM_VALUES (guint64);
3573 COMPARE_ENUM_VALUES (gint64);
3577 #undef COMPARE_ENUM_VALUES
3578 /* indicates that the enum was of an unsupported unerlying type */
3583 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3585 gpointer data = (char *)eobj + sizeof (MonoObject);
3586 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3587 g_assert (basetype);
3589 switch (basetype->type) {
3590 case MONO_TYPE_I1: {
3591 gint8 value = *((gint8*)data);
3592 return ((int)value ^ (int)value << 8);
3595 return *((guint8*)data);
3596 case MONO_TYPE_CHAR:
3598 return *((guint16*)data);
3600 case MONO_TYPE_I2: {
3601 gint16 value = *((gint16*)data);
3602 return ((int)(guint16)value | (((int)value) << 16));
3605 return *((guint32*)data);
3607 return *((gint32*)data);
3609 case MONO_TYPE_I8: {
3610 gint64 value = *((gint64*)data);
3611 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3614 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3619 ICALL_EXPORT MonoBoolean
3620 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3623 MonoDomain *domain = mono_object_domain (type);
3624 MonoClass *enumc = mono_class_from_mono_type (type->type);
3625 guint j = 0, nvalues;
3627 MonoClassField *field;
3629 guint64 field_value, previous_value = 0;
3630 gboolean sorted = TRUE;
3632 mono_class_init_checked (enumc, &error);
3633 if (mono_error_set_pending_exception (&error))
3637 if (!enumc->enumtype) {
3638 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3642 base_type = mono_class_enum_basetype (enumc)->type;
3644 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3645 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3646 if (mono_error_set_pending_exception (&error))
3648 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3649 if (mono_error_set_pending_exception (&error))
3653 while ((field = mono_class_get_fields (enumc, &iter))) {
3655 MonoTypeEnum def_type;
3657 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3659 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3661 if (mono_field_is_deleted (field))
3663 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3665 p = mono_class_get_field_default_value (field, &def_type);
3666 /* len = */ mono_metadata_decode_blob_size (p, &p);
3668 field_value = read_enum_value (p, base_type);
3669 mono_array_set (*values, guint64, j, field_value);
3671 if (previous_value > field_value)
3674 previous_value = field_value;
3682 BFLAGS_IgnoreCase = 1,
3683 BFLAGS_DeclaredOnly = 2,
3684 BFLAGS_Instance = 4,
3686 BFLAGS_Public = 0x10,
3687 BFLAGS_NonPublic = 0x20,
3688 BFLAGS_FlattenHierarchy = 0x40,
3689 BFLAGS_InvokeMethod = 0x100,
3690 BFLAGS_CreateInstance = 0x200,
3691 BFLAGS_GetField = 0x400,
3692 BFLAGS_SetField = 0x800,
3693 BFLAGS_GetProperty = 0x1000,
3694 BFLAGS_SetProperty = 0x2000,
3695 BFLAGS_ExactBinding = 0x10000,
3696 BFLAGS_SuppressChangeType = 0x20000,
3697 BFLAGS_OptionalParamBinding = 0x40000
3700 ICALL_EXPORT GPtrArray*
3701 ves_icall_RuntimeType_GetFields_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
3704 MonoClass *startklass, *klass;
3707 int (*compare_func) (const char *s1, const char *s2) = NULL;
3708 MonoClassField *field;
3710 if (type->type->byref) {
3711 return g_ptr_array_new ();
3714 mono_error_init (&error);
3716 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3718 klass = startklass = mono_class_from_mono_type (type->type);
3720 GPtrArray *ptr_array = g_ptr_array_sized_new (16);
3723 if (mono_class_has_failure (klass)) {
3724 mono_error_set_for_class_failure (&error, klass);
3729 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3730 guint32 flags = mono_field_get_flags (field);
3732 if (mono_field_is_deleted_with_flags (field, flags))
3734 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3735 if (bflags & BFLAGS_Public)
3737 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3738 if (bflags & BFLAGS_NonPublic) {
3745 if (flags & FIELD_ATTRIBUTE_STATIC) {
3746 if (bflags & BFLAGS_Static)
3747 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3750 if (bflags & BFLAGS_Instance)
3757 if (utf8_name != NULL && compare_func (mono_field_get_name (field), utf8_name))
3760 g_ptr_array_add (ptr_array, field);
3762 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3768 g_ptr_array_free (ptr_array, TRUE);
3769 mono_error_set_pending_exception (&error);
3774 method_nonpublic (MonoMethod* method, gboolean start_klass)
3776 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3777 case METHOD_ATTRIBUTE_ASSEM:
3778 return (start_klass || mono_defaults.generic_ilist_class);
3779 case METHOD_ATTRIBUTE_PRIVATE:
3781 case METHOD_ATTRIBUTE_PUBLIC:
3789 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoError *error)
3792 MonoClass *startklass;
3796 /*FIXME, use MonoBitSet*/
3797 guint32 method_slots_default [8];
3798 guint32 *method_slots = NULL;
3799 int (*compare_func) (const char *s1, const char *s2) = NULL;
3801 array = g_ptr_array_new ();
3803 mono_error_init (error);
3806 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3808 /* An optimization for calls made from Delegate:CreateDelegate () */
3809 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3810 method = mono_get_delegate_invoke (klass);
3813 g_ptr_array_add (array, method);
3817 mono_class_setup_methods (klass);
3818 mono_class_setup_vtable (klass);
3819 if (mono_class_has_failure (klass))
3822 if (is_generic_parameter (&klass->byval_arg))
3823 nslots = mono_class_get_vtable_size (klass->parent);
3825 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3826 if (nslots >= sizeof (method_slots_default) * 8) {
3827 method_slots = g_new0 (guint32, nslots / 32 + 1);
3829 method_slots = method_slots_default;
3830 memset (method_slots, 0, sizeof (method_slots_default));
3833 mono_class_setup_methods (klass);
3834 mono_class_setup_vtable (klass);
3835 if (mono_class_has_failure (klass))
3839 while ((method = mono_class_get_methods (klass, &iter))) {
3841 if (method->slot != -1) {
3842 g_assert (method->slot < nslots);
3843 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3845 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3846 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3849 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3851 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3852 if (bflags & BFLAGS_Public)
3854 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3860 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3861 if (bflags & BFLAGS_Static)
3862 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3865 if (bflags & BFLAGS_Instance)
3873 if (compare_func (name, method->name))
3878 g_ptr_array_add (array, method);
3880 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3882 if (method_slots != method_slots_default)
3883 g_free (method_slots);
3888 if (method_slots != method_slots_default)
3889 g_free (method_slots);
3890 g_ptr_array_free (array, TRUE);
3892 g_assert (mono_class_has_failure (klass));
3893 mono_error_set_for_class_failure (error, klass);
3897 ICALL_EXPORT GPtrArray*
3898 ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionType *type, const char *mname, guint32 bflags, MonoBoolean ignore_case)
3901 GPtrArray *method_array;
3904 klass = mono_class_from_mono_type (type->type);
3905 if (type->type->byref) {
3906 return g_ptr_array_new ();
3909 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &error);
3910 mono_error_set_pending_exception (&error);
3911 return method_array;
3914 ICALL_EXPORT GPtrArray*
3915 ves_icall_RuntimeType_GetConstructors_native (MonoReflectionType *type, guint32 bflags)
3917 MonoClass *startklass, *klass;
3920 gpointer iter = NULL;
3921 GPtrArray *res_array;
3924 if (type->type->byref) {
3925 return g_ptr_array_new ();
3928 klass = startklass = mono_class_from_mono_type (type->type);
3930 mono_class_setup_methods (klass);
3931 if (mono_class_has_failure (klass)) {
3932 mono_error_init (&error);
3933 mono_error_set_for_class_failure (&error, klass);
3934 mono_error_set_pending_exception (&error);
3938 res_array = g_ptr_array_sized_new (4); /* FIXME, guestimating */
3941 while ((method = mono_class_get_methods (klass, &iter))) {
3943 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3945 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3946 if (bflags & BFLAGS_Public)
3949 if (bflags & BFLAGS_NonPublic)
3955 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3956 if (bflags & BFLAGS_Static)
3957 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3960 if (bflags & BFLAGS_Instance)
3966 g_ptr_array_add (res_array, method);
3973 property_hash (gconstpointer data)
3975 MonoProperty *prop = (MonoProperty*)data;
3977 return g_str_hash (prop->name);
3981 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
3983 if (method1->slot != -1 && method1->slot == method2->slot)
3986 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
3987 if (method1->is_inflated)
3988 method1 = ((MonoMethodInflated*) method1)->declaring;
3989 if (method2->is_inflated)
3990 method2 = ((MonoMethodInflated*) method2)->declaring;
3993 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3997 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3999 // Properties are hide-by-name-and-signature
4000 if (!g_str_equal (prop1->name, prop2->name))
4003 /* If we see a property in a generic method, we want to
4004 compare the generic signatures, not the inflated signatures
4005 because we might conflate two properties that were
4009 public T this[T t] { getter { return t; } } // method 1
4010 public U this[U u] { getter { return u; } } // method 2
4013 If we see int Foo<int,int>::Item[int] we need to know if
4014 the indexer came from method 1 or from method 2, and we
4015 shouldn't conflate them. (Bugzilla 36283)
4017 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4020 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4027 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4032 return method_nonpublic (accessor, start_klass);
4035 ICALL_EXPORT GPtrArray*
4036 ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionType *type, gchar *propname, guint32 bflags, MonoBoolean ignore_case)
4039 MonoClass *startklass, *klass;
4044 int (*compare_func) (const char *s1, const char *s2) = NULL;
4046 GHashTable *properties = NULL;
4047 GPtrArray *res_array;
4049 if (type->type->byref) {
4050 return g_ptr_array_new ();
4053 mono_error_init (&error);
4055 klass = startklass = mono_class_from_mono_type (type->type);
4057 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4059 res_array = g_ptr_array_sized_new (8); /*This the average for ASP.NET types*/
4061 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4063 mono_class_setup_methods (klass);
4064 mono_class_setup_vtable (klass);
4065 if (mono_class_has_failure (klass)) {
4066 mono_error_set_for_class_failure (&error, klass);
4071 while ((prop = mono_class_get_properties (klass, &iter))) {
4077 flags = method->flags;
4080 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4081 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4082 if (bflags & BFLAGS_Public)
4084 } else if (bflags & BFLAGS_NonPublic) {
4085 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4086 property_accessor_nonpublic(prop->set, startklass == klass)) {
4093 if (flags & METHOD_ATTRIBUTE_STATIC) {
4094 if (bflags & BFLAGS_Static)
4095 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4098 if (bflags & BFLAGS_Instance)
4106 if (propname != NULL && compare_func (propname, prop->name))
4109 if (g_hash_table_lookup (properties, prop))
4112 g_ptr_array_add (res_array, prop);
4114 g_hash_table_insert (properties, prop, prop);
4116 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4119 g_hash_table_destroy (properties);
4126 g_hash_table_destroy (properties);
4127 g_ptr_array_free (res_array, TRUE);
4129 mono_error_set_pending_exception (&error);
4135 event_hash (gconstpointer data)
4137 MonoEvent *event = (MonoEvent*)data;
4139 return g_str_hash (event->name);
4143 event_equal (MonoEvent *event1, MonoEvent *event2)
4145 // Events are hide-by-name
4146 return g_str_equal (event1->name, event2->name);
4149 ICALL_EXPORT GPtrArray*
4150 ves_icall_RuntimeType_GetEvents_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
4153 MonoClass *startklass, *klass;
4158 int (*compare_func) (const char *s1, const char *s2) = NULL;
4159 GHashTable *events = NULL;
4160 GPtrArray *res_array;
4162 if (type->type->byref) {
4163 return g_ptr_array_new ();
4166 mono_error_init (&error);
4168 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4170 res_array = g_ptr_array_sized_new (4);
4172 klass = startklass = mono_class_from_mono_type (type->type);
4174 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4176 mono_class_setup_methods (klass);
4177 mono_class_setup_vtable (klass);
4178 if (mono_class_has_failure (klass)) {
4179 mono_error_set_for_class_failure (&error, klass);
4184 while ((event = mono_class_get_events (klass, &iter))) {
4186 method = event->add;
4188 method = event->remove;
4190 method = event->raise;
4192 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4193 if (bflags & BFLAGS_Public)
4195 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4196 if (bflags & BFLAGS_NonPublic)
4201 if (bflags & BFLAGS_NonPublic)
4207 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4208 if (bflags & BFLAGS_Static)
4209 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4212 if (bflags & BFLAGS_Instance)
4217 if (bflags & BFLAGS_Instance)
4222 if (utf8_name != NULL && compare_func (event->name, utf8_name))
4225 if (g_hash_table_lookup (events, event))
4228 g_ptr_array_add (res_array, event);
4230 g_hash_table_insert (events, event, event);
4232 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4235 g_hash_table_destroy (events);
4241 g_hash_table_destroy (events);
4243 g_ptr_array_free (res_array, TRUE);
4245 mono_error_set_pending_exception (&error);
4249 ICALL_EXPORT GPtrArray *
4250 ves_icall_RuntimeType_GetNestedTypes_native (MonoReflectionType *type, char *str, guint32 bflags)
4256 GPtrArray *res_array;
4258 if (type->type->byref) {
4259 return g_ptr_array_new ();
4262 klass = mono_class_from_mono_type (type->type);
4265 * If a nested type is generic, return its generic type definition.
4266 * Note that this means that the return value is essentially the set
4267 * of nested types of the generic type definition of @klass.
4269 * A note in MSDN claims that a generic type definition can have
4270 * nested types that aren't generic. In any case, the container of that
4271 * nested type would be the generic type definition.
4273 if (klass->generic_class)
4274 klass = klass->generic_class->container_class;
4276 res_array = g_ptr_array_new ();
4279 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4281 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4282 if (bflags & BFLAGS_Public)
4285 if (bflags & BFLAGS_NonPublic)
4291 if (str != NULL && strcmp (nested->name, str))
4294 g_ptr_array_add (res_array, &nested->byval_arg);
4300 ICALL_EXPORT MonoReflectionType*
4301 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4304 MonoReflectionType *ret;
4306 MonoType *type = NULL;
4307 MonoTypeNameParse info;
4308 gboolean type_resolve;
4310 /* On MS.NET, this does not fire a TypeResolve event */
4311 type_resolve = TRUE;
4312 str = mono_string_to_utf8_checked (name, &error);
4313 if (mono_error_set_pending_exception (&error))
4315 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4316 if (!mono_reflection_parse_type (str, &info)) {
4318 mono_reflection_free_type_info (&info);
4320 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4323 /*g_print ("failed parse\n");*/
4327 if (info.assembly.name) {
4329 mono_reflection_free_type_info (&info);
4331 /* 1.0 and 2.0 throw different exceptions */
4332 if (mono_defaults.generic_ilist_class)
4333 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4335 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4341 if (module != NULL) {
4342 if (module->image) {
4343 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4344 if (!is_ok (&error)) {
4346 mono_reflection_free_type_info (&info);
4347 mono_error_set_pending_exception (&error);
4354 if (assembly_is_dynamic (assembly->assembly)) {
4355 /* Enumerate all modules */
4356 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4360 if (abuilder->modules) {
4361 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4362 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4363 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4364 if (!is_ok (&error)) {
4366 mono_reflection_free_type_info (&info);
4367 mono_error_set_pending_exception (&error);
4375 if (!type && abuilder->loaded_modules) {
4376 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4377 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4378 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4379 if (!is_ok (&error)) {
4381 mono_reflection_free_type_info (&info);
4382 mono_error_set_pending_exception (&error);
4391 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4392 if (!is_ok (&error)) {
4394 mono_reflection_free_type_info (&info);
4395 mono_error_set_pending_exception (&error);
4400 mono_reflection_free_type_info (&info);
4402 MonoException *e = NULL;
4405 e = mono_get_exception_type_load (name, NULL);
4408 mono_set_pending_exception (e);
4412 if (type->type == MONO_TYPE_CLASS) {
4413 MonoClass *klass = mono_type_get_class (type);
4415 /* need to report exceptions ? */
4416 if (throwOnError && mono_class_has_failure (klass)) {
4417 /* report SecurityException (or others) that occured when loading the assembly */
4418 MonoException *exc = mono_class_get_exception_for_failure (klass);
4419 mono_set_pending_exception (exc);
4424 /* g_print ("got it\n"); */
4425 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4426 mono_error_set_pending_exception (&error);
4432 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4435 gchar *shadow_ini_file;
4438 /* Check for shadow-copied assembly */
4439 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4440 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4442 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4443 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4449 g_free (shadow_ini_file);
4450 if (content != NULL) {
4453 *filename = content;
4460 ICALL_EXPORT MonoString *
4461 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4463 MonoDomain *domain = mono_object_domain (assembly);
4464 MonoAssembly *mass = assembly->assembly;
4465 MonoString *res = NULL;
4470 if (g_path_is_absolute (mass->image->name)) {
4471 absolute = g_strdup (mass->image->name);
4472 dirname = g_path_get_dirname (absolute);
4474 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4475 dirname = g_strdup (mass->basedir);
4478 replace_shadow_path (domain, dirname, &absolute);
4483 for (i = strlen (absolute) - 1; i >= 0; i--)
4484 if (absolute [i] == '\\')
4489 uri = g_filename_to_uri (absolute, NULL, NULL);
4491 const char *prepend = "file://";
4493 if (*absolute == '/' && *(absolute + 1) == '/') {
4496 prepend = "file:///";
4499 uri = g_strconcat (prepend, absolute, NULL);
4503 res = mono_string_new (domain, uri);
4510 ICALL_EXPORT MonoBoolean
4511 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4513 MonoAssembly *mass = assembly->assembly;
4515 return mass->in_gac;
4518 ICALL_EXPORT MonoReflectionAssembly*
4519 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4524 MonoImageOpenStatus status;
4525 MonoReflectionAssembly* result = NULL;
4527 name = mono_string_to_utf8_checked (mname, &error);
4528 if (mono_error_set_pending_exception (&error))
4530 res = mono_assembly_load_with_partial_name (name, &status);
4536 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4538 mono_error_set_pending_exception (&error);
4542 ICALL_EXPORT MonoStringHandle
4543 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4545 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4546 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4547 return mono_string_new_handle (domain, mono_image_get_filename (assembly->image), error);
4550 ICALL_EXPORT MonoBoolean
4551 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4553 return assembly->assembly->ref_only;
4556 ICALL_EXPORT MonoStringHandle
4557 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4559 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4560 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4562 return mono_string_new_handle (domain, assembly->image->version, error);
4565 ICALL_EXPORT MonoReflectionMethod*
4566 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4569 MonoReflectionMethod *res = NULL;
4572 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4576 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4577 if (!mono_error_ok (&error))
4580 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4583 if (!mono_error_ok (&error))
4584 mono_error_set_pending_exception (&error);
4588 ICALL_EXPORT MonoReflectionModule*
4589 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4592 MonoReflectionModule *result = NULL;
4593 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4594 if (!mono_error_ok (&error))
4595 mono_error_set_pending_exception (&error);
4599 ICALL_EXPORT MonoArray*
4600 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4603 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4604 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4605 if (mono_error_set_pending_exception (&error))
4610 for (i = 0; i < table->rows; ++i) {
4611 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4612 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4617 ICALL_EXPORT MonoStringHandle
4618 ves_icall_System_Reflection_Assembly_GetAotId (MonoError *error)
4621 guint8 aotid_sum = 0;
4622 MonoDomain* domain = mono_domain_get ();
4624 if (!domain->entry_assembly || !domain->entry_assembly->image)
4627 guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
4629 for (i = 0; i < 16; ++i)
4630 aotid_sum |= (*aotid)[i];
4635 gchar *guid = mono_guid_to_string((guint8*) aotid);
4636 MonoStringHandle res = mono_string_new_handle (domain, guid, error);
4642 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4644 static MonoMethod *create_version = NULL;
4648 mono_error_init (error);
4651 if (!create_version) {
4652 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4653 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4654 g_assert (create_version);
4655 mono_method_desc_free (desc);
4661 args [3] = &revision;
4662 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4663 return_val_if_nok (error, NULL);
4665 mono_runtime_invoke_checked (create_version, result, args, error);
4666 return_val_if_nok (error, NULL);
4671 ICALL_EXPORT MonoArray*
4672 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4676 MonoDomain *domain = mono_object_domain (assembly);
4678 static MonoMethod *create_culture = NULL;
4679 MonoImage *image = assembly->assembly->image;
4683 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4686 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4687 if (mono_error_set_pending_exception (&error))
4691 if (count > 0 && !create_culture) {
4692 MonoMethodDesc *desc = mono_method_desc_new (
4693 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4694 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4695 g_assert (create_culture);
4696 mono_method_desc_free (desc);
4699 for (i = 0; i < count; i++) {
4700 MonoObject *version;
4701 MonoReflectionAssemblyName *aname;
4702 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4704 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4706 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4707 domain, mono_class_get_assembly_name_class (), &error);
4708 if (mono_error_set_pending_exception (&error))
4711 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4713 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4714 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4715 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4716 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4717 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4718 aname->versioncompat = 1; /* SameMachine (default) */
4719 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4721 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4722 if (mono_error_set_pending_exception (&error))
4725 MONO_OBJECT_SETREF (aname, version, version);
4727 if (create_culture) {
4729 MonoBoolean assembly_ref = 1;
4730 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4731 args [1] = &assembly_ref;
4733 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4734 if (mono_error_set_pending_exception (&error))
4737 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4740 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4741 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4742 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4744 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4745 /* public key token isn't copied - the class library will
4746 automatically generate it from the public key if required */
4747 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4748 if (mono_error_set_pending_exception (&error))
4751 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4752 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4754 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4755 if (mono_error_set_pending_exception (&error))
4758 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4759 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
4762 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
4763 if (mono_error_set_pending_exception (&error))
4766 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4769 /* note: this function doesn't return the codebase on purpose (i.e. it can
4770 be used under partial trust as path information isn't present). */
4772 mono_array_setref (result, i, aname);
4777 /* move this in some file in mono/util/ */
4779 g_concat_dir_and_file (const char *dir, const char *file)
4781 g_return_val_if_fail (dir != NULL, NULL);
4782 g_return_val_if_fail (file != NULL, NULL);
4785 * If the directory name doesn't have a / on the end, we need
4786 * to add one so we get a proper path to the file
4788 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4789 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4791 return g_strconcat (dir, file, NULL);
4795 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4798 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4800 guint32 cols [MONO_MANIFEST_SIZE];
4801 guint32 impl, file_idx;
4805 char *n = mono_string_to_utf8_checked (name, &error);
4806 if (mono_error_set_pending_exception (&error))
4809 for (i = 0; i < table->rows; ++i) {
4810 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4811 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4812 if (strcmp (val, n) == 0)
4816 if (i == table->rows)
4819 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4822 * this code should only be called after obtaining the
4823 * ResourceInfo and handling the other cases.
4825 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4826 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4828 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4833 module = assembly->assembly->image;
4836 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4837 if (mono_error_set_pending_exception (&error))
4839 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4841 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4844 ICALL_EXPORT gboolean
4845 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4848 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4850 guint32 cols [MONO_MANIFEST_SIZE];
4851 guint32 file_cols [MONO_FILE_SIZE];
4855 n = mono_string_to_utf8_checked (name, &error);
4856 if (mono_error_set_pending_exception (&error))
4858 for (i = 0; i < table->rows; ++i) {
4859 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4860 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4861 if (strcmp (val, n) == 0)
4865 if (i == table->rows)
4868 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4869 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4872 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4873 case MONO_IMPLEMENTATION_FILE:
4874 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4875 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4876 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4877 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4878 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4879 if (file_cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA)
4882 info->location = RESOURCE_LOCATION_EMBEDDED;
4885 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4886 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4887 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4888 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4889 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4890 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4892 mono_set_pending_exception (ex);
4895 MonoReflectionAssembly *assm_obj;
4896 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4898 mono_error_set_pending_exception (&error);
4901 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4903 /* Obtain info recursively */
4904 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4905 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4908 case MONO_IMPLEMENTATION_EXP_TYPE:
4909 g_assert_not_reached ();
4917 ICALL_EXPORT MonoObject*
4918 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4921 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4922 MonoArray *result = NULL;
4927 /* check hash if needed */
4929 n = mono_string_to_utf8_checked (name, &error);
4930 if (mono_error_set_pending_exception (&error))
4933 for (i = 0; i < table->rows; ++i) {
4934 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4935 if (strcmp (val, n) == 0) {
4938 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4939 fn = mono_string_new (mono_object_domain (assembly), n);
4941 return (MonoObject*)fn;
4949 for (i = 0; i < table->rows; ++i) {
4950 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4954 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
4955 if (mono_error_set_pending_exception (&error))
4960 for (i = 0; i < table->rows; ++i) {
4961 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4962 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4963 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4964 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4969 return (MonoObject*)result;
4972 ICALL_EXPORT MonoArray*
4973 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4976 MonoDomain *domain = mono_domain_get();
4979 int i, j, file_count = 0;
4980 MonoImage **modules;
4981 guint32 module_count, real_module_count;
4982 MonoTableInfo *table;
4983 guint32 cols [MONO_FILE_SIZE];
4984 MonoImage *image = assembly->assembly->image;
4986 g_assert (image != NULL);
4987 g_assert (!assembly_is_dynamic (assembly->assembly));
4989 table = &image->tables [MONO_TABLE_FILE];
4990 file_count = table->rows;
4992 modules = image->modules;
4993 module_count = image->module_count;
4995 real_module_count = 0;
4996 for (i = 0; i < module_count; ++i)
4998 real_module_count ++;
5000 klass = mono_class_get_module_class ();
5001 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5002 if (mono_error_set_pending_exception (&error))
5005 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5006 if (mono_error_set_pending_exception (&error))
5009 mono_array_setref (res, 0, image_obj);
5011 for (i = 0; i < module_count; ++i)
5013 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5014 if (mono_error_set_pending_exception (&error))
5016 mono_array_setref (res, j, rm);
5020 for (i = 0; i < file_count; ++i, ++j) {
5021 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5022 if (cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA) {
5023 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5024 if (mono_error_set_pending_exception (&error))
5026 mono_array_setref (res, j, rm);
5029 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5031 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5032 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5035 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5036 if (mono_error_set_pending_exception (&error))
5038 mono_array_setref (res, j, rm);
5045 ICALL_EXPORT MonoReflectionMethod*
5046 ves_icall_GetCurrentMethod (void)
5048 MonoReflectionMethod *res = NULL;
5051 MonoMethod *m = mono_method_get_last_managed ();
5054 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5058 while (m->is_inflated)
5059 m = ((MonoMethodInflated*)m)->declaring;
5061 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5062 mono_error_set_pending_exception (&error);
5068 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5071 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5074 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5075 //method is inflated, we should inflate it on the other class
5076 MonoGenericContext ctx;
5077 ctx.method_inst = inflated->context.method_inst;
5078 ctx.class_inst = inflated->context.class_inst;
5079 if (klass->generic_class)
5080 ctx.class_inst = klass->generic_class->context.class_inst;
5081 else if (klass->generic_container)
5082 ctx.class_inst = klass->generic_container->context.class_inst;
5083 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5084 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5088 mono_class_setup_methods (method->klass);
5089 if (mono_class_has_failure (method->klass))
5091 for (i = 0; i < method->klass->method.count; ++i) {
5092 if (method->klass->methods [i] == method) {
5097 mono_class_setup_methods (klass);
5098 if (mono_class_has_failure (klass))
5100 g_assert (offset >= 0 && offset < klass->method.count);
5101 return klass->methods [offset];
5104 ICALL_EXPORT MonoReflectionMethod*
5105 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check)
5107 MonoReflectionMethod *res = NULL;
5110 if (type && generic_check) {
5111 klass = mono_class_from_mono_type (type);
5112 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5115 if (method->klass != klass) {
5116 method = mono_method_get_equivalent_method (method, klass);
5121 klass = mono_class_from_mono_type (type);
5123 klass = method->klass;
5124 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5125 mono_error_set_pending_exception (&error);
5129 ICALL_EXPORT MonoReflectionMethodBody*
5130 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5133 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5134 mono_error_set_pending_exception (&error);
5138 ICALL_EXPORT MonoReflectionAssembly*
5139 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5142 MonoReflectionAssembly *result;
5143 MonoMethod *dest = NULL;
5145 mono_stack_walk_no_il (get_executing, &dest);
5147 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5149 mono_error_set_pending_exception (&error);
5154 ICALL_EXPORT MonoReflectionAssembly*
5155 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5158 MonoReflectionAssembly *result;
5159 MonoDomain* domain = mono_domain_get ();
5161 if (!domain->entry_assembly)
5164 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5166 mono_error_set_pending_exception (&error);
5170 ICALL_EXPORT MonoReflectionAssembly*
5171 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5176 MonoReflectionAssembly *result;
5179 mono_stack_walk_no_il (get_executing, &dest);
5181 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5185 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5188 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5190 mono_error_set_pending_exception (&error);
5194 ICALL_EXPORT MonoStringHandle
5195 ves_icall_System_RuntimeType_getFullName (MonoReflectionTypeHandle object, gboolean full_name,
5196 gboolean assembly_qualified, MonoError *error)
5198 MonoDomain *domain = mono_object_domain (MONO_HANDLE_RAW (object));
5199 MonoType *type = MONO_HANDLE_RAW (object)->type;
5200 MonoTypeNameFormat format;
5201 MonoStringHandle res;
5205 format = assembly_qualified ?
5206 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5207 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5209 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5211 name = mono_type_get_name_full (type, format);
5213 return NULL_HANDLE_STRING;
5215 if (full_name && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
5217 return NULL_HANDLE_STRING;
5220 res = mono_string_new_handle (domain, name, error);
5227 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5230 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5232 mono_class_init_checked (klass, &error);
5233 mono_error_set_pending_exception (&error);
5234 return mono_security_core_clr_class_level (klass);
5238 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5240 MonoClassField *field = rfield->field;
5241 return mono_security_core_clr_field_level (field, TRUE);
5245 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5247 MonoMethod *method = rfield->method;
5248 return mono_security_core_clr_method_level (method, TRUE);
5252 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)
5254 static MonoMethod *create_culture = NULL;
5258 const char *pkey_ptr;
5260 MonoBoolean assembly_ref = 0;
5262 mono_error_init (error);
5264 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5265 aname->major = name->major;
5266 aname->minor = name->minor;
5267 aname->build = name->build;
5268 aname->flags = name->flags;
5269 aname->revision = name->revision;
5270 aname->hashalg = name->hash_alg;
5271 aname->versioncompat = 1; /* SameMachine (default) */
5272 aname->processor_architecture = name->arch;
5274 if (by_default_version) {
5275 MonoObject *version;
5277 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5278 return_if_nok (error);
5280 MONO_OBJECT_SETREF (aname, version, version);
5284 if (absolute != NULL && *absolute != '\0') {
5285 const gchar *prepend = "file://";
5288 codebase = g_strdup (absolute);
5293 for (i = strlen (codebase) - 1; i >= 0; i--)
5294 if (codebase [i] == '\\')
5297 if (*codebase == '/' && *(codebase + 1) == '/') {
5300 prepend = "file:///";
5304 result = g_strconcat (prepend, codebase, NULL);
5310 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5314 if (!create_culture) {
5315 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5316 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5317 g_assert (create_culture);
5318 mono_method_desc_free (desc);
5321 if (name->culture) {
5322 args [0] = mono_string_new (domain, name->culture);
5323 args [1] = &assembly_ref;
5325 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5326 return_if_nok (error);
5328 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5331 if (name->public_key) {
5332 pkey_ptr = (char*)name->public_key;
5333 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5335 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5336 return_if_nok (error);
5337 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5338 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5339 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5340 } else if (default_publickey) {
5341 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5342 return_if_nok (error);
5343 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5344 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5347 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5348 if (name->public_key_token [0]) {
5352 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5353 return_if_nok (error);
5355 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5356 p = mono_array_addr (keyToken, char, 0);
5358 for (i = 0, j = 0; i < 8; i++) {
5359 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5360 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5363 } else if (default_token) {
5364 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5365 return_if_nok (error);
5366 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5370 ICALL_EXPORT MonoString *
5371 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5373 MonoDomain *domain = mono_object_domain (assembly);
5374 MonoAssembly *mass = assembly->assembly;
5378 name = mono_stringify_assembly_name (&mass->aname);
5379 res = mono_string_new (domain, name);
5385 ICALL_EXPORT MonoAssemblyName *
5386 ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
5388 return &mass->aname;
5392 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5396 MonoImageOpenStatus status = MONO_IMAGE_OK;
5399 MonoAssemblyName name;
5402 filename = mono_string_to_utf8_checked (fname, &error);
5403 if (mono_error_set_pending_exception (&error))
5406 dirname = g_path_get_dirname (filename);
5407 replace_shadow_path (mono_domain_get (), dirname, &filename);
5410 image = mono_image_open (filename, &status);
5416 if (status == MONO_IMAGE_IMAGE_INVALID)
5417 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5419 exc = mono_get_exception_file_not_found2 (NULL, fname);
5420 mono_set_pending_exception (exc);
5424 res = mono_assembly_fill_assembly_name (image, &name);
5426 mono_image_close (image);
5428 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5432 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5433 mono_error_set_pending_exception (&error);
5435 mono_image_close (image);
5439 ICALL_EXPORT MonoBoolean
5440 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5441 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5443 MonoBoolean result = FALSE;
5444 MonoDeclSecurityEntry entry;
5446 /* SecurityAction.RequestMinimum */
5447 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5448 *minimum = entry.blob;
5449 *minLength = entry.size;
5452 /* SecurityAction.RequestOptional */
5453 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5454 *optional = entry.blob;
5455 *optLength = entry.size;
5458 /* SecurityAction.RequestRefuse */
5459 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5460 *refused = entry.blob;
5461 *refLength = entry.size;
5469 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5471 guint32 attrs, visibility;
5473 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5474 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5475 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5478 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5484 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5486 MonoReflectionType *rt;
5489 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5492 mono_error_init (error);
5494 /* we start the count from 1 because we skip the special type <Module> */
5497 for (i = 1; i < tdef->rows; ++i) {
5498 if (mono_module_type_is_visible (tdef, image, i + 1))
5502 count = tdef->rows - 1;
5504 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5505 return_val_if_nok (error, NULL);
5506 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5507 return_val_if_nok (error, NULL);
5509 for (i = 1; i < tdef->rows; ++i) {
5510 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5511 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5514 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5515 return_val_if_nok (error, NULL);
5517 mono_array_setref (res, count, rt);
5519 MonoException *ex = mono_error_convert_to_exception (error);
5520 mono_array_setref (*exceptions, count, ex);
5529 ICALL_EXPORT MonoArray*
5530 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5533 MonoArray *res = NULL;
5534 MonoArray *exceptions = NULL;
5535 MonoImage *image = NULL;
5536 MonoTableInfo *table = NULL;
5539 int i, len, ex_count;
5541 domain = mono_object_domain (assembly);
5543 g_assert (!assembly_is_dynamic (assembly->assembly));
5544 image = assembly->assembly->image;
5545 table = &image->tables [MONO_TABLE_FILE];
5546 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5547 if (mono_error_set_pending_exception (&error))
5550 /* Append data from all modules in the assembly */
5551 for (i = 0; i < table->rows; ++i) {
5552 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5553 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5558 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5559 if (mono_error_set_pending_exception (&error))
5563 /* Append the new types to the end of the array */
5564 if (mono_array_length (res2) > 0) {
5566 MonoArray *res3, *ex3;
5568 len1 = mono_array_length (res);
5569 len2 = mono_array_length (res2);
5571 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5572 if (mono_error_set_pending_exception (&error))
5574 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5575 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5578 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5579 if (mono_error_set_pending_exception (&error))
5581 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5582 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5589 /* the ReflectionTypeLoadException must have all the types (Types property),
5590 * NULL replacing types which throws an exception. The LoaderException must
5591 * contain all exceptions for NULL items.
5594 len = mono_array_length (res);
5597 for (i = 0; i < len; i++) {
5598 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5602 klass = mono_type_get_class (t->type);
5603 if ((klass != NULL) && mono_class_has_failure (klass)) {
5604 /* keep the class in the list */
5605 list = g_list_append (list, klass);
5606 /* and replace Type with NULL */
5607 mono_array_setref (res, i, NULL);
5614 if (list || ex_count) {
5616 MonoException *exc = NULL;
5617 MonoArray *exl = NULL;
5618 int j, length = g_list_length (list) + ex_count;
5620 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5621 if (mono_error_set_pending_exception (&error)) {
5625 /* Types for which mono_class_get_checked () succeeded */
5626 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5627 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5628 mono_array_setref (exl, i, exc);
5630 /* Types for which it don't */
5631 for (j = 0; j < mono_array_length (exceptions); ++j) {
5632 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5634 g_assert (i < length);
5635 mono_array_setref (exl, i, exc);
5642 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5643 if (!is_ok (&error)) {
5644 mono_error_set_pending_exception (&error);
5647 mono_set_pending_exception (exc);
5655 ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname)
5657 mono_assembly_name_free (aname);
5660 ICALL_EXPORT gboolean
5661 ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, gboolean *is_version_definited, gboolean *is_token_defined)
5663 *is_version_definited = *is_token_defined = FALSE;
5665 return mono_assembly_name_parse_full (name, aname, TRUE, is_version_definited, is_token_defined);
5668 ICALL_EXPORT MonoReflectionType*
5669 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5672 MonoReflectionType *ret;
5673 MonoDomain *domain = mono_object_domain (module);
5676 g_assert (module->image);
5678 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5679 /* These images do not have a global type */
5682 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5683 if (!mono_error_ok (&error)) {
5684 mono_error_set_pending_exception (&error);
5688 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5689 if (!mono_error_ok (&error)) {
5690 mono_error_set_pending_exception (&error);
5698 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5700 /*if (module->image)
5701 mono_image_close (module->image);*/
5704 ICALL_EXPORT MonoStringHandle
5705 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModuleHandle refmodule, MonoError *error)
5707 MonoDomain *domain = MONO_HANDLE_DOMAIN (refmodule);
5708 MonoImage *image = MONO_HANDLE_RAW (refmodule)->image;
5711 return mono_string_new_handle (domain, image->guid, error);
5714 ICALL_EXPORT gpointer
5715 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5718 if (module->image && module->image->is_module_handle)
5719 return module->image->raw_data;
5722 return (gpointer) (-1);
5726 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5728 if (image_is_dynamic (image)) {
5729 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5730 *pe_kind = dyn->pe_kind;
5731 *machine = dyn->machine;
5734 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5735 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5740 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5742 return (image->md_version_major << 16) | (image->md_version_minor);
5745 ICALL_EXPORT MonoArray*
5746 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5749 MonoArray *exceptions;
5752 if (!module->image) {
5753 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
5754 mono_error_set_pending_exception (&error);
5759 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5760 if (mono_error_set_pending_exception (&error))
5763 for (i = 0; i < mono_array_length (exceptions); ++i) {
5764 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5766 mono_set_pending_exception (ex);
5775 mono_memberref_is_method (MonoImage *image, guint32 token)
5777 if (!image_is_dynamic (image)) {
5778 guint32 cols [MONO_MEMBERREF_SIZE];
5780 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5781 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5782 mono_metadata_decode_blob_size (sig, &sig);
5783 return (*sig != 0x6);
5786 MonoClass *handle_class;
5788 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5789 mono_error_cleanup (&error); /* just probing, ignore error */
5793 return mono_defaults.methodhandle_class == handle_class;
5798 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5801 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5802 mono_array_addr (type_args, MonoType*, 0));
5804 context->class_inst = NULL;
5806 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5807 mono_array_addr (method_args, MonoType*, 0));
5809 context->method_inst = NULL;
5812 ICALL_EXPORT MonoType*
5813 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5816 int table = mono_metadata_token_table (token);
5817 int index = mono_metadata_token_index (token);
5818 MonoGenericContext context;
5821 *resolve_error = ResolveTokenError_Other;
5823 /* Validate token */
5824 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5825 (table != MONO_TABLE_TYPESPEC)) {
5826 *resolve_error = ResolveTokenError_BadTable;
5830 if (image_is_dynamic (image)) {
5831 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5832 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5833 mono_error_cleanup (&error);
5834 return klass ? &klass->byval_arg : NULL;
5837 init_generic_context_from_args (&context, type_args, method_args);
5838 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5839 mono_error_cleanup (&error);
5840 return klass ? &klass->byval_arg : NULL;
5843 if ((index <= 0) || (index > image->tables [table].rows)) {
5844 *resolve_error = ResolveTokenError_OutOfRange;
5848 init_generic_context_from_args (&context, type_args, method_args);
5849 klass = mono_class_get_checked (image, token, &error);
5851 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5852 if (!mono_error_ok (&error)) {
5853 mono_error_set_pending_exception (&error);
5858 return &klass->byval_arg;
5863 ICALL_EXPORT MonoMethod*
5864 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5867 int table = mono_metadata_token_table (token);
5868 int index = mono_metadata_token_index (token);
5869 MonoGenericContext context;
5872 *resolve_error = ResolveTokenError_Other;
5874 /* Validate token */
5875 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5876 (table != MONO_TABLE_MEMBERREF)) {
5877 *resolve_error = ResolveTokenError_BadTable;
5881 if (image_is_dynamic (image)) {
5882 if (table == MONO_TABLE_METHOD) {
5883 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5884 mono_error_cleanup (&error);
5888 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5889 *resolve_error = ResolveTokenError_BadTable;
5893 init_generic_context_from_args (&context, type_args, method_args);
5894 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5895 mono_error_cleanup (&error);
5899 if ((index <= 0) || (index > image->tables [table].rows)) {
5900 *resolve_error = ResolveTokenError_OutOfRange;
5903 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5904 *resolve_error = ResolveTokenError_BadTable;
5908 init_generic_context_from_args (&context, type_args, method_args);
5909 method = mono_get_method_checked (image, token, NULL, &context, &error);
5910 mono_error_set_pending_exception (&error);
5915 ICALL_EXPORT MonoString*
5916 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5919 int index = mono_metadata_token_index (token);
5921 *resolve_error = ResolveTokenError_Other;
5923 /* Validate token */
5924 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5925 *resolve_error = ResolveTokenError_BadTable;
5929 if (image_is_dynamic (image)) {
5930 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5931 mono_error_cleanup (&error);
5935 if ((index <= 0) || (index >= image->heap_us.size)) {
5936 *resolve_error = ResolveTokenError_OutOfRange;
5940 /* FIXME: What to do if the index points into the middle of a string ? */
5942 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
5943 mono_error_set_pending_exception (&error);
5947 ICALL_EXPORT MonoClassField*
5948 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5952 int table = mono_metadata_token_table (token);
5953 int index = mono_metadata_token_index (token);
5954 MonoGenericContext context;
5955 MonoClassField *field;
5957 *resolve_error = ResolveTokenError_Other;
5959 /* Validate token */
5960 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5961 *resolve_error = ResolveTokenError_BadTable;
5965 if (image_is_dynamic (image)) {
5966 if (table == MONO_TABLE_FIELD) {
5967 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5968 mono_error_cleanup (&error);
5972 if (mono_memberref_is_method (image, token)) {
5973 *resolve_error = ResolveTokenError_BadTable;
5977 init_generic_context_from_args (&context, type_args, method_args);
5978 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5979 mono_error_cleanup (&error);
5983 if ((index <= 0) || (index > image->tables [table].rows)) {
5984 *resolve_error = ResolveTokenError_OutOfRange;
5987 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5988 *resolve_error = ResolveTokenError_BadTable;
5992 init_generic_context_from_args (&context, type_args, method_args);
5993 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5994 mono_error_set_pending_exception (&error);
6000 ICALL_EXPORT MonoObject*
6001 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6005 int table = mono_metadata_token_table (token);
6007 *error = ResolveTokenError_Other;
6010 case MONO_TABLE_TYPEDEF:
6011 case MONO_TABLE_TYPEREF:
6012 case MONO_TABLE_TYPESPEC: {
6013 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6015 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6016 mono_error_set_pending_exception (&merror);
6023 case MONO_TABLE_METHOD:
6024 case MONO_TABLE_METHODSPEC: {
6025 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6027 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6028 mono_error_set_pending_exception (&merror);
6034 case MONO_TABLE_FIELD: {
6035 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6037 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6038 mono_error_set_pending_exception (&merror);
6044 case MONO_TABLE_MEMBERREF:
6045 if (mono_memberref_is_method (image, token)) {
6046 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6048 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6049 mono_error_set_pending_exception (&merror);
6056 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6058 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6059 mono_error_set_pending_exception (&merror);
6068 *error = ResolveTokenError_BadTable;
6074 ICALL_EXPORT MonoArray*
6075 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6078 int table = mono_metadata_token_table (token);
6079 int idx = mono_metadata_token_index (token);
6080 MonoTableInfo *tables = image->tables;
6085 *resolve_error = ResolveTokenError_OutOfRange;
6087 /* FIXME: Support other tables ? */
6088 if (table != MONO_TABLE_STANDALONESIG)
6091 if (image_is_dynamic (image))
6094 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6097 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6099 ptr = mono_metadata_blob_heap (image, sig);
6100 len = mono_metadata_decode_blob_size (ptr, &ptr);
6102 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6103 if (mono_error_set_pending_exception (&error))
6105 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6109 ICALL_EXPORT MonoBoolean
6110 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6116 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6122 check_for_invalid_type (MonoClass *klass, MonoError *error)
6127 mono_error_init (error);
6129 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6132 name = mono_type_get_full_name (klass);
6133 str = mono_string_new (mono_domain_get (), name);
6135 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6138 ICALL_EXPORT MonoReflectionType *
6139 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6142 MonoReflectionType *ret;
6143 MonoClass *klass, *aklass;
6145 klass = mono_class_from_mono_type (type->type);
6146 check_for_invalid_type (klass, &error);
6147 mono_error_set_pending_exception (&error);
6149 if (rank == 0) //single dimentional array
6150 aklass = mono_array_class_get (klass, 1);
6152 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6154 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6155 mono_error_set_pending_exception (&error);
6160 ICALL_EXPORT MonoReflectionType *
6161 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6164 MonoReflectionType *ret;
6167 klass = mono_class_from_mono_type (type->type);
6168 mono_class_init_checked (klass, &error);
6169 if (mono_error_set_pending_exception (&error))
6172 check_for_invalid_type (klass, &error);
6173 if (mono_error_set_pending_exception (&error))
6176 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6177 mono_error_set_pending_exception (&error);
6182 ICALL_EXPORT MonoReflectionType *
6183 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6186 MonoReflectionType *ret;
6187 MonoClass *klass, *pklass;
6189 klass = mono_class_from_mono_type (type->type);
6190 mono_class_init_checked (klass, &error);
6191 if (mono_error_set_pending_exception (&error))
6193 check_for_invalid_type (klass, &error);
6194 if (mono_error_set_pending_exception (&error))
6197 pklass = mono_ptr_class_get (type->type);
6199 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6200 mono_error_set_pending_exception (&error);
6205 ICALL_EXPORT MonoObject *
6206 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6207 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6210 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6211 MonoObject *delegate;
6213 MonoMethod *method = info->method;
6214 MonoMethodSignature *sig = mono_method_signature(method);
6216 mono_class_init_checked (delegate_class, &error);
6217 if (mono_error_set_pending_exception (&error))
6220 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6221 /* FIXME improve this exception message */
6222 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6224 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6225 mono_error_set_pending_exception (&error);
6229 if (mono_security_core_clr_enabled ()) {
6230 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6231 if (throwOnBindFailure)
6232 mono_error_set_pending_exception (&error);
6234 mono_error_cleanup (&error);
6239 if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
6240 if (!method->is_inflated) {
6241 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"));
6246 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6247 if (mono_error_set_pending_exception (&error))
6250 if (method_is_dynamic (method)) {
6251 /* Creating a trampoline would leak memory */
6252 func = mono_compile_method_checked (method, &error);
6253 if (mono_error_set_pending_exception (&error))
6256 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6257 method = mono_object_get_virtual_method (target, method);
6258 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6259 if (mono_error_set_pending_exception (&error))
6261 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6264 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6265 if (mono_error_set_pending_exception (&error))
6270 ICALL_EXPORT MonoMulticastDelegate *
6271 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6274 MonoMulticastDelegate *ret;
6276 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6278 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6279 if (mono_error_set_pending_exception (&error))
6282 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6287 ICALL_EXPORT MonoReflectionMethod*
6288 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6290 MonoReflectionMethod *ret = NULL;
6292 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6293 mono_error_set_pending_exception (&error);
6299 static inline gint32
6300 mono_array_get_byte_length (MonoArray *array)
6306 klass = array->obj.vtable->klass;
6308 if (array->bounds == NULL)
6309 length = array->max_length;
6312 for (i = 0; i < klass->rank; ++ i)
6313 length *= array->bounds [i].length;
6316 switch (klass->element_class->byval_arg.type) {
6319 case MONO_TYPE_BOOLEAN:
6323 case MONO_TYPE_CHAR:
6331 return length * sizeof (gpointer);
6342 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6344 return mono_array_get_byte_length (array);
6348 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6350 return mono_array_get (array, gint8, idx);
6354 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6356 mono_array_set (array, gint8, idx, value);
6359 ICALL_EXPORT MonoBoolean
6360 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6362 guint8 *src_buf, *dest_buf;
6365 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6369 g_assert (count >= 0);
6371 /* This is called directly from the class libraries without going through the managed wrapper */
6372 MONO_CHECK_ARG_NULL (src, FALSE);
6373 MONO_CHECK_ARG_NULL (dest, FALSE);
6375 /* watch out for integer overflow */
6376 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6379 src_buf = (guint8 *)src->vector + src_offset;
6380 dest_buf = (guint8 *)dest->vector + dest_offset;
6383 memcpy (dest_buf, src_buf, count);
6385 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6390 #ifndef DISABLE_REMOTING
6391 ICALL_EXPORT MonoObject *
6392 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6395 MonoDomain *domain = mono_object_domain (this_obj);
6397 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6398 MonoTransparentProxy *tp;
6402 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6403 if (mono_error_set_pending_exception (&error))
6406 tp = (MonoTransparentProxy*) res;
6408 MONO_OBJECT_SETREF (tp, rp, rp);
6409 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6410 klass = mono_class_from_mono_type (type);
6412 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6413 mono_class_setup_vtable (klass);
6414 if (mono_class_has_failure (klass)) {
6415 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6419 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6420 if (mono_error_set_pending_exception (&error))
6422 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6423 if (mono_error_set_pending_exception (&error))
6426 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6427 if (mono_error_set_pending_exception (&error))
6432 ICALL_EXPORT MonoReflectionType *
6433 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6436 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6437 mono_error_set_pending_exception (&error);
6443 /* System.Environment */
6446 ves_icall_System_Environment_get_UserName (void)
6448 /* using glib is more portable */
6449 return mono_string_new (mono_domain_get (), g_get_user_name ());
6453 ICALL_EXPORT MonoString *
6454 ves_icall_System_Environment_get_MachineName (void)
6456 #if defined (HOST_WIN32)
6461 len = MAX_COMPUTERNAME_LENGTH + 1;
6462 buf = g_new (gunichar2, len);
6465 if (GetComputerName (buf, (PDWORD) &len)) {
6467 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6468 mono_error_set_pending_exception (&error);
6473 #elif !defined(DISABLE_SOCKETS)
6477 #if defined _SC_HOST_NAME_MAX
6478 n = sysconf (_SC_HOST_NAME_MAX);
6482 buf = g_malloc (n+1);
6484 if (gethostname (buf, n) == 0){
6486 result = mono_string_new (mono_domain_get (), buf);
6493 return mono_string_new (mono_domain_get (), "mono");
6498 ves_icall_System_Environment_get_Platform (void)
6500 #if defined (TARGET_WIN32)
6503 #elif defined(__MACH__)
6506 // Notice that the value is hidden from user code, and only exposed
6507 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6508 // define and making assumptions based on Unix/128/4 values before there
6509 // was a MacOS define. Lots of code would assume that not-Unix meant
6510 // Windows, but in this case, it would be OSX.
6519 ICALL_EXPORT MonoString *
6520 ves_icall_System_Environment_get_NewLine (void)
6522 #if defined (HOST_WIN32)
6523 return mono_string_new (mono_domain_get (), "\r\n");
6525 return mono_string_new (mono_domain_get (), "\n");
6529 ICALL_EXPORT MonoBoolean
6530 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6532 #if SIZEOF_VOID_P == 8
6536 gboolean isWow64Process = FALSE;
6537 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6538 return (MonoBoolean)isWow64Process;
6540 #elif defined(HAVE_SYS_UTSNAME_H)
6541 struct utsname name;
6543 if (uname (&name) >= 0) {
6544 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6551 ICALL_EXPORT MonoStringHandle
6552 ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
6556 if (utf8_name == NULL)
6557 return NULL_HANDLE_STRING;
6559 value = g_getenv (utf8_name);
6562 return NULL_HANDLE_STRING;
6564 return mono_string_new_handle (mono_domain_get (), value, error);
6568 * There is no standard way to get at environ.
6571 #ifndef __MINGW32_VERSION
6572 #if defined(__APPLE__)
6573 #if defined (TARGET_OSX)
6574 /* Apple defines this in crt_externs.h but doesn't provide that header for
6575 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6576 * in fact exist on all implementations (so far)
6578 gchar ***_NSGetEnviron(void);
6579 #define environ (*_NSGetEnviron())
6581 static char *mono_environ[1] = { NULL };
6582 #define environ mono_environ
6583 #endif /* defined (TARGET_OSX) */
6591 ICALL_EXPORT MonoArray *
6592 ves_icall_System_Environment_GetCoomandLineArgs (void)
6595 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6596 mono_error_set_pending_exception (&error);
6600 ICALL_EXPORT MonoArray *
6601 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6613 env_strings = GetEnvironmentStrings();
6616 env_string = env_strings;
6617 while (*env_string != '\0') {
6618 /* weird case that MS seems to skip */
6619 if (*env_string != '=')
6621 while (*env_string != '\0')
6627 domain = mono_domain_get ();
6628 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6629 if (mono_error_set_pending_exception (&error))
6634 env_string = env_strings;
6635 while (*env_string != '\0') {
6636 /* weird case that MS seems to skip */
6637 if (*env_string != '=') {
6638 equal_str = wcschr(env_string, '=');
6639 g_assert(equal_str);
6641 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6642 if (mono_error_set_pending_exception (&error))
6645 mono_array_setref (names, n, str);
6648 while (*env_string != '\0')
6653 FreeEnvironmentStrings (env_strings);
6667 for (e = environ; *e != 0; ++ e)
6670 domain = mono_domain_get ();
6671 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6672 if (mono_error_set_pending_exception (&error))
6676 for (e = environ; *e != 0; ++ e) {
6677 parts = g_strsplit (*e, "=", 2);
6679 str = mono_string_new (domain, *parts);
6680 mono_array_setref (names, n, str);
6693 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6696 gunichar2 *utf16_name, *utf16_value;
6698 gchar *utf8_name, *utf8_value;
6703 utf16_name = mono_string_to_utf16 (name);
6704 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6705 SetEnvironmentVariable (utf16_name, NULL);
6706 g_free (utf16_name);
6710 utf16_value = mono_string_to_utf16 (value);
6712 SetEnvironmentVariable (utf16_name, utf16_value);
6714 g_free (utf16_name);
6715 g_free (utf16_value);
6717 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6718 if (mono_error_set_pending_exception (&error))
6721 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6722 g_unsetenv (utf8_name);
6727 utf8_value = mono_string_to_utf8_checked (value, &error);
6728 if (!mono_error_ok (&error)) {
6730 mono_error_set_pending_exception (&error);
6733 g_setenv (utf8_name, utf8_value, TRUE);
6736 g_free (utf8_value);
6741 ves_icall_System_Environment_Exit (int result)
6743 mono_environment_exitcode_set (result);
6745 /* FIXME: There are some cleanup hangs that should be worked out, but
6746 * if the program is going to exit, everything will be cleaned up when
6747 * NaCl exits anyway.
6749 #ifndef __native_client__
6750 if (!mono_runtime_try_shutdown ())
6751 mono_thread_exit ();
6753 /* Suspend all managed threads since the runtime is going away */
6754 mono_thread_suspend_all_other_threads ();
6756 mono_runtime_quit ();
6759 /* we may need to do some cleanup here... */
6763 ICALL_EXPORT MonoStringHandle
6764 ves_icall_System_Environment_GetGacPath (MonoError *error)
6766 return mono_string_new_handle (mono_domain_get (), mono_assembly_getrootdir (), error);
6769 ICALL_EXPORT MonoString*
6770 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6772 #if defined (HOST_WIN32)
6773 #ifndef CSIDL_FLAG_CREATE
6774 #define CSIDL_FLAG_CREATE 0x8000
6777 WCHAR path [MAX_PATH];
6778 /* Create directory if no existing */
6779 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6784 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6785 mono_error_set_pending_exception (&error);
6789 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6791 return mono_string_new (mono_domain_get (), "");
6794 ICALL_EXPORT MonoArray *
6795 ves_icall_System_Environment_GetLogicalDrives (void)
6798 gunichar2 buf [256], *ptr, *dname;
6800 guint initial_size = 127, size = 128;
6803 MonoString *drivestr;
6804 MonoDomain *domain = mono_domain_get ();
6810 while (size > initial_size) {
6811 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6812 if (size > initial_size) {
6815 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6816 initial_size = size;
6830 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
6831 if (mono_error_set_pending_exception (&error))
6838 while (*u16) { u16++; len ++; }
6839 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6840 if (mono_error_set_pending_exception (&error))
6843 mono_array_setref (result, ndrives++, drivestr);
6854 ICALL_EXPORT MonoString *
6855 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6858 gunichar2 volume_name [MAX_PATH + 1];
6860 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6862 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
6863 mono_error_set_pending_exception (&error);
6867 ICALL_EXPORT MonoStringHandle
6868 ves_icall_System_Environment_InternalGetHome (MonoError *error)
6870 return mono_string_new_handle (mono_domain_get (), g_get_home_dir (), error);
6873 static const char *encodings [] = {
6875 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6876 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6877 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6879 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6880 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6881 "x_unicode_2_0_utf_7",
6883 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6884 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6886 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6889 "unicodefffe", "utf_16be",
6896 * Returns the internal codepage, if the value of "int_code_page" is
6897 * 1 at entry, and we can not compute a suitable code page number,
6898 * returns the code page as a string
6900 ICALL_EXPORT MonoString*
6901 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6906 char *codepage = NULL;
6908 int want_name = *int_code_page;
6911 *int_code_page = -1;
6913 g_get_charset (&cset);
6914 c = codepage = strdup (cset);
6915 for (c = codepage; *c; c++){
6916 if (isascii (*c) && isalpha (*c))
6921 /* g_print ("charset: %s\n", cset); */
6923 /* handle some common aliases */
6926 for (i = 0; p != 0; ){
6929 p = encodings [++i];
6932 if (strcmp (p, codepage) == 0){
6933 *int_code_page = code;
6936 p = encodings [++i];
6939 if (strstr (codepage, "utf_8") != NULL)
6940 *int_code_page |= 0x10000000;
6943 if (want_name && *int_code_page == -1)
6944 return mono_string_new (mono_domain_get (), cset);
6949 ICALL_EXPORT MonoBoolean
6950 ves_icall_System_Environment_get_HasShutdownStarted (void)
6952 if (mono_runtime_is_shutting_down ())
6955 if (mono_domain_is_unloading (mono_domain_get ()))
6962 ves_icall_System_Environment_BroadcastSettingChange (void)
6965 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6971 ves_icall_System_Environment_get_TickCount (void)
6973 /* this will overflow after ~24 days */
6974 return (gint32) (mono_msec_boottime () & 0xffffffff);
6978 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6983 #ifndef DISABLE_REMOTING
6984 ICALL_EXPORT MonoBoolean
6985 ves_icall_IsTransparentProxy (MonoObject *proxy)
6990 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6996 ICALL_EXPORT MonoReflectionMethod *
6997 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6998 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7000 MonoReflectionMethod *ret = NULL;
7005 MonoMethod **vtable;
7006 MonoMethod *res = NULL;
7008 MONO_CHECK_ARG_NULL (rtype, NULL);
7009 MONO_CHECK_ARG_NULL (rmethod, NULL);
7011 method = rmethod->method;
7012 klass = mono_class_from_mono_type (rtype->type);
7013 mono_class_init_checked (klass, &error);
7014 if (mono_error_set_pending_exception (&error))
7017 if (MONO_CLASS_IS_INTERFACE (klass))
7020 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7023 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7024 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7030 mono_class_setup_vtable (klass);
7031 vtable = klass->vtable;
7033 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7034 gboolean variance_used = FALSE;
7035 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7036 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7038 res = vtable [offs + method->slot];
7040 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7043 if (method->slot != -1)
7044 res = vtable [method->slot];
7050 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7051 mono_error_set_pending_exception (&error);
7056 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7062 klass = mono_class_from_mono_type (type->type);
7063 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7064 if (!is_ok (&error)) {
7065 mono_error_set_pending_exception (&error);
7069 mono_vtable_set_is_remote (vtable, enable);
7072 #else /* DISABLE_REMOTING */
7075 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7077 g_assert_not_reached ();
7082 ICALL_EXPORT MonoObject *
7083 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7090 domain = mono_object_domain (type);
7091 klass = mono_class_from_mono_type (type->type);
7092 mono_class_init_checked (klass, &error);
7093 if (mono_error_set_pending_exception (&error))
7096 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7097 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7101 if (klass->rank >= 1) {
7102 g_assert (klass->rank == 1);
7103 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7104 mono_error_set_pending_exception (&error);
7107 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7108 if (!is_ok (&error)) {
7109 mono_error_set_pending_exception (&error);
7112 /* Bypass remoting object creation check */
7113 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7114 mono_error_set_pending_exception (&error);
7120 ICALL_EXPORT MonoStringHandle
7121 ves_icall_System_IO_get_temp_path (MonoError *error)
7123 return mono_string_new_handle (mono_domain_get (), g_get_tmp_dir (), error);
7126 #ifndef PLATFORM_NO_DRIVEINFO
7127 ICALL_EXPORT MonoBoolean
7128 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7129 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7133 ULARGE_INTEGER wapi_free_bytes_avail;
7134 ULARGE_INTEGER wapi_total_number_of_bytes;
7135 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7137 *error = ERROR_SUCCESS;
7138 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7139 &wapi_total_number_of_free_bytes);
7142 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7143 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7144 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7146 *free_bytes_avail = 0;
7147 *total_number_of_bytes = 0;
7148 *total_number_of_free_bytes = 0;
7149 *error = GetLastError ();
7155 ICALL_EXPORT guint32
7156 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7158 return GetDriveType (mono_string_chars (root_path_name));
7162 ICALL_EXPORT gpointer
7163 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7166 gpointer result = mono_compile_method_checked (method, &error);
7167 mono_error_set_pending_exception (&error);
7171 ICALL_EXPORT MonoString *
7172 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7177 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7179 #if defined (HOST_WIN32)
7180 /* Avoid mixing '/' and '\\' */
7183 for (i = strlen (path) - 1; i >= 0; i--)
7184 if (path [i] == '/')
7188 mcpath = mono_string_new (mono_domain_get (), path);
7194 /* this is an icall */
7196 get_bundled_app_config (void)
7199 const gchar *app_config;
7202 gchar *config_file_name, *config_file_path;
7203 gsize len, config_file_path_length, config_ext_length;
7206 domain = mono_domain_get ();
7207 file = domain->setup->configuration_file;
7208 if (!file || file->length == 0)
7211 // Retrieve config file and remove the extension
7212 config_file_name = mono_string_to_utf8_checked (file, &error);
7213 if (mono_error_set_pending_exception (&error))
7215 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7216 if (!config_file_path)
7217 config_file_path = config_file_name;
7219 config_file_path_length = strlen (config_file_path);
7220 config_ext_length = strlen (".config");
7221 if (config_file_path_length <= config_ext_length)
7224 len = config_file_path_length - config_ext_length;
7225 module = (gchar *)g_malloc0 (len + 1);
7226 memcpy (module, config_file_path, len);
7227 // Get the config file from the module name
7228 app_config = mono_config_string_for_assembly_file (module);
7231 if (config_file_name != config_file_path)
7232 g_free (config_file_name);
7233 g_free (config_file_path);
7238 return mono_string_new (mono_domain_get (), app_config);
7241 /* this is an icall */
7242 static MonoStringHandle
7243 get_bundled_machine_config (MonoError *error)
7245 const gchar *machine_config;
7247 machine_config = mono_get_machine_config ();
7249 if (!machine_config)
7250 return NULL_HANDLE_STRING;
7252 return mono_string_new_handle (mono_domain_get (), machine_config, error);
7255 ICALL_EXPORT MonoString *
7256 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7261 path = g_path_get_dirname (mono_get_config_dir ());
7263 #if defined (HOST_WIN32)
7264 /* Avoid mixing '/' and '\\' */
7267 for (i = strlen (path) - 1; i >= 0; i--)
7268 if (path [i] == '/')
7272 ipath = mono_string_new (mono_domain_get (), path);
7278 ICALL_EXPORT gboolean
7279 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7281 MonoPEResourceDataEntry *entry;
7284 if (!assembly || !result || !size)
7289 image = assembly->assembly->image;
7290 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7294 *result = mono_image_rva_map (image, entry->rde_data_offset);
7299 *size = entry->rde_size;
7304 ICALL_EXPORT MonoBoolean
7305 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7307 return mono_is_debugger_attached ();
7310 ICALL_EXPORT MonoBoolean
7311 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7313 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7314 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7320 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7322 if (mono_get_runtime_callbacks ()->debug_log)
7323 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7327 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7329 #if defined (HOST_WIN32)
7330 OutputDebugString (mono_string_chars (message));
7332 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7336 /* Only used for value types */
7337 ICALL_EXPORT MonoObject *
7338 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7345 domain = mono_object_domain (type);
7346 klass = mono_class_from_mono_type (type->type);
7347 mono_class_init_checked (klass, &error);
7348 if (mono_error_set_pending_exception (&error))
7351 if (mono_class_is_nullable (klass))
7352 /* No arguments -> null */
7355 result = mono_object_new_checked (domain, klass, &error);
7356 mono_error_set_pending_exception (&error);
7360 ICALL_EXPORT MonoReflectionMethod *
7361 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7363 MonoReflectionMethod *ret = NULL;
7366 MonoClass *klass, *parent;
7367 MonoGenericContext *generic_inst = NULL;
7368 MonoMethod *method = m->method;
7369 MonoMethod *result = NULL;
7372 if (method->klass == NULL)
7375 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7376 MONO_CLASS_IS_INTERFACE (method->klass) ||
7377 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7380 slot = mono_method_get_vtable_slot (method);
7384 klass = method->klass;
7385 if (klass->generic_class) {
7386 generic_inst = mono_class_get_context (klass);
7387 klass = klass->generic_class->container_class;
7391 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7392 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7393 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7394 or klass is the generic container class and generic_inst is the instantiation.
7396 when we go to the parent, if the parent is an open constructed type, we need to
7397 replace the type parameters by the definitions from the generic_inst, and then take it
7398 apart again into the klass and the generic_inst.
7400 For cases like this:
7401 class C<T> : B<T, int> {
7402 public override void Foo () { ... }
7404 class B<U,V> : A<HashMap<U,V>> {
7405 public override void Foo () { ... }
7408 public virtual void Foo () { ... }
7411 if at each iteration the parent isn't open, we can skip inflating it. if at some
7412 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7415 MonoGenericContext *parent_inst = NULL;
7416 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7417 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7418 if (!mono_error_ok (&error)) {
7419 mono_error_set_pending_exception (&error);
7423 if (parent->generic_class) {
7424 parent_inst = mono_class_get_context (parent);
7425 parent = parent->generic_class->container_class;
7428 mono_class_setup_vtable (parent);
7429 if (parent->vtable_size <= slot)
7432 generic_inst = parent_inst;
7435 klass = klass->parent;
7438 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7439 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7440 if (!mono_error_ok (&error)) {
7441 mono_error_set_pending_exception (&error);
7445 generic_inst = NULL;
7447 if (klass->generic_class) {
7448 generic_inst = mono_class_get_context (klass);
7449 klass = klass->generic_class->container_class;
7455 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7456 if (!mono_error_ok (&error)) {
7457 mono_error_set_pending_exception (&error);
7462 if (klass == method->klass)
7465 /*This is possible if definition == FALSE.
7466 * Do it here to be really sure we don't read invalid memory.
7468 if (slot >= klass->vtable_size)
7471 mono_class_setup_vtable (klass);
7473 result = klass->vtable [slot];
7474 if (result == NULL) {
7475 /* It is an abstract method */
7476 gpointer iter = NULL;
7477 while ((result = mono_class_get_methods (klass, &iter)))
7478 if (result->slot == slot)
7485 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7486 mono_error_set_pending_exception (&error);
7490 ICALL_EXPORT MonoString*
7491 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7493 MonoMethod *method = m->method;
7495 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7500 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7502 iter->sig = *(MonoMethodSignature**)argsp;
7504 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7505 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7508 /* FIXME: it's not documented what start is exactly... */
7512 iter->args = argsp + sizeof (gpointer);
7514 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7516 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7519 ICALL_EXPORT MonoTypedRef
7520 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7522 guint32 i, arg_size;
7526 i = iter->sig->sentinelpos + iter->next_arg;
7528 g_assert (i < iter->sig->param_count);
7530 res.type = iter->sig->params [i];
7531 res.klass = mono_class_from_mono_type (res.type);
7532 arg_size = mono_type_stack_size (res.type, &align);
7533 #if defined(__arm__) || defined(__mips__)
7534 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7536 res.value = iter->args;
7537 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7538 /* Values are stored as 8 byte register sized objects, but 'value'
7539 * is dereferenced as a pointer in other routines.
7541 res.value = (char*)res.value + 4;
7543 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7544 if (arg_size <= sizeof (gpointer)) {
7546 int padding = arg_size - mono_type_size (res.type, &dummy);
7547 res.value = (guint8*)res.value + padding;
7550 iter->args = (char*)iter->args + arg_size;
7553 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7558 ICALL_EXPORT MonoTypedRef
7559 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7561 guint32 i, arg_size;
7565 i = iter->sig->sentinelpos + iter->next_arg;
7567 g_assert (i < iter->sig->param_count);
7569 while (i < iter->sig->param_count) {
7570 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7572 res.type = iter->sig->params [i];
7573 res.klass = mono_class_from_mono_type (res.type);
7574 /* FIXME: endianess issue... */
7575 arg_size = mono_type_stack_size (res.type, &align);
7576 #if defined(__arm__) || defined(__mips__)
7577 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7579 res.value = iter->args;
7580 iter->args = (char*)iter->args + arg_size;
7582 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7585 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7593 ICALL_EXPORT MonoType*
7594 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7598 i = iter->sig->sentinelpos + iter->next_arg;
7600 g_assert (i < iter->sig->param_count);
7602 return iter->sig->params [i];
7605 ICALL_EXPORT MonoObject*
7606 mono_TypedReference_ToObject (MonoTypedRef* tref)
7609 MonoObject *result = NULL;
7610 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7611 MonoObject** objp = (MonoObject **)tref->value;
7615 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7616 mono_error_set_pending_exception (&error);
7620 ICALL_EXPORT MonoTypedRef
7621 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7624 MonoReflectionField *f;
7626 MonoType *ftype = NULL;
7630 memset (&res, 0, sizeof (res));
7633 g_assert (mono_array_length (fields) > 0);
7635 klass = target->vtable->klass;
7637 for (i = 0; i < mono_array_length (fields); ++i) {
7638 f = mono_array_get (fields, MonoReflectionField*, i);
7640 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7643 if (f->field->parent != klass) {
7644 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7648 p = (guint8*)target + f->field->offset;
7650 p += f->field->offset - sizeof (MonoObject);
7651 klass = mono_class_from_mono_type (f->field->type);
7652 ftype = f->field->type;
7656 res.klass = mono_class_from_mono_type (ftype);
7663 prelink_method (MonoMethod *method, MonoError *error)
7665 const char *exc_class, *exc_arg;
7667 mono_error_init (error);
7668 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7670 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7672 mono_error_set_exception_instance (error,
7673 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7676 /* create the wrapper, too? */
7680 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7684 prelink_method (method->method, &error);
7685 mono_error_set_pending_exception (&error);
7689 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7692 MonoClass *klass = mono_class_from_mono_type (type->type);
7694 gpointer iter = NULL;
7696 mono_class_init_checked (klass, &error);
7697 if (mono_error_set_pending_exception (&error))
7700 while ((m = mono_class_get_methods (klass, &iter))) {
7701 prelink_method (m, &error);
7702 if (mono_error_set_pending_exception (&error))
7707 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7709 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7710 gint32 const **exponents,
7711 gunichar2 const **digitLowerTable,
7712 gunichar2 const **digitUpperTable,
7713 gint64 const **tenPowersList,
7714 gint32 const **decHexDigits)
7716 *mantissas = Formatter_MantissaBitsTable;
7717 *exponents = Formatter_TensExponentTable;
7718 *digitLowerTable = Formatter_DigitLowerTable;
7719 *digitUpperTable = Formatter_DigitUpperTable;
7720 *tenPowersList = Formatter_TenPowersList;
7721 *decHexDigits = Formatter_DecHexDigits;
7725 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7726 * and avoid useless allocations.
7729 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7731 MonoReflectionType *rt;
7735 mono_error_init (error);
7736 for (i = 0; i < type->num_mods; ++i) {
7737 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7742 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7743 return_val_if_nok (error, NULL);
7745 for (i = 0; i < type->num_mods; ++i) {
7746 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7747 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7748 return_val_if_nok (error, NULL);
7750 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7751 return_val_if_nok (error, NULL);
7753 mono_array_setref (res, count, rt);
7760 ICALL_EXPORT MonoArray*
7761 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7764 MonoType *type = param->ClassImpl->type;
7765 MonoClass *member_class = mono_object_class (param->MemberImpl);
7766 MonoMethod *method = NULL;
7769 MonoMethodSignature *sig;
7772 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7773 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7774 method = rmethod->method;
7775 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7776 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7777 if (!(method = prop->property->get))
7778 method = prop->property->set;
7781 char *type_name = mono_type_get_full_name (member_class);
7782 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7783 MonoException *ex = mono_get_exception_not_supported (msg);
7786 mono_set_pending_exception (ex);
7790 image = method->klass->image;
7791 pos = param->PositionImpl;
7792 sig = mono_method_signature (method);
7796 type = sig->params [pos];
7798 res = type_array_from_modifiers (image, type, optional, &error);
7799 mono_error_set_pending_exception (&error);
7804 get_property_type (MonoProperty *prop)
7806 MonoMethodSignature *sig;
7808 sig = mono_method_signature (prop->get);
7810 } else if (prop->set) {
7811 sig = mono_method_signature (prop->set);
7812 return sig->params [sig->param_count - 1];
7817 ICALL_EXPORT MonoArray*
7818 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7821 MonoType *type = get_property_type (property->property);
7822 MonoImage *image = property->klass->image;
7827 res = type_array_from_modifiers (image, type, optional, &error);
7828 mono_error_set_pending_exception (&error);
7833 *Construct a MonoType suited to be used to decode a constant blob object.
7835 * @type is the target type which will be constructed
7836 * @blob_type is the blob type, for example, that comes from the constant table
7837 * @real_type is the expected constructed type.
7840 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7842 type->type = blob_type;
7843 type->data.klass = NULL;
7844 if (blob_type == MONO_TYPE_CLASS)
7845 type->data.klass = mono_defaults.object_class;
7846 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7847 /* For enums, we need to use the base type */
7848 type->type = MONO_TYPE_VALUETYPE;
7849 type->data.klass = mono_class_from_mono_type (real_type);
7851 type->data.klass = mono_class_from_mono_type (real_type);
7854 ICALL_EXPORT MonoObject*
7855 property_info_get_default_value (MonoReflectionProperty *property)
7859 MonoProperty *prop = property->property;
7860 MonoType *type = get_property_type (prop);
7861 MonoDomain *domain = mono_object_domain (property);
7862 MonoTypeEnum def_type;
7863 const char *def_value;
7866 mono_class_init (prop->parent);
7868 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7869 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7873 def_value = mono_class_get_property_default_value (prop, &def_type);
7875 mono_type_from_blob_type (&blob_type, def_type, type);
7876 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7878 mono_error_set_pending_exception (&error);
7882 ICALL_EXPORT MonoBoolean
7883 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7886 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7887 MonoCustomAttrInfo *cinfo;
7890 mono_class_init_checked (attr_class, &error);
7891 if (mono_error_set_pending_exception (&error))
7894 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7895 if (!is_ok (&error)) {
7896 mono_error_set_pending_exception (&error);
7901 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7903 mono_custom_attrs_free (cinfo);
7907 ICALL_EXPORT MonoArray*
7908 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7910 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7915 mono_class_init_checked (attr_class, &error);
7916 if (mono_error_set_pending_exception (&error))
7920 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7921 if (!mono_error_ok (&error)) {
7922 mono_error_set_pending_exception (&error);
7929 ICALL_EXPORT MonoArray*
7930 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7934 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7935 mono_error_set_pending_exception (&error);
7940 ICALL_EXPORT MonoString*
7941 ves_icall_Mono_Runtime_GetDisplayName (void)
7944 MonoString *display_name;
7946 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7947 display_name = mono_string_new (mono_domain_get (), info);
7949 return display_name;
7952 ICALL_EXPORT MonoString*
7953 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7956 MonoString *message;
7960 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7961 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7964 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7966 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7967 if (mono_error_set_pending_exception (&error))
7974 ICALL_EXPORT gpointer
7975 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
7977 return GetCurrentProcess ();
7980 ICALL_EXPORT MonoBoolean
7981 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
7983 return GetExitCodeProcess (handle, (guint32*) exitcode);
7986 ICALL_EXPORT MonoBoolean
7987 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
7989 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
7990 return CloseHandle (handle);
7992 return CloseProcess (handle);
7996 ICALL_EXPORT MonoBoolean
7997 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
7999 return TerminateProcess (handle, exitcode);
8003 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8006 return WaitForInputIdle (handle, milliseconds);
8008 /*TODO: Not implemented*/
8009 return WAIT_TIMEOUT;
8013 ICALL_EXPORT MonoBoolean
8014 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8016 return GetProcessWorkingSetSize (handle, min, max);
8019 ICALL_EXPORT MonoBoolean
8020 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8022 return SetProcessWorkingSetSize (handle, min, max);
8025 ICALL_EXPORT MonoBoolean
8026 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8028 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8032 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8034 return mono_process_current_pid ();
8038 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8040 return GetPriorityClass (handle);
8043 ICALL_EXPORT MonoBoolean
8044 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8046 return SetPriorityClass (handle, priorityClass);
8049 #ifndef DISABLE_ICALL_TABLES
8051 #define ICALL_TYPE(id,name,first)
8052 #define ICALL(id,name,func) Icall_ ## id,
8053 #define HANDLES(inner) inner
8056 #include "metadata/icall-def.h"
8062 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8063 #define ICALL(id,name,func)
8065 #define HANDLES(inner) inner
8067 #include "metadata/icall-def.h"
8073 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8074 #define ICALL(id,name,func)
8076 #define HANDLES(inner) inner
8078 guint16 first_icall;
8081 static const IcallTypeDesc
8082 icall_type_descs [] = {
8083 #include "metadata/icall-def.h"
8087 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8090 #define HANDLES(inner) inner
8092 #define ICALL_TYPE(id,name,first)
8095 #ifdef HAVE_ARRAY_ELEM_INIT
8096 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8097 #define MSGSTRFIELD1(line) str##line
8099 static const struct msgstrtn_t {
8100 #define ICALL(id,name,func)
8102 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8103 #include "metadata/icall-def.h"
8105 } icall_type_names_str = {
8106 #define ICALL_TYPE(id,name,first) (name),
8107 #include "metadata/icall-def.h"
8110 static const guint16 icall_type_names_idx [] = {
8111 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8112 #include "metadata/icall-def.h"
8115 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8117 static const struct msgstr_t {
8119 #define ICALL_TYPE(id,name,first)
8120 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8121 #include "metadata/icall-def.h"
8123 } icall_names_str = {
8124 #define ICALL(id,name,func) (name),
8125 #include "metadata/icall-def.h"
8128 static const guint16 icall_names_idx [] = {
8129 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8130 #include "metadata/icall-def.h"
8133 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8139 #define ICALL_TYPE(id,name,first) name,
8140 #define ICALL(id,name,func)
8141 static const char* const
8142 icall_type_names [] = {
8143 #include "metadata/icall-def.h"
8147 #define icall_type_name_get(id) (icall_type_names [(id)])
8151 #define ICALL_TYPE(id,name,first)
8152 #define ICALL(id,name,func) name,
8153 static const char* const
8155 #include "metadata/icall-def.h"
8158 #define icall_name_get(id) icall_names [(id)]
8160 #endif /* !HAVE_ARRAY_ELEM_INIT */
8163 #define HANDLES(inner) inner
8166 #define ICALL_TYPE(id,name,first)
8167 #define ICALL(id,name,func) func,
8168 static const gconstpointer
8169 icall_functions [] = {
8170 #include "metadata/icall-def.h"
8174 #ifdef ENABLE_ICALL_SYMBOL_MAP
8176 #define HANDLES(inner) inner
8179 #define ICALL_TYPE(id,name,first)
8180 #define ICALL(id,name,func) #func,
8181 static const gconstpointer
8182 icall_symbols [] = {
8183 #include "metadata/icall-def.h"
8190 #define ICALL_TYPE(id,name,first)
8191 #define ICALL(id,name,func) 0,
8193 #define HANDLES(inner) 1,
8195 icall_uses_handles [] = {
8196 #include "metadata/icall-def.h"
8201 #endif /* DISABLE_ICALL_TABLES */
8203 static mono_mutex_t icall_mutex;
8204 static GHashTable *icall_hash = NULL;
8205 static GHashTable *jit_icall_hash_name = NULL;
8206 static GHashTable *jit_icall_hash_addr = NULL;
8209 mono_icall_init (void)
8211 #ifndef DISABLE_ICALL_TABLES
8214 /* check that tables are sorted: disable in release */
8217 const char *prev_class = NULL;
8218 const char *prev_method;
8220 for (i = 0; i < Icall_type_num; ++i) {
8221 const IcallTypeDesc *desc;
8224 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8225 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8226 prev_class = icall_type_name_get (i);
8227 desc = &icall_type_descs [i];
8228 num_icalls = icall_desc_num_icalls (desc);
8229 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8230 for (j = 0; j < num_icalls; ++j) {
8231 const char *methodn = icall_name_get (desc->first_icall + j);
8232 if (prev_method && strcmp (prev_method, methodn) >= 0)
8233 g_print ("method %s should come before method %s\n", methodn, prev_method);
8234 prev_method = methodn;
8240 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8241 mono_os_mutex_init (&icall_mutex);
8245 mono_icall_lock (void)
8247 mono_locks_os_acquire (&icall_mutex, IcallLock);
8251 mono_icall_unlock (void)
8253 mono_locks_os_release (&icall_mutex, IcallLock);
8257 mono_icall_cleanup (void)
8259 g_hash_table_destroy (icall_hash);
8260 g_hash_table_destroy (jit_icall_hash_name);
8261 g_hash_table_destroy (jit_icall_hash_addr);
8262 mono_os_mutex_destroy (&icall_mutex);
8266 * mono_add_internal_call:
8267 * @name: method specification to surface to the managed world
8268 * @method: pointer to a C method to invoke when the method is called
8270 * This method surfaces the C function pointed by @method as a method
8271 * that has been surfaced in managed code with the method specified in
8272 * @name as an internal call.
8274 * Internal calls are surfaced to all app domains loaded and they are
8275 * accessibly by a type with the specified name.
8277 * You must provide a fully qualified type name, that is namespaces
8278 * and type name, followed by a colon and the method name, with an
8279 * optional signature to bind.
8281 * For example, the following are all valid declarations:
8283 * "MyApp.Services.ScriptService:Accelerate"
8284 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8286 * You use method parameters in cases where there might be more than
8287 * one surface method to managed code. That way you can register different
8288 * internal calls for different method overloads.
8290 * The internal calls are invoked with no marshalling. This means that .NET
8291 * types like System.String are exposed as `MonoString *` parameters. This is
8292 * different than the way that strings are surfaced in P/Invoke.
8294 * For more information on how the parameters are marshalled, see the
8295 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8298 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8299 * reference for more information on the format of method descriptions.
8302 mono_add_internal_call (const char *name, gconstpointer method)
8306 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8308 mono_icall_unlock ();
8311 #ifndef DISABLE_ICALL_TABLES
8313 #ifdef HAVE_ARRAY_ELEM_INIT
8315 compare_method_imap (const void *key, const void *elem)
8317 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8318 return strcmp (key, method_name);
8322 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8324 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);
8327 return (nameslot - &icall_names_idx [0]);
8331 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8333 gsize slotnum = find_slot_icall (imap, name);
8336 return (gboolean)icall_uses_handles [slotnum];
8340 find_method_icall (const IcallTypeDesc *imap, const char *name)
8342 gsize slotnum = find_slot_icall (imap, name);
8345 return (gpointer)icall_functions [slotnum];
8349 compare_class_imap (const void *key, const void *elem)
8351 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8352 return strcmp (key, class_name);
8355 static const IcallTypeDesc*
8356 find_class_icalls (const char *name)
8358 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);
8361 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8364 #else /* HAVE_ARRAY_ELEM_INIT */
8367 compare_method_imap (const void *key, const void *elem)
8369 const char** method_name = (const char**)elem;
8370 return strcmp (key, *method_name);
8374 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8376 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8379 return nameslot - icall_names;
8383 find_method_icall (const IcallTypeDesc *imap, const char *name)
8385 gsize slotnum = find_slot_icall (imap, name);
8388 return (gpointer)icall_functions [slotnum];
8392 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8394 gsize slotnum = find_slot_icall (imap, name);
8397 return (gboolean)icall_uses_handles [slotnum];
8401 compare_class_imap (const void *key, const void *elem)
8403 const char** class_name = (const char**)elem;
8404 return strcmp (key, *class_name);
8407 static const IcallTypeDesc*
8408 find_class_icalls (const char *name)
8410 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8413 return &icall_type_descs [nameslot - icall_type_names];
8416 #endif /* HAVE_ARRAY_ELEM_INIT */
8418 #endif /* DISABLE_ICALL_TABLES */
8421 * we should probably export this as an helper (handle nested types).
8422 * Returns the number of chars written in buf.
8425 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8427 int nspacelen, cnamelen;
8428 nspacelen = strlen (klass->name_space);
8429 cnamelen = strlen (klass->name);
8430 if (nspacelen + cnamelen + 2 > bufsize)
8433 memcpy (buf, klass->name_space, nspacelen);
8434 buf [nspacelen ++] = '.';
8436 memcpy (buf + nspacelen, klass->name, cnamelen);
8437 buf [nspacelen + cnamelen] = 0;
8438 return nspacelen + cnamelen;
8441 #ifdef DISABLE_ICALL_TABLES
8443 no_icall_table (void)
8445 g_assert_not_reached ();
8450 * mono_lookup_internal_call_full:
8451 * @method: the method to look up
8452 * @uses_handles: out argument if method needs handles around managed objects.
8454 * Returns a pointer to the icall code for the given method. If
8455 * uses_handles is not NULL, it will be set to TRUE if the method
8456 * needs managed objects wrapped using the infrastructure in handle.h
8458 * If the method is not found, warns and returns NULL.
8461 mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
8466 int typelen = 0, mlen, siglen;
8468 #ifndef DISABLE_ICALL_TABLES
8469 const IcallTypeDesc *imap = NULL;
8472 g_assert (method != NULL);
8474 if (method->is_inflated)
8475 method = ((MonoMethodInflated *) method)->declaring;
8477 if (method->klass->nested_in) {
8478 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8482 mname [pos++] = '/';
8485 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8491 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8496 #ifndef DISABLE_ICALL_TABLES
8497 imap = find_class_icalls (mname);
8500 mname [typelen] = ':';
8501 mname [typelen + 1] = ':';
8503 mlen = strlen (method->name);
8504 memcpy (mname + typelen + 2, method->name, mlen);
8505 sigstart = mname + typelen + 2 + mlen;
8508 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8509 siglen = strlen (tmpsig);
8510 if (typelen + mlen + siglen + 6 > sizeof (mname))
8513 memcpy (sigstart + 1, tmpsig, siglen);
8514 sigstart [siglen + 1] = ')';
8515 sigstart [siglen + 2] = 0;
8520 res = g_hash_table_lookup (icall_hash, mname);
8523 *uses_handles = FALSE;
8524 mono_icall_unlock ();;
8527 /* try without signature */
8529 res = g_hash_table_lookup (icall_hash, mname);
8532 *uses_handles = FALSE;
8533 mono_icall_unlock ();
8537 #ifdef DISABLE_ICALL_TABLES
8538 mono_icall_unlock ();
8539 /* Fail only when the result is actually used */
8540 /* mono_marshal_get_native_wrapper () depends on this */
8541 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8542 return ves_icall_System_String_ctor_RedirectToCreateString;
8544 return no_icall_table;
8546 /* it wasn't found in the static call tables */
8549 *uses_handles = FALSE;
8550 mono_icall_unlock ();
8553 res = find_method_icall (imap, sigstart - mlen);
8556 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8557 mono_icall_unlock ();
8560 /* try _with_ signature */
8562 res = find_method_icall (imap, sigstart - mlen);
8565 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8566 mono_icall_unlock ();
8570 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8571 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8572 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8573 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8574 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");
8575 g_print ("If you see other errors or faults after this message they are probably related\n");
8576 g_print ("and you need to fix your mono install first.\n");
8578 mono_icall_unlock ();
8585 mono_lookup_internal_call (MonoMethod *method)
8587 return mono_lookup_internal_call_full (method, NULL);
8590 #ifdef ENABLE_ICALL_SYMBOL_MAP
8592 func_cmp (gconstpointer key, gconstpointer p)
8594 return (gsize)key - (gsize)*(gsize*)p;
8599 * mono_lookup_icall_symbol:
8601 * Given the icall METHOD, returns its C symbol.
8604 mono_lookup_icall_symbol (MonoMethod *m)
8606 #ifdef DISABLE_ICALL_TABLES
8607 g_assert_not_reached ();
8610 #ifdef ENABLE_ICALL_SYMBOL_MAP
8614 static gconstpointer *functions_sorted;
8615 static const char**symbols_sorted;
8616 static gboolean inited;
8621 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8622 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8623 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8624 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8625 /* Bubble sort the two arrays */
8629 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8630 if (functions_sorted [i] > functions_sorted [i + 1]) {
8633 tmp = functions_sorted [i];
8634 functions_sorted [i] = functions_sorted [i + 1];
8635 functions_sorted [i + 1] = tmp;
8636 tmp = symbols_sorted [i];
8637 symbols_sorted [i] = symbols_sorted [i + 1];
8638 symbols_sorted [i + 1] = tmp;
8645 func = mono_lookup_internal_call (m);
8648 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8652 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8654 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8655 g_assert_not_reached ();
8662 type_from_typename (char *type_name)
8664 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8666 if (!strcmp (type_name, "int"))
8667 klass = mono_defaults.int_class;
8668 else if (!strcmp (type_name, "ptr"))
8669 klass = mono_defaults.int_class;
8670 else if (!strcmp (type_name, "void"))
8671 klass = mono_defaults.void_class;
8672 else if (!strcmp (type_name, "int32"))
8673 klass = mono_defaults.int32_class;
8674 else if (!strcmp (type_name, "uint32"))
8675 klass = mono_defaults.uint32_class;
8676 else if (!strcmp (type_name, "int8"))
8677 klass = mono_defaults.sbyte_class;
8678 else if (!strcmp (type_name, "uint8"))
8679 klass = mono_defaults.byte_class;
8680 else if (!strcmp (type_name, "int16"))
8681 klass = mono_defaults.int16_class;
8682 else if (!strcmp (type_name, "uint16"))
8683 klass = mono_defaults.uint16_class;
8684 else if (!strcmp (type_name, "long"))
8685 klass = mono_defaults.int64_class;
8686 else if (!strcmp (type_name, "ulong"))
8687 klass = mono_defaults.uint64_class;
8688 else if (!strcmp (type_name, "float"))
8689 klass = mono_defaults.single_class;
8690 else if (!strcmp (type_name, "double"))
8691 klass = mono_defaults.double_class;
8692 else if (!strcmp (type_name, "object"))
8693 klass = mono_defaults.object_class;
8694 else if (!strcmp (type_name, "obj"))
8695 klass = mono_defaults.object_class;
8696 else if (!strcmp (type_name, "string"))
8697 klass = mono_defaults.string_class;
8698 else if (!strcmp (type_name, "bool"))
8699 klass = mono_defaults.boolean_class;
8700 else if (!strcmp (type_name, "boolean"))
8701 klass = mono_defaults.boolean_class;
8703 g_error ("%s", type_name);
8704 g_assert_not_reached ();
8706 return &klass->byval_arg;
8710 * LOCKING: Take the corlib image lock.
8712 MonoMethodSignature*
8713 mono_create_icall_signature (const char *sigstr)
8718 MonoMethodSignature *res, *res2;
8719 MonoImage *corlib = mono_defaults.corlib;
8721 mono_image_lock (corlib);
8722 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8723 mono_image_unlock (corlib);
8728 parts = g_strsplit (sigstr, " ", 256);
8737 res = mono_metadata_signature_alloc (corlib, len - 1);
8742 * Under windows, the default pinvoke calling convention is STDCALL but
8745 res->call_convention = MONO_CALL_C;
8748 res->ret = type_from_typename (parts [0]);
8749 for (i = 1; i < len; ++i) {
8750 res->params [i - 1] = type_from_typename (parts [i]);
8755 mono_image_lock (corlib);
8756 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8758 res = res2; /*Value is allocated in the image pool*/
8760 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8761 mono_image_unlock (corlib);
8767 mono_find_jit_icall_by_name (const char *name)
8769 MonoJitICallInfo *info;
8770 g_assert (jit_icall_hash_name);
8773 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8774 mono_icall_unlock ();
8779 mono_find_jit_icall_by_addr (gconstpointer addr)
8781 MonoJitICallInfo *info;
8782 g_assert (jit_icall_hash_addr);
8785 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8786 mono_icall_unlock ();
8792 * mono_get_jit_icall_info:
8794 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8795 * caller should access it while holding the icall lock.
8798 mono_get_jit_icall_info (void)
8800 return jit_icall_hash_name;
8804 * mono_lookup_jit_icall_symbol:
8806 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8809 mono_lookup_jit_icall_symbol (const char *name)
8811 MonoJitICallInfo *info;
8812 const char *res = NULL;
8815 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8817 res = info->c_symbol;
8818 mono_icall_unlock ();
8823 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8826 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8827 mono_icall_unlock ();
8831 * 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
8832 * icalls without wrappers in some cases.
8835 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8837 MonoJitICallInfo *info;
8844 if (!jit_icall_hash_name) {
8845 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8846 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8849 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8850 g_warning ("jit icall already defined \"%s\"\n", name);
8851 g_assert_not_reached ();
8854 info = g_new0 (MonoJitICallInfo, 1);
8859 info->c_symbol = c_symbol;
8860 info->no_raise = no_raise;
8863 info->wrapper = func;
8865 info->wrapper = NULL;
8868 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8869 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8871 mono_icall_unlock ();
8876 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8878 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);