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/io-layer/io-layer.h>
86 #include <mono/utils/monobitset.h>
87 #include <mono/utils/mono-time.h>
88 #include <mono/utils/mono-proclib.h>
89 #include <mono/utils/mono-string.h>
90 #include <mono/utils/mono-error-internals.h>
91 #include <mono/utils/mono-mmap.h>
92 #include <mono/utils/mono-io-portability.h>
93 #include <mono/utils/mono-digest.h>
94 #include <mono/utils/bsearch.h>
95 #include <mono/utils/mono-os-mutex.h>
96 #include <mono/utils/mono-threads.h>
98 #if defined (HOST_WIN32)
102 #include "decimal-ms.h"
103 #include "number-ms.h"
105 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
106 #include <sys/utsname.h>
109 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
111 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
113 /* Lazy class loading functions */
114 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
115 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
116 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
119 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
122 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
124 static inline MonoBoolean
125 is_generic_parameter (MonoType *type)
127 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
131 mono_class_init_checked (MonoClass *klass, MonoError *error)
133 mono_error_init (error);
135 if (!mono_class_init (klass))
136 mono_error_set_for_class_failure (error, klass);
139 ICALL_EXPORT MonoObject *
140 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
146 MonoObject *result = NULL;
148 ac = (MonoClass *)arr->obj.vtable->klass;
150 esize = mono_array_element_size (ac);
151 ea = (gpointer*)((char*)arr->vector + (pos * esize));
153 if (ac->element_class->valuetype) {
154 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
155 mono_error_set_pending_exception (&error);
157 result = (MonoObject *)*ea;
161 ICALL_EXPORT MonoObject *
162 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
168 MONO_CHECK_ARG_NULL (idxs, NULL);
171 ic = (MonoClass *)io->obj.vtable->klass;
173 ac = (MonoClass *)arr->obj.vtable->klass;
175 g_assert (ic->rank == 1);
176 if (io->bounds != NULL || io->max_length != ac->rank) {
177 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
181 ind = (gint32 *)io->vector;
183 if (arr->bounds == NULL) {
184 if (*ind < 0 || *ind >= arr->max_length) {
185 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
189 return ves_icall_System_Array_GetValueImpl (arr, *ind);
192 for (i = 0; i < ac->rank; i++) {
193 if ((ind [i] < arr->bounds [i].lower_bound) ||
194 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
195 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
200 pos = ind [0] - arr->bounds [0].lower_bound;
201 for (i = 1; i < ac->rank; i++)
202 pos = pos * arr->bounds [i].length + ind [i] -
203 arr->bounds [i].lower_bound;
205 return ves_icall_System_Array_GetValueImpl (arr, pos);
209 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
212 MonoClass *ac, *vc, *ec;
221 mono_error_init (&error);
224 vc = value->vtable->klass;
228 ac = arr->obj.vtable->klass;
229 ec = ac->element_class;
231 esize = mono_array_element_size (ac);
232 ea = (gpointer*)((char*)arr->vector + (pos * esize));
233 va = (gpointer*)((char*)value + sizeof (MonoObject));
235 if (mono_class_is_nullable (ec)) {
236 mono_nullable_init ((guint8*)ea, value, ec);
241 mono_gc_bzero_atomic (ea, esize);
245 #define NO_WIDENING_CONVERSION G_STMT_START{\
246 mono_set_pending_exception (mono_get_exception_argument ( \
247 "value", "not a widening conversion")); \
251 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
252 if (esize < vsize + (extra)) { \
253 mono_set_pending_exception (mono_get_exception_argument ( \
254 "value", "not a widening conversion")); \
259 #define INVALID_CAST G_STMT_START{ \
260 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
261 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
265 /* Check element (destination) type. */
266 switch (ec->byval_arg.type) {
267 case MONO_TYPE_STRING:
268 switch (vc->byval_arg.type) {
269 case MONO_TYPE_STRING:
275 case MONO_TYPE_BOOLEAN:
276 switch (vc->byval_arg.type) {
277 case MONO_TYPE_BOOLEAN:
290 NO_WIDENING_CONVERSION;
299 if (!ec->valuetype) {
300 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
301 if (mono_error_set_pending_exception (&error))
305 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
309 if (mono_object_isinst_checked (value, ec, &error)) {
310 if (ec->has_references)
311 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
313 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
316 if (mono_error_set_pending_exception (&error))
322 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
324 et = ec->byval_arg.type;
325 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
326 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
328 vt = vc->byval_arg.type;
329 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
330 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
332 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
338 case MONO_TYPE_CHAR: \
339 CHECK_WIDENING_CONVERSION(0); \
340 *(etype *) ea = (etype) u64; \
342 /* You can't assign a signed value to an unsigned array. */ \
347 /* You can't assign a floating point number to an integer array. */ \
350 NO_WIDENING_CONVERSION; \
354 #define ASSIGN_SIGNED(etype) G_STMT_START{\
360 CHECK_WIDENING_CONVERSION(0); \
361 *(etype *) ea = (etype) i64; \
363 /* You can assign an unsigned value to a signed array if the array's */ \
364 /* element size is larger than the value size. */ \
369 case MONO_TYPE_CHAR: \
370 CHECK_WIDENING_CONVERSION(1); \
371 *(etype *) ea = (etype) u64; \
373 /* You can't assign a floating point number to an integer array. */ \
376 NO_WIDENING_CONVERSION; \
380 #define ASSIGN_REAL(etype) G_STMT_START{\
384 CHECK_WIDENING_CONVERSION(0); \
385 *(etype *) ea = (etype) r64; \
387 /* All integer values fit into a floating point array, so we don't */ \
388 /* need to CHECK_WIDENING_CONVERSION here. */ \
393 *(etype *) ea = (etype) i64; \
399 case MONO_TYPE_CHAR: \
400 *(etype *) ea = (etype) u64; \
407 u64 = *(guint8 *) va;
410 u64 = *(guint16 *) va;
413 u64 = *(guint32 *) va;
416 u64 = *(guint64 *) va;
422 i64 = *(gint16 *) va;
425 i64 = *(gint32 *) va;
428 i64 = *(gint64 *) va;
431 r64 = *(gfloat *) va;
434 r64 = *(gdouble *) va;
437 u64 = *(guint16 *) va;
439 case MONO_TYPE_BOOLEAN:
440 /* Boolean is only compatible with itself. */
453 NO_WIDENING_CONVERSION;
460 /* If we can't do a direct copy, let's try a widening conversion. */
463 ASSIGN_UNSIGNED (guint16);
465 ASSIGN_UNSIGNED (guint8);
467 ASSIGN_UNSIGNED (guint16);
469 ASSIGN_UNSIGNED (guint32);
471 ASSIGN_UNSIGNED (guint64);
473 ASSIGN_SIGNED (gint8);
475 ASSIGN_SIGNED (gint16);
477 ASSIGN_SIGNED (gint32);
479 ASSIGN_SIGNED (gint64);
481 ASSIGN_REAL (gfloat);
483 ASSIGN_REAL (gdouble);
487 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
491 #undef NO_WIDENING_CONVERSION
492 #undef CHECK_WIDENING_CONVERSION
493 #undef ASSIGN_UNSIGNED
499 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
505 MONO_CHECK_ARG_NULL (idxs,);
507 ic = idxs->obj.vtable->klass;
508 ac = arr->obj.vtable->klass;
510 g_assert (ic->rank == 1);
511 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
512 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
516 ind = (gint32 *)idxs->vector;
518 if (arr->bounds == NULL) {
519 if (*ind < 0 || *ind >= arr->max_length) {
520 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
524 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
528 for (i = 0; i < ac->rank; i++)
529 if ((ind [i] < arr->bounds [i].lower_bound) ||
530 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
531 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
535 pos = ind [0] - arr->bounds [0].lower_bound;
536 for (i = 1; i < ac->rank; i++)
537 pos = pos * arr->bounds [i].length + ind [i] -
538 arr->bounds [i].lower_bound;
540 ves_icall_System_Array_SetValueImpl (arr, value, pos);
543 ICALL_EXPORT MonoArray *
544 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
547 MonoClass *aklass, *klass;
550 gboolean bounded = FALSE;
552 MONO_CHECK_ARG_NULL (type, NULL);
553 MONO_CHECK_ARG_NULL (lengths, NULL);
555 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
557 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
559 for (i = 0; i < mono_array_length (lengths); i++) {
560 if (mono_array_get (lengths, gint32, i) < 0) {
561 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
566 klass = mono_class_from_mono_type (type->type);
567 mono_class_init_checked (klass, &error);
568 if (mono_error_set_pending_exception (&error))
571 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
572 /* vectors are not the same as one dimensional arrays with no-zero bounds */
577 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
579 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
580 for (i = 0; i < aklass->rank; ++i) {
581 sizes [i] = mono_array_get (lengths, guint32, i);
583 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
585 sizes [i + aklass->rank] = 0;
588 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
589 mono_error_set_pending_exception (&error);
594 ICALL_EXPORT MonoArray *
595 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
598 MonoClass *aklass, *klass;
601 gboolean bounded = FALSE;
603 MONO_CHECK_ARG_NULL (type, NULL);
604 MONO_CHECK_ARG_NULL (lengths, NULL);
606 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
608 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
610 for (i = 0; i < mono_array_length (lengths); i++) {
611 if ((mono_array_get (lengths, gint64, i) < 0) ||
612 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
613 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
618 klass = mono_class_from_mono_type (type->type);
619 mono_class_init_checked (klass, &error);
620 if (mono_error_set_pending_exception (&error))
623 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
624 /* vectors are not the same as one dimensional arrays with no-zero bounds */
629 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
631 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
632 for (i = 0; i < aklass->rank; ++i) {
633 sizes [i] = mono_array_get (lengths, guint64, i);
635 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
637 sizes [i + aklass->rank] = 0;
640 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
641 mono_error_set_pending_exception (&error);
647 ves_icall_System_Array_GetRank (MonoObject *arr)
649 return arr->vtable->klass->rank;
653 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
655 gint32 rank = arr->obj.vtable->klass->rank;
658 if ((dimension < 0) || (dimension >= rank)) {
659 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
663 if (arr->bounds == NULL)
664 length = arr->max_length;
666 length = arr->bounds [dimension].length;
668 #ifdef MONO_BIG_ARRAYS
669 if (length > G_MAXINT32) {
670 mono_set_pending_exception (mono_get_exception_overflow ());
678 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
680 gint32 rank = arr->obj.vtable->klass->rank;
682 if ((dimension < 0) || (dimension >= rank)) {
683 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
687 if (arr->bounds == NULL)
688 return arr->max_length;
690 return arr->bounds [dimension].length;
694 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
696 gint32 rank = arr->obj.vtable->klass->rank;
698 if ((dimension < 0) || (dimension >= rank)) {
699 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
703 if (arr->bounds == NULL)
706 return arr->bounds [dimension].lower_bound;
710 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
712 int sz = mono_array_element_size (mono_object_class (arr));
713 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
716 ICALL_EXPORT MonoArray*
717 ves_icall_System_Array_Clone (MonoArray *arr)
720 MonoArray *result = mono_array_clone_checked (arr, &error);
721 mono_error_set_pending_exception (&error);
725 ICALL_EXPORT gboolean
726 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
731 MonoVTable *src_vtable;
732 MonoVTable *dest_vtable;
733 MonoClass *src_class;
734 MonoClass *dest_class;
736 src_vtable = source->obj.vtable;
737 dest_vtable = dest->obj.vtable;
739 if (src_vtable->rank != dest_vtable->rank)
742 if (source->bounds || dest->bounds)
745 /* there's no integer overflow since mono_array_length returns an unsigned integer */
746 if ((dest_idx + length > mono_array_length_fast (dest)) ||
747 (source_idx + length > mono_array_length_fast (source)))
750 src_class = src_vtable->klass->element_class;
751 dest_class = dest_vtable->klass->element_class;
754 * Handle common cases.
757 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
758 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
760 if (src_class == mono_defaults.object_class && dest_class->valuetype)
763 /* Check if we're copying a char[] <==> (u)short[] */
764 if (src_class != dest_class) {
765 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
768 /* 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. */
769 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
773 if (dest_class->valuetype) {
774 element_size = mono_array_element_size (source->obj.vtable->klass);
775 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
776 if (dest_class->has_references) {
777 mono_value_copy_array (dest, dest_idx, source_addr, length);
779 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
780 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
783 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
790 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
796 ac = (MonoClass *)arr->obj.vtable->klass;
798 esize = mono_array_element_size (ac);
799 ea = (gpointer*)((char*)arr->vector + (pos * esize));
801 mono_gc_memmove_atomic (value, ea, esize);
805 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
811 ac = (MonoClass *)arr->obj.vtable->klass;
812 ec = ac->element_class;
814 esize = mono_array_element_size (ac);
815 ea = (gpointer*)((char*)arr->vector + (pos * esize));
817 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
818 g_assert (esize == sizeof (gpointer));
819 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
821 g_assert (ec->inited);
822 g_assert (esize == mono_class_value_size (ec, NULL));
823 if (ec->has_references)
824 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
826 mono_gc_memmove_atomic (ea, value, esize);
831 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
833 MonoClass *klass = array->obj.vtable->klass;
834 guint32 size = mono_array_element_size (klass);
835 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
837 const char *field_data;
839 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
840 MonoException *exc = mono_get_exception_argument("array",
841 "Cannot initialize array of non-primitive type.");
842 mono_set_pending_exception (exc);
846 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
847 MonoException *exc = mono_get_exception_argument("field_handle",
848 "Field doesn't have an RVA");
849 mono_set_pending_exception (exc);
853 size *= array->max_length;
854 field_data = mono_field_get_data (field_handle);
856 if (size > mono_type_size (field_handle->type, &align)) {
857 MonoException *exc = mono_get_exception_argument("field_handle",
858 "Field not large enough to fill array");
859 mono_set_pending_exception (exc);
863 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
865 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
866 guint ## n *src = (guint ## n *) field_data; \
868 nEnt = (size / sizeof(guint ## n)); \
870 for (i = 0; i < nEnt; i++) { \
871 data[i] = read ## n (&src[i]); \
875 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
877 switch (type->type) {
894 memcpy (mono_array_addr (array, char, 0), field_data, size);
898 memcpy (mono_array_addr (array, char, 0), field_data, size);
903 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
905 return offsetof (MonoString, chars);
908 ICALL_EXPORT MonoObject *
909 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
911 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
915 MonoObject *ret = mono_object_clone_checked (obj, &error);
916 mono_error_set_pending_exception (&error);
923 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
929 MONO_CHECK_ARG_NULL (handle,);
931 klass = mono_class_from_mono_type (handle);
932 MONO_CHECK_ARG (handle, klass,);
934 if (klass->generic_container)
937 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
938 if (!is_ok (&error)) {
939 mono_error_set_pending_exception (&error);
943 /* This will call the type constructor */
944 if (!mono_runtime_class_init_full (vtable, &error))
945 mono_error_set_pending_exception (&error);
949 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
953 mono_image_check_for_module_cctor (image);
954 if (image->has_module_cctor) {
955 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
956 if (!mono_error_ok (&error)) {
957 mono_error_set_pending_exception (&error);
960 /*It's fine to raise the exception here*/
961 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
962 if (!is_ok (&error)) {
963 mono_error_set_pending_exception (&error);
966 if (!mono_runtime_class_init_full (vtable, &error))
967 mono_error_set_pending_exception (&error);
971 ICALL_EXPORT MonoBoolean
972 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
977 /* later make this configurable and per-arch */
978 int min_size = 4096 * 4 * sizeof (void*);
979 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
980 /* if we have no info we are optimistic and assume there is enough room */
984 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
988 current = (guint8 *)&stack_addr;
989 if (current > stack_addr) {
990 if ((current - stack_addr) < min_size)
993 if (current - (stack_addr - stack_size) < min_size)
999 ICALL_EXPORT MonoObject *
1000 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
1003 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
1004 mono_error_set_pending_exception (&error);
1010 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1014 MonoObject **values = NULL;
1017 gint32 result = (int)(gsize)mono_defaults.int32_class;
1018 MonoClassField* field;
1021 klass = mono_object_class (this_obj);
1023 if (mono_class_num_fields (klass) == 0)
1027 * Compute the starting value of the hashcode for fields of primitive
1028 * types, and return the remaining fields in an array to the managed side.
1029 * This way, we can avoid costly reflection operations in managed code.
1032 while ((field = mono_class_get_fields (klass, &iter))) {
1033 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1035 if (mono_field_is_deleted (field))
1037 /* FIXME: Add more types */
1038 switch (field->type->type) {
1040 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1042 case MONO_TYPE_STRING: {
1044 s = *(MonoString**)((guint8*)this_obj + field->offset);
1046 result ^= mono_string_hash (s);
1051 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1052 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1053 if (!is_ok (&error)) {
1054 mono_error_set_pending_exception (&error);
1057 values [count++] = o;
1063 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1064 if (mono_error_set_pending_exception (&error))
1066 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1067 for (i = 0; i < count; ++i)
1068 mono_array_setref (*fields, i, values [i]);
1075 ICALL_EXPORT MonoBoolean
1076 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1080 MonoObject **values = NULL;
1082 MonoClassField* field;
1086 MONO_CHECK_ARG_NULL (that, FALSE);
1088 if (this_obj->vtable != that->vtable)
1091 klass = mono_object_class (this_obj);
1093 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1094 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1097 * Do the comparison for fields of primitive type and return a result if
1098 * possible. Otherwise, return the remaining fields in an array to the
1099 * managed side. This way, we can avoid costly reflection operations in
1104 while ((field = mono_class_get_fields (klass, &iter))) {
1105 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1107 if (mono_field_is_deleted (field))
1109 /* FIXME: Add more types */
1110 switch (field->type->type) {
1113 case MONO_TYPE_BOOLEAN:
1114 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1119 case MONO_TYPE_CHAR:
1120 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1125 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1130 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1134 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1138 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1143 case MONO_TYPE_STRING: {
1144 MonoString *s1, *s2;
1145 guint32 s1len, s2len;
1146 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1147 s2 = *(MonoString**)((guint8*)that + field->offset);
1150 if ((s1 == NULL) || (s2 == NULL))
1152 s1len = mono_string_length (s1);
1153 s2len = mono_string_length (s2);
1157 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1163 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1164 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1165 if (!is_ok (&error)) {
1166 mono_error_set_pending_exception (&error);
1169 values [count++] = o;
1170 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1171 if (!is_ok (&error)) {
1172 mono_error_set_pending_exception (&error);
1175 values [count++] = o;
1178 if (klass->enumtype)
1179 /* enums only have one non-static field */
1185 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1186 if (mono_error_set_pending_exception (&error))
1188 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1189 for (i = 0; i < count; ++i)
1190 mono_array_setref_fast (*fields, i, values [i]);
1197 ICALL_EXPORT MonoReflectionType *
1198 ves_icall_System_Object_GetType (MonoObject *obj)
1201 MonoReflectionType *ret;
1202 #ifndef DISABLE_REMOTING
1203 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1204 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1207 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1209 mono_error_set_pending_exception (&error);
1214 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1216 MONO_CHECK_ARG_NULL (obj, 0);
1219 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1220 mono_error_set_pending_exception (&error);
1225 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1226 MonoReflectionMethod *method,
1227 MonoArray *opt_param_types)
1229 MONO_CHECK_ARG_NULL (method, 0);
1232 gint32 result = mono_image_create_method_token (
1233 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1234 mono_error_set_pending_exception (&error);
1239 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1242 mono_image_create_pefile (mb, file, &error);
1243 mono_error_set_pending_exception (&error);
1247 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1250 mono_image_build_metadata (mb, &error);
1251 mono_error_set_pending_exception (&error);
1255 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1257 mono_image_register_token (mb->dynamic_image, token, obj);
1260 ICALL_EXPORT MonoObject*
1261 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1265 mono_loader_lock ();
1266 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1267 mono_loader_unlock ();
1272 ICALL_EXPORT MonoReflectionModule*
1273 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1276 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1277 mono_error_set_pending_exception (&error);
1282 * ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class:
1283 * @tb: a TypeBuilder object
1286 * Creates the generic class after all generic parameters have been added.
1289 ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class (MonoReflectionTypeBuilder *tb)
1292 (void) mono_reflection_create_generic_class (tb, &error);
1293 mono_error_set_pending_exception (&error);
1296 #ifndef DISABLE_REFLECTION_EMIT
1297 ICALL_EXPORT MonoArray*
1298 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
1301 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
1302 mono_error_set_pending_exception (&error);
1308 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1310 MonoMethod **dest = (MonoMethod **)data;
1312 /* skip unmanaged frames */
1317 if (!strcmp (m->klass->name_space, "System.Reflection"))
1326 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1328 MonoMethod **dest = (MonoMethod **)data;
1330 /* skip unmanaged frames */
1334 if (m->wrapper_type != MONO_WRAPPER_NONE)
1342 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1353 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1355 MonoMethod **dest = (MonoMethod **)data;
1357 /* skip unmanaged frames */
1361 if (m->wrapper_type != MONO_WRAPPER_NONE)
1369 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1370 || (!strcmp (m->klass->name_space, "System"))))
1380 static MonoReflectionType *
1381 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1383 MonoMethod *m, *dest;
1385 MonoType *type = NULL;
1386 MonoAssembly *assembly = NULL;
1387 gboolean type_resolve = FALSE;
1388 MonoImage *rootimage = NULL;
1390 mono_error_init (error);
1393 * We must compute the calling assembly as type loading must happen under a metadata context.
1394 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1395 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1397 m = mono_method_get_last_managed ();
1399 if (m && m->klass->image != mono_defaults.corlib) {
1400 /* Happens with inlining */
1402 /* Ugly hack: type_from_parsed_name is called from
1403 * System.Type.internal_from_name, which is called most
1404 * directly from System.Type.GetType(string,bool,bool) but
1405 * also indirectly from places such as
1406 * System.Type.GetType(string,func,func) (via
1407 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1408 * so we need to skip over all of those to find the true caller.
1410 * It would be nice if we had stack marks.
1412 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1418 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1419 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1420 * to crash. This only seems to happen in some strange remoting
1421 * scenarios and I was unable to figure out what's happening there.
1422 * Dec 10, 2005 - Martin.
1426 assembly = dest->klass->image->assembly;
1427 type_resolve = TRUE;
1428 rootimage = assembly->image;
1430 g_warning (G_STRLOC);
1433 if (info->assembly.name)
1434 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1437 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1438 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1439 return_val_if_nok (error, NULL);
1443 // Say we're looking for System.Generic.Dict<int, Local>
1444 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1445 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1446 // is messed up when we go to construct the Local as the type arg...
1448 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1449 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1450 if (!info->assembly.name && !type) {
1452 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1453 return_val_if_nok (error, NULL);
1455 if (assembly && !type && type_resolve) {
1456 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1457 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1458 return_val_if_nok (error, NULL);
1464 return mono_type_get_object_checked (mono_domain_get (), type, error);
1467 ICALL_EXPORT MonoReflectionType*
1468 ves_icall_System_Type_internal_from_name (MonoString *name,
1469 MonoBoolean throwOnError,
1470 MonoBoolean ignoreCase)
1473 MonoTypeNameParse info;
1474 MonoReflectionType *type = NULL;
1477 char *str = mono_string_to_utf8_checked (name, &error);
1478 if (!is_ok (&error))
1481 parsedOk = mono_reflection_parse_type (str, &info);
1483 /* mono_reflection_parse_type() mangles the string */
1485 mono_reflection_free_type_info (&info);
1487 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1491 type = type_from_parsed_name (&info, ignoreCase, &error);
1493 mono_reflection_free_type_info (&info);
1495 if (!is_ok (&error))
1500 mono_error_set_type_load_name (&error, g_strdup (str), NULL, "");
1507 if (!is_ok (&error)) {
1509 mono_error_set_pending_exception (&error);
1511 mono_error_cleanup (&error);
1519 ICALL_EXPORT MonoReflectionType*
1520 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1523 MonoReflectionType *ret;
1524 MonoDomain *domain = mono_domain_get ();
1526 ret = mono_type_get_object_checked (domain, handle, &error);
1527 mono_error_set_pending_exception (&error);
1532 ICALL_EXPORT MonoType*
1533 ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass)
1535 return mono_class_get_type (klass);
1539 ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array)
1541 g_ptr_array_free (ptr_array, TRUE);
1545 ves_icall_Mono_SafeStringMarshal_GFree (void *c_str)
1551 ves_icall_Mono_SafeStringMarshal_StringToUtf8 (MonoString *s)
1554 char *res = mono_string_to_utf8_checked (s, &error);
1555 mono_error_set_pending_exception (&error);
1559 /* System.TypeCode */
1578 TYPECODE_STRING = 18
1581 ICALL_EXPORT guint32
1582 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1584 int t = type->type->type;
1586 if (type->type->byref)
1587 return TYPECODE_OBJECT;
1591 case MONO_TYPE_VOID:
1592 return TYPECODE_OBJECT;
1593 case MONO_TYPE_BOOLEAN:
1594 return TYPECODE_BOOLEAN;
1596 return TYPECODE_BYTE;
1598 return TYPECODE_SBYTE;
1600 return TYPECODE_UINT16;
1602 return TYPECODE_INT16;
1603 case MONO_TYPE_CHAR:
1604 return TYPECODE_CHAR;
1608 return TYPECODE_OBJECT;
1610 return TYPECODE_UINT32;
1612 return TYPECODE_INT32;
1614 return TYPECODE_UINT64;
1616 return TYPECODE_INT64;
1618 return TYPECODE_SINGLE;
1620 return TYPECODE_DOUBLE;
1621 case MONO_TYPE_VALUETYPE: {
1622 MonoClass *klass = type->type->data.klass;
1624 if (klass->enumtype) {
1625 t = mono_class_enum_basetype (klass)->type;
1627 } else if (mono_is_corlib_image (klass->image)) {
1628 if (strcmp (klass->name_space, "System") == 0) {
1629 if (strcmp (klass->name, "Decimal") == 0)
1630 return TYPECODE_DECIMAL;
1631 else if (strcmp (klass->name, "DateTime") == 0)
1632 return TYPECODE_DATETIME;
1635 return TYPECODE_OBJECT;
1637 case MONO_TYPE_STRING:
1638 return TYPECODE_STRING;
1639 case MONO_TYPE_SZARRAY:
1640 case MONO_TYPE_ARRAY:
1641 case MONO_TYPE_OBJECT:
1643 case MONO_TYPE_MVAR:
1644 case MONO_TYPE_TYPEDBYREF:
1645 return TYPECODE_OBJECT;
1646 case MONO_TYPE_CLASS:
1648 MonoClass *klass = type->type->data.klass;
1649 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1650 if (strcmp (klass->name, "DBNull") == 0)
1651 return TYPECODE_DBNULL;
1654 return TYPECODE_OBJECT;
1655 case MONO_TYPE_GENERICINST:
1656 return TYPECODE_OBJECT;
1658 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1664 mono_type_is_primitive (MonoType *type)
1666 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1667 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1671 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1673 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1674 return mono_class_enum_basetype (type->data.klass);
1675 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1676 return mono_class_enum_basetype (type->data.generic_class->container_class);
1680 ICALL_EXPORT guint32
1681 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1686 g_assert (type != NULL);
1688 klass = mono_class_from_mono_type (type->type);
1689 klassc = mono_class_from_mono_type (c->type);
1691 if (type->type->byref ^ c->type->byref)
1694 if (type->type->byref) {
1695 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1696 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1698 klass = mono_class_from_mono_type (t);
1699 klassc = mono_class_from_mono_type (ot);
1701 if (mono_type_is_primitive (t)) {
1702 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1703 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1704 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1705 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1706 return t->type == ot->type;
1708 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1711 if (klass->valuetype)
1712 return klass == klassc;
1713 return klass->valuetype == klassc->valuetype;
1716 return mono_class_is_assignable_from (klass, klassc);
1719 ICALL_EXPORT guint32
1720 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1723 MonoClass *klass = mono_class_from_mono_type (type->type);
1724 mono_class_init_checked (klass, &error);
1725 if (!is_ok (&error)) {
1726 mono_error_set_pending_exception (&error);
1729 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1730 mono_error_set_pending_exception (&error);
1734 ICALL_EXPORT guint32
1735 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1737 MonoClass *klass = mono_class_from_mono_type (type->type);
1738 return klass->flags;
1741 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1742 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1745 MonoClass *klass = field->field->parent;
1746 MonoMarshalType *info;
1750 if (klass->generic_container ||
1751 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1754 ftype = mono_field_get_type (field->field);
1755 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1758 info = mono_marshal_load_type_info (klass);
1760 for (i = 0; i < info->num_fields; ++i) {
1761 if (info->fields [i].field == field->field) {
1762 if (!info->fields [i].mspec)
1765 MonoReflectionMarshalAsAttribute* obj;
1766 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1767 if (!mono_error_ok (&error))
1768 mono_error_set_pending_exception (&error);
1777 ICALL_EXPORT MonoReflectionField*
1778 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1781 gboolean found = FALSE;
1787 klass = handle->parent;
1789 klass = mono_class_from_mono_type (type);
1791 found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1794 /* The managed code will throw the exception */
1798 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1799 mono_error_set_pending_exception (&error);
1803 ICALL_EXPORT MonoReflectionEvent*
1804 ves_icall_System_Reflection_EventInfo_internal_from_handle_type (MonoEvent *handle, MonoType *type)
1812 klass = handle->parent;
1814 klass = mono_class_from_mono_type (type);
1816 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1818 /* Managed code will throw an exception */
1822 MonoReflectionEvent *result = mono_event_get_object_checked (mono_domain_get (), klass, handle, &error);
1823 mono_error_set_pending_exception (&error);
1828 ICALL_EXPORT MonoReflectionProperty*
1829 ves_icall_System_Reflection_PropertyInfo_internal_from_handle_type (MonoProperty *handle, MonoType *type)
1837 klass = handle->parent;
1839 klass = mono_class_from_mono_type (type);
1841 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1843 /* Managed code will throw an exception */
1847 MonoReflectionProperty *result = mono_property_get_object_checked (mono_domain_get (), klass, handle, &error);
1848 mono_error_set_pending_exception (&error);
1852 ICALL_EXPORT MonoArray*
1853 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1856 MonoType *type = mono_field_get_type_checked (field->field, &error);
1859 if (!mono_error_ok (&error)) {
1860 mono_error_set_pending_exception (&error);
1864 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1865 mono_error_set_pending_exception (&error);
1870 vell_icall_get_method_attributes (MonoMethod *method)
1872 return method->flags;
1876 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1879 MonoReflectionType *rt;
1880 MonoDomain *domain = mono_domain_get ();
1881 MonoMethodSignature* sig;
1883 sig = mono_method_signature_checked (method, &error);
1884 if (!mono_error_ok (&error)) {
1885 mono_error_set_pending_exception (&error);
1889 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1890 if (!mono_error_ok (&error)) {
1891 mono_error_set_pending_exception (&error);
1895 MONO_STRUCT_SETREF (info, parent, rt);
1897 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1898 if (!mono_error_ok (&error)) {
1899 mono_error_set_pending_exception (&error);
1903 MONO_STRUCT_SETREF (info, ret, rt);
1905 info->attrs = method->flags;
1906 info->implattrs = method->iflags;
1907 if (sig->call_convention == MONO_CALL_DEFAULT)
1908 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1910 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1915 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1918 ICALL_EXPORT MonoArray*
1919 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1922 MonoDomain *domain = mono_domain_get ();
1924 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1925 mono_error_set_pending_exception (&error);
1929 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1930 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1933 MonoDomain *domain = mono_domain_get ();
1934 MonoReflectionMarshalAsAttribute* res = NULL;
1935 MonoMarshalSpec **mspecs;
1938 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1939 mono_method_get_marshal_info (method, mspecs);
1942 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1943 if (!mono_error_ok (&error)) {
1944 mono_error_set_pending_exception (&error);
1949 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1951 mono_metadata_free_marshal_spec (mspecs [i]);
1958 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1960 MonoClass *parent = field->field->parent;
1961 if (!parent->size_inited)
1962 mono_class_init (parent);
1963 mono_class_setup_fields_locking (parent);
1965 return field->field->offset - sizeof (MonoObject);
1968 ICALL_EXPORT MonoReflectionType*
1969 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1972 MonoReflectionType *ret;
1975 parent = declaring? field->field->parent: field->klass;
1977 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1978 mono_error_set_pending_exception (&error);
1984 ICALL_EXPORT MonoObject *
1985 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1988 MonoClass *fklass = field->klass;
1989 MonoClassField *cf = field->field;
1990 MonoDomain *domain = mono_object_domain (field);
1992 if (fklass->image->assembly->ref_only) {
1993 mono_set_pending_exception (mono_get_exception_invalid_operation (
1994 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1998 if (mono_security_core_clr_enabled () &&
1999 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
2000 mono_error_set_pending_exception (&error);
2004 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
2005 mono_error_set_pending_exception (&error);
2010 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
2013 MonoClassField *cf = field->field;
2017 if (field->klass->image->assembly->ref_only) {
2018 mono_set_pending_exception (mono_get_exception_invalid_operation (
2019 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
2023 if (mono_security_core_clr_enabled () &&
2024 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
2025 mono_error_set_pending_exception (&error);
2029 type = mono_field_get_type_checked (cf, &error);
2030 if (!mono_error_ok (&error)) {
2031 mono_error_set_pending_exception (&error);
2035 v = (gchar *) value;
2037 switch (type->type) {
2040 case MONO_TYPE_BOOLEAN:
2043 case MONO_TYPE_CHAR:
2052 case MONO_TYPE_VALUETYPE:
2055 v += sizeof (MonoObject);
2057 case MONO_TYPE_STRING:
2058 case MONO_TYPE_OBJECT:
2059 case MONO_TYPE_CLASS:
2060 case MONO_TYPE_ARRAY:
2061 case MONO_TYPE_SZARRAY:
2064 case MONO_TYPE_GENERICINST: {
2065 MonoGenericClass *gclass = type->data.generic_class;
2066 g_assert (!gclass->context.class_inst->is_open);
2068 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
2069 MonoClass *nklass = mono_class_from_mono_type (type);
2070 MonoObject *nullable;
2073 * Convert the boxed vtype into a Nullable structure.
2074 * This is complicated by the fact that Nullables have
2075 * a variable structure.
2077 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2078 if (!mono_error_ok (&error)) {
2079 mono_error_set_pending_exception (&error);
2083 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2085 v = (gchar *)mono_object_unbox (nullable);
2088 if (gclass->container_class->valuetype && (v != NULL))
2089 v += sizeof (MonoObject);
2093 g_error ("type 0x%x not handled in "
2094 "ves_icall_FieldInfo_SetValueInternal", type->type);
2099 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2100 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2101 if (!is_ok (&error)) {
2102 mono_error_set_pending_exception (&error);
2105 if (!vtable->initialized) {
2106 if (!mono_runtime_class_init_full (vtable, &error)) {
2107 mono_error_set_pending_exception (&error);
2111 mono_field_static_set_value (vtable, cf, v);
2113 mono_field_set_value (obj, cf, v);
2118 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2127 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2128 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2132 if (MONO_TYPE_IS_REFERENCE (f->type))
2133 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2135 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2138 ICALL_EXPORT MonoObject *
2139 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2141 MonoObject *o = NULL;
2142 MonoClassField *field = rfield->field;
2144 MonoDomain *domain = mono_object_domain (rfield);
2146 MonoTypeEnum def_type;
2147 const char *def_value;
2151 mono_class_init (field->parent);
2153 t = mono_field_get_type_checked (field, &error);
2154 if (!mono_error_ok (&error)) {
2155 mono_error_set_pending_exception (&error);
2159 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2160 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2164 if (image_is_dynamic (field->parent->image)) {
2165 MonoClass *klass = field->parent;
2166 int fidx = field - klass->fields;
2168 g_assert (fidx >= 0 && fidx < klass->field.count);
2169 g_assert (klass->ext);
2170 g_assert (klass->ext->field_def_values);
2171 def_type = klass->ext->field_def_values [fidx].def_type;
2172 def_value = klass->ext->field_def_values [fidx].data;
2173 if (def_type == MONO_TYPE_END) {
2174 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2178 def_value = mono_class_get_field_default_value (field, &def_type);
2179 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2181 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2186 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2190 case MONO_TYPE_BOOLEAN:
2193 case MONO_TYPE_CHAR:
2201 case MONO_TYPE_R8: {
2204 /* boxed value type */
2205 t = g_new0 (MonoType, 1);
2207 klass = mono_class_from_mono_type (t);
2209 o = mono_object_new_checked (domain, klass, &error);
2210 if (!mono_error_ok (&error)) {
2211 mono_error_set_pending_exception (&error);
2214 v = ((gchar *) o) + sizeof (MonoObject);
2215 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2216 if (mono_error_set_pending_exception (&error))
2220 case MONO_TYPE_STRING:
2221 case MONO_TYPE_CLASS:
2222 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2223 if (mono_error_set_pending_exception (&error))
2227 g_assert_not_reached ();
2233 ICALL_EXPORT MonoReflectionType*
2234 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2237 MonoReflectionType *ret;
2240 type = mono_field_get_type_checked (ref_field->field, &error);
2241 if (!mono_error_ok (&error)) {
2242 mono_error_set_pending_exception (&error);
2246 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2247 if (!mono_error_ok (&error)) {
2248 mono_error_set_pending_exception (&error);
2255 /* From MonoProperty.cs */
2257 PInfo_Attributes = 1,
2258 PInfo_GetMethod = 1 << 1,
2259 PInfo_SetMethod = 1 << 2,
2260 PInfo_ReflectedType = 1 << 3,
2261 PInfo_DeclaringType = 1 << 4,
2266 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2269 MonoReflectionType *rt;
2270 MonoReflectionMethod *rm;
2271 MonoDomain *domain = mono_object_domain (property);
2272 const MonoProperty *pproperty = property->property;
2274 if ((req_info & PInfo_ReflectedType) != 0) {
2275 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2276 if (mono_error_set_pending_exception (&error))
2279 MONO_STRUCT_SETREF (info, parent, rt);
2281 if ((req_info & PInfo_DeclaringType) != 0) {
2282 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2283 if (mono_error_set_pending_exception (&error))
2286 MONO_STRUCT_SETREF (info, declaring_type, rt);
2289 if ((req_info & PInfo_Name) != 0)
2290 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2292 if ((req_info & PInfo_Attributes) != 0)
2293 info->attrs = pproperty->attrs;
2295 if ((req_info & PInfo_GetMethod) != 0) {
2296 if (pproperty->get &&
2297 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2298 pproperty->get->klass == property->klass)) {
2299 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2300 if (mono_error_set_pending_exception (&error))
2306 MONO_STRUCT_SETREF (info, get, rm);
2308 if ((req_info & PInfo_SetMethod) != 0) {
2309 if (pproperty->set &&
2310 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2311 pproperty->set->klass == property->klass)) {
2312 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2313 if (mono_error_set_pending_exception (&error))
2319 MONO_STRUCT_SETREF (info, set, rm);
2322 * There may be other methods defined for properties, though, it seems they are not exposed
2323 * in the reflection API
2328 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2331 MonoReflectionType *rt;
2332 MonoReflectionMethod *rm;
2333 MonoDomain *domain = mono_object_domain (event);
2335 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2336 if (mono_error_set_pending_exception (&error))
2339 MONO_STRUCT_SETREF (info, reflected_type, rt);
2341 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2342 if (mono_error_set_pending_exception (&error))
2345 MONO_STRUCT_SETREF (info, declaring_type, rt);
2347 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2348 info->attrs = event->event->attrs;
2350 if (event->event->add) {
2351 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2352 if (mono_error_set_pending_exception (&error))
2358 MONO_STRUCT_SETREF (info, add_method, rm);
2360 if (event->event->remove) {
2361 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2362 if (mono_error_set_pending_exception (&error))
2368 MONO_STRUCT_SETREF (info, remove_method, rm);
2370 if (event->event->raise) {
2371 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2372 if (mono_error_set_pending_exception (&error))
2378 MONO_STRUCT_SETREF (info, raise_method, rm);
2380 #ifndef MONO_SMALL_CONFIG
2381 if (event->event->other) {
2383 while (event->event->other [n])
2385 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2386 if (mono_error_set_pending_exception (&error))
2388 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2390 for (i = 0; i < n; i++) {
2391 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2392 if (mono_error_set_pending_exception (&error))
2394 mono_array_setref (info->other_methods, i, rm);
2401 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2406 mono_class_setup_interfaces (klass, error);
2407 if (!mono_error_ok (error))
2410 for (i = 0; i < klass->interface_count; i++) {
2411 ic = klass->interfaces [i];
2412 g_hash_table_insert (ifaces, ic, ic);
2414 collect_interfaces (ic, ifaces, error);
2415 if (!mono_error_ok (error))
2421 MonoArray *iface_array;
2422 MonoGenericContext *context;
2426 } FillIfaceArrayData;
2429 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2431 MonoReflectionType *rt;
2432 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2433 MonoClass *ic = (MonoClass *)key;
2434 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2436 if (!mono_error_ok (data->error))
2439 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2440 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2441 if (!mono_error_ok (data->error))
2445 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2446 if (!mono_error_ok (data->error))
2449 mono_array_setref (data->iface_array, data->next_idx++, rt);
2452 mono_metadata_free_type (inflated);
2456 get_interfaces_hash (gconstpointer v1)
2458 MonoClass *k = (MonoClass*)v1;
2460 return k->type_token;
2463 ICALL_EXPORT MonoArray*
2464 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2467 MonoClass *klass = mono_class_from_mono_type (type->type);
2469 FillIfaceArrayData data = { 0 };
2472 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2474 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2475 data.context = mono_class_get_context (klass);
2476 klass = klass->generic_class->container_class;
2479 for (parent = klass; parent; parent = parent->parent) {
2480 mono_class_setup_interfaces (parent, &error);
2481 if (!mono_error_ok (&error))
2483 collect_interfaces (parent, iface_hash, &error);
2484 if (!mono_error_ok (&error))
2488 data.error = &error;
2489 data.domain = mono_object_domain (type);
2491 len = g_hash_table_size (iface_hash);
2493 g_hash_table_destroy (iface_hash);
2494 if (!data.domain->empty_types) {
2495 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2496 if (!is_ok (&error))
2499 return data.domain->empty_types;
2502 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2503 if (!is_ok (&error))
2505 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2506 if (!mono_error_ok (&error))
2509 g_hash_table_destroy (iface_hash);
2510 return data.iface_array;
2513 g_hash_table_destroy (iface_hash);
2514 mono_error_set_pending_exception (&error);
2519 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2521 gboolean variance_used;
2522 MonoClass *klass = mono_class_from_mono_type (type->type);
2523 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2524 MonoReflectionMethod *member;
2527 int i = 0, len, ioffset;
2531 mono_class_init_checked (klass, &error);
2532 if (mono_error_set_pending_exception (&error))
2534 mono_class_init_checked (iclass, &error);
2535 if (mono_error_set_pending_exception (&error))
2538 mono_class_setup_vtable (klass);
2540 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2544 len = mono_class_num_methods (iclass);
2545 domain = mono_object_domain (type);
2546 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2547 if (mono_error_set_pending_exception (&error))
2549 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2550 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2551 if (mono_error_set_pending_exception (&error))
2553 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2555 while ((method = mono_class_get_methods (iclass, &iter))) {
2556 member = mono_method_get_object_checked (domain, method, iclass, &error);
2557 if (mono_error_set_pending_exception (&error))
2559 mono_array_setref (*methods, i, member);
2560 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2561 if (mono_error_set_pending_exception (&error))
2563 mono_array_setref (*targets, i, member);
2570 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2573 MonoClass *klass = mono_class_from_mono_type (type->type);
2575 mono_class_init_checked (klass, &error);
2576 if (mono_error_set_pending_exception (&error))
2579 if (image_is_dynamic (klass->image)) {
2580 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2581 *packing = tb->packing_size;
2582 *size = tb->class_size;
2584 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2588 ICALL_EXPORT MonoReflectionType*
2589 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2592 MonoReflectionType *ret;
2595 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2596 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2597 mono_error_set_pending_exception (&error);
2601 klass = mono_class_from_mono_type (type->type);
2602 mono_class_init_checked (klass, &error);
2603 if (mono_error_set_pending_exception (&error))
2607 // GetElementType should only return a type for:
2608 // Array Pointer PassedByRef
2609 if (type->type->byref)
2610 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2611 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2612 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2613 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2614 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2618 mono_error_set_pending_exception (&error);
2623 ICALL_EXPORT MonoReflectionType*
2624 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2627 MonoReflectionType *ret;
2629 if (type->type->byref)
2632 MonoClass *klass = mono_class_from_mono_type (type->type);
2636 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2637 mono_error_set_pending_exception (&error);
2642 ICALL_EXPORT MonoBoolean
2643 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2645 return type->type->type == MONO_TYPE_PTR;
2648 ICALL_EXPORT MonoBoolean
2649 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2651 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)));
2654 ICALL_EXPORT MonoBoolean
2655 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2657 return type->type->byref;
2660 ICALL_EXPORT MonoBoolean
2661 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2664 MonoClass *klass = mono_class_from_mono_type (type->type);
2665 mono_class_init_checked (klass, &error);
2666 if (mono_error_set_pending_exception (&error))
2669 return mono_class_is_com_object (klass);
2672 ICALL_EXPORT guint32
2673 ves_icall_reflection_get_token (MonoObject* obj)
2676 guint32 result = mono_reflection_get_token_checked (obj, &error);
2677 mono_error_set_pending_exception (&error);
2681 ICALL_EXPORT MonoReflectionModule*
2682 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2685 MonoReflectionModule *result = NULL;
2686 MonoClass *klass = mono_class_from_mono_type (type->type);
2687 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2688 mono_error_set_pending_exception (&error);
2692 ICALL_EXPORT MonoReflectionAssembly*
2693 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2696 MonoDomain *domain = mono_domain_get ();
2697 MonoClass *klass = mono_class_from_mono_type (type->type);
2698 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2699 mono_error_set_pending_exception (&error);
2703 ICALL_EXPORT MonoReflectionType*
2704 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2707 MonoReflectionType *ret;
2708 MonoDomain *domain = mono_domain_get ();
2711 if (type->type->byref)
2713 if (type->type->type == MONO_TYPE_VAR) {
2714 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2715 klass = param ? param->owner.klass : NULL;
2716 } else if (type->type->type == MONO_TYPE_MVAR) {
2717 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2718 klass = param ? param->owner.method->klass : NULL;
2720 klass = mono_class_from_mono_type (type->type)->nested_in;
2726 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2727 mono_error_set_pending_exception (&error);
2732 ICALL_EXPORT MonoString*
2733 ves_icall_RuntimeType_get_Name (MonoReflectionType *type)
2735 MonoDomain *domain = mono_domain_get ();
2736 MonoClass *klass = mono_class_from_mono_type (type->type);
2738 if (type->type->byref) {
2739 char *n = g_strdup_printf ("%s&", klass->name);
2740 MonoString *res = mono_string_new (domain, n);
2746 return mono_string_new (domain, klass->name);
2750 ICALL_EXPORT MonoString*
2751 ves_icall_RuntimeType_get_Namespace (MonoReflectionType *type)
2753 MonoDomain *domain = mono_domain_get ();
2754 MonoClass *klass = mono_class_from_mono_type (type->type);
2756 while (klass->nested_in)
2757 klass = klass->nested_in;
2759 if (klass->name_space [0] == '\0')
2762 return mono_string_new (domain, klass->name_space);
2766 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2770 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2771 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2775 klass = mono_class_from_mono_type (type->type);
2781 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2783 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2786 ICALL_EXPORT MonoArray*
2787 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2790 MonoReflectionType *rt;
2792 MonoClass *klass, *pklass;
2793 MonoDomain *domain = mono_object_domain (type);
2796 klass = mono_class_from_mono_type (type->type);
2798 if (klass->generic_container) {
2799 MonoGenericContainer *container = klass->generic_container;
2800 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2801 if (mono_error_set_pending_exception (&error))
2803 for (i = 0; i < container->type_argc; ++i) {
2804 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2806 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2807 if (mono_error_set_pending_exception (&error))
2810 mono_array_setref (res, i, rt);
2812 } else if (klass->generic_class) {
2813 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2814 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2815 if (mono_error_set_pending_exception (&error))
2817 for (i = 0; i < inst->type_argc; ++i) {
2818 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2819 if (mono_error_set_pending_exception (&error))
2822 mono_array_setref (res, i, rt);
2830 ICALL_EXPORT gboolean
2831 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2835 if (!IS_MONOTYPE (type))
2838 if (type->type->byref)
2841 klass = mono_class_from_mono_type (type->type);
2842 return klass->generic_container != NULL;
2845 ICALL_EXPORT MonoReflectionType*
2846 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2849 MonoReflectionType *ret;
2852 if (type->type->byref)
2855 klass = mono_class_from_mono_type (type->type);
2857 if (klass->generic_container) {
2858 return type; /* check this one */
2860 if (klass->generic_class) {
2861 MonoClass *generic_class = klass->generic_class->container_class;
2864 tb = mono_class_get_ref_info (generic_class);
2866 if (generic_class->wastypebuilder && tb)
2867 return (MonoReflectionType *)tb;
2869 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2870 mono_error_set_pending_exception (&error);
2878 ICALL_EXPORT MonoReflectionType*
2879 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2882 MonoReflectionType *ret;
2884 MonoType *geninst, **types;
2887 g_assert (IS_MONOTYPE (type));
2888 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2889 if (mono_error_set_pending_exception (&error))
2892 count = mono_array_length (type_array);
2893 types = g_new0 (MonoType *, count);
2895 for (i = 0; i < count; i++) {
2896 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2897 types [i] = t->type;
2900 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2903 mono_error_set_pending_exception (&error);
2907 klass = mono_class_from_mono_type (geninst);
2909 /*we might inflate to the GTD*/
2910 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2911 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2915 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2916 mono_error_set_pending_exception (&error);
2921 ICALL_EXPORT gboolean
2922 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2926 if (!IS_MONOTYPE (type))
2929 if (type->type->byref)
2932 klass = mono_class_from_mono_type (type->type);
2933 return klass->generic_class != NULL || klass->generic_container != NULL;
2937 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2939 if (!IS_MONOTYPE (type))
2942 if (is_generic_parameter (type->type))
2943 return mono_type_get_generic_param_num (type->type);
2947 ICALL_EXPORT MonoGenericParamInfo *
2948 ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionType *type)
2950 return mono_generic_param_info (type->type->data.generic_param);
2953 ICALL_EXPORT MonoBoolean
2954 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2956 return is_generic_parameter (type->type);
2959 ICALL_EXPORT MonoBoolean
2960 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2962 return is_generic_parameter (tb->type.type);
2966 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2967 MonoReflectionType *t)
2969 enumtype->type = t->type;
2972 ICALL_EXPORT MonoReflectionMethod*
2973 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2974 MonoReflectionMethod* generic)
2981 MonoReflectionMethod *ret = NULL;
2983 domain = ((MonoObject *)type)->vtable->domain;
2985 klass = mono_class_from_mono_type (type->type);
2986 mono_class_init_checked (klass, &error);
2987 if (mono_error_set_pending_exception (&error))
2991 while ((method = mono_class_get_methods (klass, &iter))) {
2992 if (method->token == generic->method->token) {
2993 ret = mono_method_get_object_checked (domain, method, klass, &error);
2994 if (mono_error_set_pending_exception (&error))
3002 ICALL_EXPORT MonoReflectionMethod *
3003 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
3006 MonoType *type = ref_type->type;
3008 MonoReflectionMethod *ret = NULL;
3010 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
3011 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
3014 if (type->type == MONO_TYPE_VAR)
3017 method = mono_type_get_generic_param_owner (type)->owner.method;
3020 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
3021 if (!mono_error_ok (&error))
3022 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3026 ICALL_EXPORT MonoBoolean
3027 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
3029 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3033 ICALL_EXPORT MonoBoolean
3034 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
3036 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3041 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
3043 MonoDomain *domain = mono_domain_get ();
3044 MonoImage *image = method->method->klass->image;
3045 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
3046 MonoTableInfo *tables = image->tables;
3047 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
3048 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
3049 guint32 im_cols [MONO_IMPLMAP_SIZE];
3050 guint32 scope_token;
3051 const char *import = NULL;
3052 const char *scope = NULL;
3054 if (image_is_dynamic (image)) {
3055 MonoReflectionMethodAux *method_aux =
3056 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
3058 import = method_aux->dllentry;
3059 scope = method_aux->dll;
3062 if (!import || !scope) {
3063 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
3068 if (piinfo->implmap_idx) {
3069 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
3071 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
3072 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
3073 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
3074 scope = mono_metadata_string_heap (image, scope_token);
3078 *flags = piinfo->piflags;
3079 *entry_point = mono_string_new (domain, import);
3080 *dll_name = mono_string_new (domain, scope);
3083 ICALL_EXPORT MonoReflectionMethod *
3084 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3086 MonoMethodInflated *imethod;
3088 MonoReflectionMethod *ret = NULL;
3091 if (method->method->is_generic)
3094 if (!method->method->is_inflated)
3097 imethod = (MonoMethodInflated *) method->method;
3099 result = imethod->declaring;
3100 /* Not a generic method. */
3101 if (!result->is_generic)
3104 if (image_is_dynamic (method->method->klass->image)) {
3105 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3106 MonoReflectionMethod *res;
3109 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3110 * the dynamic case as well ?
3112 mono_image_lock ((MonoImage*)image);
3113 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3114 mono_image_unlock ((MonoImage*)image);
3120 if (imethod->context.class_inst) {
3121 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3122 /*Generic methods gets the context of the GTD.*/
3123 if (mono_class_get_context (klass)) {
3124 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3125 if (!mono_error_ok (&error))
3130 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3132 if (!mono_error_ok (&error))
3133 mono_error_set_pending_exception (&error);
3137 ICALL_EXPORT gboolean
3138 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3140 return mono_method_signature (method->method)->generic_param_count != 0;
3143 ICALL_EXPORT gboolean
3144 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3146 return method->method->is_generic;
3149 ICALL_EXPORT MonoArray*
3150 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3153 MonoReflectionType *rt;
3158 domain = mono_object_domain (method);
3160 if (method->method->is_inflated) {
3161 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3164 count = inst->type_argc;
3165 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3166 if (mono_error_set_pending_exception (&error))
3169 for (i = 0; i < count; i++) {
3170 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3171 if (mono_error_set_pending_exception (&error))
3174 mono_array_setref (res, i, rt);
3181 count = mono_method_signature (method->method)->generic_param_count;
3182 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3183 if (mono_error_set_pending_exception (&error))
3186 for (i = 0; i < count; i++) {
3187 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3188 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3189 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3191 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3192 if (mono_error_set_pending_exception (&error))
3195 mono_array_setref (res, i, rt);
3201 ICALL_EXPORT MonoObject *
3202 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3206 * Invoke from reflection is supposed to always be a virtual call (the API
3207 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3208 * greater flexibility.
3210 MonoMethod *m = method->method;
3211 MonoMethodSignature *sig = mono_method_signature (m);
3214 void *obj = this_arg;
3218 if (mono_security_core_clr_enabled () &&
3219 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3220 mono_error_set_pending_exception (&error);
3224 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3225 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3226 mono_error_cleanup (&error); /* FIXME does this make sense? */
3227 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3232 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3233 if (!is_ok (&error)) {
3234 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3237 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3238 char *target_name = mono_type_get_full_name (m->klass);
3239 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3240 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3242 g_free (target_name);
3246 m = mono_object_get_virtual_method (this_arg, m);
3247 /* must pass the pointer to the value for valuetype methods */
3248 if (m->klass->valuetype)
3249 obj = mono_object_unbox (this_arg);
3250 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3251 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3256 if (sig->ret->byref) {
3257 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"));
3261 pcount = params? mono_array_length (params): 0;
3262 if (pcount != sig->param_count) {
3263 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3267 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3268 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."));
3272 image = m->klass->image;
3273 if (image->assembly->ref_only) {
3274 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."));
3278 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3279 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3283 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3287 intptr_t *lower_bounds;
3288 pcount = mono_array_length (params);
3289 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3290 /* Note: the synthetized array .ctors have int32 as argument type */
3291 for (i = 0; i < pcount; ++i)
3292 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3294 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3295 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3296 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3297 if (!mono_error_ok (&error)) {
3298 mono_error_set_pending_exception (&error);
3302 for (i = 0; i < mono_array_length (arr); ++i) {
3303 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3304 if (!mono_error_ok (&error)) {
3305 mono_error_set_pending_exception (&error);
3308 mono_array_setref_fast (arr, i, subarray);
3310 return (MonoObject*)arr;
3313 if (m->klass->rank == pcount) {
3314 /* Only lengths provided. */
3315 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3316 if (!mono_error_ok (&error)) {
3317 mono_error_set_pending_exception (&error);
3321 return (MonoObject*)arr;
3323 g_assert (pcount == (m->klass->rank * 2));
3324 /* The arguments are lower-bound-length pairs */
3325 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3327 for (i = 0; i < pcount / 2; ++i) {
3328 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3329 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3332 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3333 if (!mono_error_ok (&error)) {
3334 mono_error_set_pending_exception (&error);
3338 return (MonoObject*)arr;
3341 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3342 mono_error_set_pending_exception (&error);
3346 #ifndef DISABLE_REMOTING
3347 ICALL_EXPORT MonoObject *
3348 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3351 MonoDomain *domain = mono_object_domain (method);
3352 MonoMethod *m = method->method;
3353 MonoMethodSignature *sig = mono_method_signature (m);
3354 MonoArray *out_args;
3356 int i, j, outarg_count = 0;
3358 if (m->klass == mono_defaults.object_class) {
3359 if (!strcmp (m->name, "FieldGetter")) {
3360 MonoClass *k = this_arg->vtable->klass;
3364 /* If this is a proxy, then it must be a CBO */
3365 if (k == mono_defaults.transparent_proxy_class) {
3366 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3367 this_arg = tp->rp->unwrapped_server;
3368 g_assert (this_arg);
3369 k = this_arg->vtable->klass;
3372 name = mono_array_get (params, MonoString *, 1);
3373 str = mono_string_to_utf8_checked (name, &error);
3374 if (mono_error_set_pending_exception (&error))
3378 MonoClassField* field = mono_class_get_field_from_name (k, str);
3381 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3382 if (field_klass->valuetype) {
3383 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3384 if (mono_error_set_pending_exception (&error))
3387 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3389 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3390 if (mono_error_set_pending_exception (&error))
3392 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3393 mono_array_setref (out_args, 0, result);
3400 g_assert_not_reached ();
3402 } else if (!strcmp (m->name, "FieldSetter")) {
3403 MonoClass *k = this_arg->vtable->klass;
3409 /* If this is a proxy, then it must be a CBO */
3410 if (k == mono_defaults.transparent_proxy_class) {
3411 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3412 this_arg = tp->rp->unwrapped_server;
3413 g_assert (this_arg);
3414 k = this_arg->vtable->klass;
3417 name = mono_array_get (params, MonoString *, 1);
3418 str = mono_string_to_utf8_checked (name, &error);
3419 if (mono_error_set_pending_exception (&error))
3423 MonoClassField* field = mono_class_get_field_from_name (k, str);
3426 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3427 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3429 if (field_klass->valuetype) {
3430 size = mono_type_size (field->type, &align);
3431 g_assert (size == mono_class_value_size (field_klass, NULL));
3432 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3434 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3437 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3438 if (mono_error_set_pending_exception (&error))
3440 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3449 g_assert_not_reached ();
3454 for (i = 0; i < mono_array_length (params); i++) {
3455 if (sig->params [i]->byref)
3459 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3460 if (mono_error_set_pending_exception (&error))
3463 /* handle constructors only for objects already allocated */
3464 if (!strcmp (method->method->name, ".ctor"))
3465 g_assert (this_arg);
3467 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3468 g_assert (!method->method->klass->valuetype);
3469 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3470 if (mono_error_set_pending_exception (&error))
3473 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3474 if (sig->params [i]->byref) {
3476 arg = mono_array_get (params, gpointer, i);
3477 mono_array_setref (out_args, j, arg);
3482 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3489 read_enum_value (const char *mem, int type)
3492 case MONO_TYPE_BOOLEAN:
3494 return *(guint8*)mem;
3496 return *(gint8*)mem;
3497 case MONO_TYPE_CHAR:
3499 return read16 (mem);
3501 return (gint16) read16 (mem);
3503 return read32 (mem);
3505 return (gint32) read32 (mem);
3508 return read64 (mem);
3510 g_assert_not_reached ();
3516 write_enum_value (char *mem, int type, guint64 value)
3520 case MONO_TYPE_I1: {
3521 guint8 *p = (guint8*)mem;
3527 case MONO_TYPE_CHAR: {
3528 guint16 *p = (guint16 *)mem;
3533 case MONO_TYPE_I4: {
3534 guint32 *p = (guint32 *)mem;
3539 case MONO_TYPE_I8: {
3540 guint64 *p = (guint64 *)mem;
3545 g_assert_not_reached ();
3550 ICALL_EXPORT MonoObject *
3551 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3559 domain = mono_object_domain (enumType);
3560 enumc = mono_class_from_mono_type (enumType->type);
3562 mono_class_init_checked (enumc, &error);
3563 if (mono_error_set_pending_exception (&error))
3566 etype = mono_class_enum_basetype (enumc);
3568 res = mono_object_new_checked (domain, enumc, &error);
3569 if (mono_error_set_pending_exception (&error))
3571 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3576 ICALL_EXPORT MonoBoolean
3577 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3579 int size = mono_class_value_size (a->vtable->klass, NULL);
3580 guint64 a_val = 0, b_val = 0;
3582 memcpy (&a_val, mono_object_unbox (a), size);
3583 memcpy (&b_val, mono_object_unbox (b), size);
3585 return (a_val & b_val) == b_val;
3588 ICALL_EXPORT MonoObject *
3589 ves_icall_System_Enum_get_value (MonoObject *eobj)
3601 g_assert (eobj->vtable->klass->enumtype);
3603 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3604 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3605 if (mono_error_set_pending_exception (&error))
3607 dst = (char *)res + sizeof (MonoObject);
3608 src = (char *)eobj + sizeof (MonoObject);
3609 size = mono_class_value_size (enumc, NULL);
3611 memcpy (dst, src, size);
3616 ICALL_EXPORT MonoReflectionType *
3617 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3620 MonoReflectionType *ret;
3624 klass = mono_class_from_mono_type (type->type);
3625 mono_class_init_checked (klass, &error);
3626 if (mono_error_set_pending_exception (&error))
3629 etype = mono_class_enum_basetype (klass);
3631 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3635 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3636 mono_error_set_pending_exception (&error);
3642 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3644 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3645 gpointer odata = (char *)other + sizeof (MonoObject);
3646 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3647 g_assert (basetype);
3652 if (eobj->vtable->klass != other->vtable->klass)
3655 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3656 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3657 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3660 return me > other ? 1 : -1; \
3663 switch (basetype->type) {
3665 COMPARE_ENUM_VALUES (guint8);
3667 COMPARE_ENUM_VALUES (gint8);
3668 case MONO_TYPE_CHAR:
3670 COMPARE_ENUM_VALUES (guint16);
3672 COMPARE_ENUM_VALUES (gint16);
3674 COMPARE_ENUM_VALUES (guint32);
3676 COMPARE_ENUM_VALUES (gint32);
3678 COMPARE_ENUM_VALUES (guint64);
3680 COMPARE_ENUM_VALUES (gint64);
3684 #undef COMPARE_ENUM_VALUES
3685 /* indicates that the enum was of an unsupported unerlying type */
3690 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3692 gpointer data = (char *)eobj + sizeof (MonoObject);
3693 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3694 g_assert (basetype);
3696 switch (basetype->type) {
3697 case MONO_TYPE_I1: {
3698 gint8 value = *((gint8*)data);
3699 return ((int)value ^ (int)value << 8);
3702 return *((guint8*)data);
3703 case MONO_TYPE_CHAR:
3705 return *((guint16*)data);
3707 case MONO_TYPE_I2: {
3708 gint16 value = *((gint16*)data);
3709 return ((int)(guint16)value | (((int)value) << 16));
3712 return *((guint32*)data);
3714 return *((gint32*)data);
3716 case MONO_TYPE_I8: {
3717 gint64 value = *((gint64*)data);
3718 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3721 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3726 ICALL_EXPORT MonoBoolean
3727 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3730 MonoDomain *domain = mono_object_domain (type);
3731 MonoClass *enumc = mono_class_from_mono_type (type->type);
3732 guint j = 0, nvalues;
3734 MonoClassField *field;
3736 guint64 field_value, previous_value = 0;
3737 gboolean sorted = TRUE;
3739 mono_class_init_checked (enumc, &error);
3740 if (mono_error_set_pending_exception (&error))
3744 if (!enumc->enumtype) {
3745 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3749 base_type = mono_class_enum_basetype (enumc)->type;
3751 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3752 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3753 if (mono_error_set_pending_exception (&error))
3755 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3756 if (mono_error_set_pending_exception (&error))
3760 while ((field = mono_class_get_fields (enumc, &iter))) {
3762 MonoTypeEnum def_type;
3764 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3766 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3768 if (mono_field_is_deleted (field))
3770 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3772 p = mono_class_get_field_default_value (field, &def_type);
3773 /* len = */ mono_metadata_decode_blob_size (p, &p);
3775 field_value = read_enum_value (p, base_type);
3776 mono_array_set (*values, guint64, j, field_value);
3778 if (previous_value > field_value)
3781 previous_value = field_value;
3789 BFLAGS_IgnoreCase = 1,
3790 BFLAGS_DeclaredOnly = 2,
3791 BFLAGS_Instance = 4,
3793 BFLAGS_Public = 0x10,
3794 BFLAGS_NonPublic = 0x20,
3795 BFLAGS_FlattenHierarchy = 0x40,
3796 BFLAGS_InvokeMethod = 0x100,
3797 BFLAGS_CreateInstance = 0x200,
3798 BFLAGS_GetField = 0x400,
3799 BFLAGS_SetField = 0x800,
3800 BFLAGS_GetProperty = 0x1000,
3801 BFLAGS_SetProperty = 0x2000,
3802 BFLAGS_ExactBinding = 0x10000,
3803 BFLAGS_SuppressChangeType = 0x20000,
3804 BFLAGS_OptionalParamBinding = 0x40000
3807 ICALL_EXPORT GPtrArray*
3808 ves_icall_RuntimeType_GetFields_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
3811 MonoClass *startklass, *klass;
3814 int (*compare_func) (const char *s1, const char *s2) = NULL;
3815 MonoClassField *field;
3817 if (type->type->byref) {
3818 return g_ptr_array_new ();
3821 mono_error_init (&error);
3823 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3825 klass = startklass = mono_class_from_mono_type (type->type);
3827 GPtrArray *ptr_array = g_ptr_array_sized_new (16);
3830 if (mono_class_has_failure (klass)) {
3831 mono_error_set_for_class_failure (&error, klass);
3836 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3837 guint32 flags = mono_field_get_flags (field);
3839 if (mono_field_is_deleted_with_flags (field, flags))
3841 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3842 if (bflags & BFLAGS_Public)
3844 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3845 if (bflags & BFLAGS_NonPublic) {
3852 if (flags & FIELD_ATTRIBUTE_STATIC) {
3853 if (bflags & BFLAGS_Static)
3854 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3857 if (bflags & BFLAGS_Instance)
3864 if (utf8_name != NULL && compare_func (mono_field_get_name (field), utf8_name))
3867 g_ptr_array_add (ptr_array, field);
3869 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3875 g_ptr_array_free (ptr_array, TRUE);
3876 mono_error_set_pending_exception (&error);
3881 method_nonpublic (MonoMethod* method, gboolean start_klass)
3883 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3884 case METHOD_ATTRIBUTE_ASSEM:
3885 return (start_klass || mono_defaults.generic_ilist_class);
3886 case METHOD_ATTRIBUTE_PRIVATE:
3888 case METHOD_ATTRIBUTE_PUBLIC:
3896 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoError *error)
3899 MonoClass *startklass;
3903 /*FIXME, use MonoBitSet*/
3904 guint32 method_slots_default [8];
3905 guint32 *method_slots = NULL;
3906 int (*compare_func) (const char *s1, const char *s2) = NULL;
3908 array = g_ptr_array_new ();
3910 mono_error_init (error);
3913 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3915 /* An optimization for calls made from Delegate:CreateDelegate () */
3916 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3917 method = mono_get_delegate_invoke (klass);
3920 g_ptr_array_add (array, method);
3924 mono_class_setup_methods (klass);
3925 mono_class_setup_vtable (klass);
3926 if (mono_class_has_failure (klass))
3929 if (is_generic_parameter (&klass->byval_arg))
3930 nslots = mono_class_get_vtable_size (klass->parent);
3932 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3933 if (nslots >= sizeof (method_slots_default) * 8) {
3934 method_slots = g_new0 (guint32, nslots / 32 + 1);
3936 method_slots = method_slots_default;
3937 memset (method_slots, 0, sizeof (method_slots_default));
3940 mono_class_setup_methods (klass);
3941 mono_class_setup_vtable (klass);
3942 if (mono_class_has_failure (klass))
3946 while ((method = mono_class_get_methods (klass, &iter))) {
3948 if (method->slot != -1) {
3949 g_assert (method->slot < nslots);
3950 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3952 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3953 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3956 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3958 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3959 if (bflags & BFLAGS_Public)
3961 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3967 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3968 if (bflags & BFLAGS_Static)
3969 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3972 if (bflags & BFLAGS_Instance)
3980 if (compare_func (name, method->name))
3985 g_ptr_array_add (array, method);
3987 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3989 if (method_slots != method_slots_default)
3990 g_free (method_slots);
3995 if (method_slots != method_slots_default)
3996 g_free (method_slots);
3997 g_ptr_array_free (array, TRUE);
3999 g_assert (mono_class_has_failure (klass));
4000 mono_error_set_for_class_failure (error, klass);
4004 ICALL_EXPORT GPtrArray*
4005 ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionType *type, const char *mname, guint32 bflags, MonoBoolean ignore_case)
4008 GPtrArray *method_array;
4011 klass = mono_class_from_mono_type (type->type);
4012 if (type->type->byref) {
4013 return g_ptr_array_new ();
4016 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &error);
4017 mono_error_set_pending_exception (&error);
4018 return method_array;
4021 ICALL_EXPORT GPtrArray*
4022 ves_icall_RuntimeType_GetConstructors_native (MonoReflectionType *type, guint32 bflags)
4024 MonoClass *startklass, *klass;
4027 gpointer iter = NULL;
4028 GPtrArray *res_array;
4031 if (type->type->byref) {
4032 return g_ptr_array_new ();
4035 klass = startklass = mono_class_from_mono_type (type->type);
4037 mono_class_setup_methods (klass);
4038 if (mono_class_has_failure (klass)) {
4039 mono_error_init (&error);
4040 mono_error_set_for_class_failure (&error, klass);
4041 mono_error_set_pending_exception (&error);
4045 res_array = g_ptr_array_sized_new (4); /* FIXME, guestimating */
4048 while ((method = mono_class_get_methods (klass, &iter))) {
4050 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
4052 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4053 if (bflags & BFLAGS_Public)
4056 if (bflags & BFLAGS_NonPublic)
4062 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4063 if (bflags & BFLAGS_Static)
4064 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4067 if (bflags & BFLAGS_Instance)
4073 g_ptr_array_add (res_array, method);
4080 property_hash (gconstpointer data)
4082 MonoProperty *prop = (MonoProperty*)data;
4084 return g_str_hash (prop->name);
4088 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
4090 if (method1->slot != -1 && method1->slot == method2->slot)
4093 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
4094 if (method1->is_inflated)
4095 method1 = ((MonoMethodInflated*) method1)->declaring;
4096 if (method2->is_inflated)
4097 method2 = ((MonoMethodInflated*) method2)->declaring;
4100 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4104 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4106 // Properties are hide-by-name-and-signature
4107 if (!g_str_equal (prop1->name, prop2->name))
4110 /* If we see a property in a generic method, we want to
4111 compare the generic signatures, not the inflated signatures
4112 because we might conflate two properties that were
4116 public T this[T t] { getter { return t; } } // method 1
4117 public U this[U u] { getter { return u; } } // method 2
4120 If we see int Foo<int,int>::Item[int] we need to know if
4121 the indexer came from method 1 or from method 2, and we
4122 shouldn't conflate them. (Bugzilla 36283)
4124 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4127 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4134 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4139 return method_nonpublic (accessor, start_klass);
4142 ICALL_EXPORT GPtrArray*
4143 ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionType *type, gchar *propname, guint32 bflags, MonoBoolean ignore_case)
4146 MonoClass *startklass, *klass;
4151 int (*compare_func) (const char *s1, const char *s2) = NULL;
4153 GHashTable *properties = NULL;
4154 GPtrArray *res_array;
4156 if (type->type->byref) {
4157 return g_ptr_array_new ();
4160 mono_error_init (&error);
4162 klass = startklass = mono_class_from_mono_type (type->type);
4164 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4166 res_array = g_ptr_array_sized_new (8); /*This the average for ASP.NET types*/
4168 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4170 mono_class_setup_methods (klass);
4171 mono_class_setup_vtable (klass);
4172 if (mono_class_has_failure (klass)) {
4173 mono_error_set_for_class_failure (&error, klass);
4178 while ((prop = mono_class_get_properties (klass, &iter))) {
4184 flags = method->flags;
4187 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4188 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4189 if (bflags & BFLAGS_Public)
4191 } else if (bflags & BFLAGS_NonPublic) {
4192 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4193 property_accessor_nonpublic(prop->set, startklass == klass)) {
4200 if (flags & METHOD_ATTRIBUTE_STATIC) {
4201 if (bflags & BFLAGS_Static)
4202 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4205 if (bflags & BFLAGS_Instance)
4213 if (propname != NULL && compare_func (propname, prop->name))
4216 if (g_hash_table_lookup (properties, prop))
4219 g_ptr_array_add (res_array, prop);
4221 g_hash_table_insert (properties, prop, prop);
4223 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4226 g_hash_table_destroy (properties);
4233 g_hash_table_destroy (properties);
4234 g_ptr_array_free (res_array, TRUE);
4236 mono_error_set_pending_exception (&error);
4242 event_hash (gconstpointer data)
4244 MonoEvent *event = (MonoEvent*)data;
4246 return g_str_hash (event->name);
4250 event_equal (MonoEvent *event1, MonoEvent *event2)
4252 // Events are hide-by-name
4253 return g_str_equal (event1->name, event2->name);
4256 ICALL_EXPORT GPtrArray*
4257 ves_icall_RuntimeType_GetEvents_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
4260 MonoClass *startklass, *klass;
4265 int (*compare_func) (const char *s1, const char *s2) = NULL;
4266 GHashTable *events = NULL;
4267 GPtrArray *res_array;
4269 if (type->type->byref) {
4270 return g_ptr_array_new ();
4273 mono_error_init (&error);
4275 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4277 res_array = g_ptr_array_sized_new (4);
4279 klass = startklass = mono_class_from_mono_type (type->type);
4281 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4283 mono_class_setup_methods (klass);
4284 mono_class_setup_vtable (klass);
4285 if (mono_class_has_failure (klass)) {
4286 mono_error_set_for_class_failure (&error, klass);
4291 while ((event = mono_class_get_events (klass, &iter))) {
4293 method = event->add;
4295 method = event->remove;
4297 method = event->raise;
4299 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4300 if (bflags & BFLAGS_Public)
4302 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4303 if (bflags & BFLAGS_NonPublic)
4308 if (bflags & BFLAGS_NonPublic)
4314 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4315 if (bflags & BFLAGS_Static)
4316 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4319 if (bflags & BFLAGS_Instance)
4324 if (bflags & BFLAGS_Instance)
4329 if (utf8_name != NULL && compare_func (event->name, utf8_name))
4332 if (g_hash_table_lookup (events, event))
4335 g_ptr_array_add (res_array, event);
4337 g_hash_table_insert (events, event, event);
4339 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4342 g_hash_table_destroy (events);
4348 g_hash_table_destroy (events);
4350 g_ptr_array_free (res_array, TRUE);
4352 mono_error_set_pending_exception (&error);
4356 ICALL_EXPORT GPtrArray *
4357 ves_icall_RuntimeType_GetNestedTypes_native (MonoReflectionType *type, MonoString *name, guint32 bflags)
4364 GPtrArray *res_array;
4366 if (type->type->byref) {
4367 return g_ptr_array_new ();
4370 klass = mono_class_from_mono_type (type->type);
4373 * If a nested type is generic, return its generic type definition.
4374 * Note that this means that the return value is essentially the set
4375 * of nested types of the generic type definition of @klass.
4377 * A note in MSDN claims that a generic type definition can have
4378 * nested types that aren't generic. In any case, the container of that
4379 * nested type would be the generic type definition.
4381 if (klass->generic_class)
4382 klass = klass->generic_class->container_class;
4384 res_array = g_ptr_array_new ();
4387 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4389 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4390 if (bflags & BFLAGS_Public)
4393 if (bflags & BFLAGS_NonPublic)
4401 str = mono_string_to_utf8_checked (name, &error);
4402 if (!is_ok (&error))
4404 mono_identifier_unescape_type_name_chars (str);
4407 if (strcmp (nested->name, str))
4411 g_ptr_array_add (res_array, &nested->byval_arg);
4419 ICALL_EXPORT MonoReflectionType*
4420 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4423 MonoReflectionType *ret;
4425 MonoType *type = NULL;
4426 MonoTypeNameParse info;
4427 gboolean type_resolve;
4429 /* On MS.NET, this does not fire a TypeResolve event */
4430 type_resolve = TRUE;
4431 str = mono_string_to_utf8_checked (name, &error);
4432 if (mono_error_set_pending_exception (&error))
4434 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4435 if (!mono_reflection_parse_type (str, &info)) {
4437 mono_reflection_free_type_info (&info);
4439 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4442 /*g_print ("failed parse\n");*/
4446 if (info.assembly.name) {
4448 mono_reflection_free_type_info (&info);
4450 /* 1.0 and 2.0 throw different exceptions */
4451 if (mono_defaults.generic_ilist_class)
4452 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4454 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4460 if (module != NULL) {
4461 if (module->image) {
4462 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4463 if (!is_ok (&error)) {
4465 mono_reflection_free_type_info (&info);
4466 mono_error_set_pending_exception (&error);
4473 if (assembly_is_dynamic (assembly->assembly)) {
4474 /* Enumerate all modules */
4475 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4479 if (abuilder->modules) {
4480 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4481 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4482 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4483 if (!is_ok (&error)) {
4485 mono_reflection_free_type_info (&info);
4486 mono_error_set_pending_exception (&error);
4494 if (!type && abuilder->loaded_modules) {
4495 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4496 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4497 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4498 if (!is_ok (&error)) {
4500 mono_reflection_free_type_info (&info);
4501 mono_error_set_pending_exception (&error);
4510 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4511 if (!is_ok (&error)) {
4513 mono_reflection_free_type_info (&info);
4514 mono_error_set_pending_exception (&error);
4519 mono_reflection_free_type_info (&info);
4521 MonoException *e = NULL;
4524 e = mono_get_exception_type_load (name, NULL);
4527 mono_set_pending_exception (e);
4531 if (type->type == MONO_TYPE_CLASS) {
4532 MonoClass *klass = mono_type_get_class (type);
4534 /* need to report exceptions ? */
4535 if (throwOnError && mono_class_has_failure (klass)) {
4536 /* report SecurityException (or others) that occured when loading the assembly */
4537 MonoException *exc = mono_class_get_exception_for_failure (klass);
4538 mono_set_pending_exception (exc);
4543 /* g_print ("got it\n"); */
4544 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4545 mono_error_set_pending_exception (&error);
4551 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4554 gchar *shadow_ini_file;
4557 /* Check for shadow-copied assembly */
4558 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4559 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4561 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4562 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4568 g_free (shadow_ini_file);
4569 if (content != NULL) {
4572 *filename = content;
4579 ICALL_EXPORT MonoString *
4580 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4582 MonoDomain *domain = mono_object_domain (assembly);
4583 MonoAssembly *mass = assembly->assembly;
4584 MonoString *res = NULL;
4589 if (g_path_is_absolute (mass->image->name)) {
4590 absolute = g_strdup (mass->image->name);
4591 dirname = g_path_get_dirname (absolute);
4593 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4594 dirname = g_strdup (mass->basedir);
4597 replace_shadow_path (domain, dirname, &absolute);
4602 for (i = strlen (absolute) - 1; i >= 0; i--)
4603 if (absolute [i] == '\\')
4608 uri = g_filename_to_uri (absolute, NULL, NULL);
4610 const char *prepend = "file://";
4612 if (*absolute == '/' && *(absolute + 1) == '/') {
4615 prepend = "file:///";
4618 uri = g_strconcat (prepend, absolute, NULL);
4622 res = mono_string_new (domain, uri);
4629 ICALL_EXPORT MonoBoolean
4630 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4632 MonoAssembly *mass = assembly->assembly;
4634 return mass->in_gac;
4637 ICALL_EXPORT MonoReflectionAssembly*
4638 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4643 MonoImageOpenStatus status;
4644 MonoReflectionAssembly* result = NULL;
4646 name = mono_string_to_utf8_checked (mname, &error);
4647 if (mono_error_set_pending_exception (&error))
4649 res = mono_assembly_load_with_partial_name (name, &status);
4655 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4657 mono_error_set_pending_exception (&error);
4661 ICALL_EXPORT MonoString *
4662 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4664 MonoDomain *domain = mono_object_domain (assembly);
4667 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4672 ICALL_EXPORT MonoBoolean
4673 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4675 return assembly->assembly->ref_only;
4678 ICALL_EXPORT MonoString *
4679 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4681 MonoDomain *domain = mono_object_domain (assembly);
4683 return mono_string_new (domain, assembly->assembly->image->version);
4686 ICALL_EXPORT MonoReflectionMethod*
4687 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4690 MonoReflectionMethod *res = NULL;
4693 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4697 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4698 if (!mono_error_ok (&error))
4701 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4704 if (!mono_error_ok (&error))
4705 mono_error_set_pending_exception (&error);
4709 ICALL_EXPORT MonoReflectionModule*
4710 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4713 MonoReflectionModule *result = NULL;
4714 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4715 if (!mono_error_ok (&error))
4716 mono_error_set_pending_exception (&error);
4720 ICALL_EXPORT MonoArray*
4721 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4724 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4725 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4726 if (mono_error_set_pending_exception (&error))
4731 for (i = 0; i < table->rows; ++i) {
4732 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4733 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4738 ICALL_EXPORT MonoString*
4739 ves_icall_System_Reflection_Assembly_GetAotId ()
4742 guint8 aotid_sum = 0;
4743 MonoDomain* domain = mono_domain_get ();
4745 if (!domain->entry_assembly || !domain->entry_assembly->image)
4748 guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
4750 for (i = 0; i < 16; ++i)
4751 aotid_sum |= (*aotid)[i];
4756 return mono_string_new (domain, mono_guid_to_string((guint8*) aotid));
4760 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4762 static MonoMethod *create_version = NULL;
4766 mono_error_init (error);
4769 if (!create_version) {
4770 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4771 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4772 g_assert (create_version);
4773 mono_method_desc_free (desc);
4779 args [3] = &revision;
4780 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4781 return_val_if_nok (error, NULL);
4783 mono_runtime_invoke_checked (create_version, result, args, error);
4784 return_val_if_nok (error, NULL);
4789 ICALL_EXPORT MonoArray*
4790 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4794 MonoDomain *domain = mono_object_domain (assembly);
4796 static MonoMethod *create_culture = NULL;
4797 MonoImage *image = assembly->assembly->image;
4801 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4804 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4805 if (mono_error_set_pending_exception (&error))
4809 if (count > 0 && !create_culture) {
4810 MonoMethodDesc *desc = mono_method_desc_new (
4811 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4812 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4813 g_assert (create_culture);
4814 mono_method_desc_free (desc);
4817 for (i = 0; i < count; i++) {
4818 MonoObject *version;
4819 MonoReflectionAssemblyName *aname;
4820 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4822 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4824 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4825 domain, mono_class_get_assembly_name_class (), &error);
4826 if (mono_error_set_pending_exception (&error))
4829 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4831 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4832 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4833 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4834 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4835 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4836 aname->versioncompat = 1; /* SameMachine (default) */
4837 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4839 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4840 if (mono_error_set_pending_exception (&error))
4843 MONO_OBJECT_SETREF (aname, version, version);
4845 if (create_culture) {
4847 MonoBoolean assembly_ref = 1;
4848 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4849 args [1] = &assembly_ref;
4851 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4852 if (mono_error_set_pending_exception (&error))
4855 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4858 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4859 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4860 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4862 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4863 /* public key token isn't copied - the class library will
4864 automatically generate it from the public key if required */
4865 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4866 if (mono_error_set_pending_exception (&error))
4869 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4870 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4872 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4873 if (mono_error_set_pending_exception (&error))
4876 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4877 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
4880 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
4881 if (mono_error_set_pending_exception (&error))
4884 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4887 /* note: this function doesn't return the codebase on purpose (i.e. it can
4888 be used under partial trust as path information isn't present). */
4890 mono_array_setref (result, i, aname);
4895 /* move this in some file in mono/util/ */
4897 g_concat_dir_and_file (const char *dir, const char *file)
4899 g_return_val_if_fail (dir != NULL, NULL);
4900 g_return_val_if_fail (file != NULL, NULL);
4903 * If the directory name doesn't have a / on the end, we need
4904 * to add one so we get a proper path to the file
4906 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4907 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4909 return g_strconcat (dir, file, NULL);
4913 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4916 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4918 guint32 cols [MONO_MANIFEST_SIZE];
4919 guint32 impl, file_idx;
4923 char *n = mono_string_to_utf8_checked (name, &error);
4924 if (mono_error_set_pending_exception (&error))
4927 for (i = 0; i < table->rows; ++i) {
4928 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4929 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4930 if (strcmp (val, n) == 0)
4934 if (i == table->rows)
4937 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4940 * this code should only be called after obtaining the
4941 * ResourceInfo and handling the other cases.
4943 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4944 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4946 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4951 module = assembly->assembly->image;
4954 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4955 if (mono_error_set_pending_exception (&error))
4957 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4959 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4962 ICALL_EXPORT gboolean
4963 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4966 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4968 guint32 cols [MONO_MANIFEST_SIZE];
4969 guint32 file_cols [MONO_FILE_SIZE];
4973 n = mono_string_to_utf8_checked (name, &error);
4974 if (mono_error_set_pending_exception (&error))
4976 for (i = 0; i < table->rows; ++i) {
4977 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4978 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4979 if (strcmp (val, n) == 0)
4983 if (i == table->rows)
4986 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4987 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4990 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4991 case MONO_IMPLEMENTATION_FILE:
4992 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4993 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4994 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4995 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4996 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4997 if (file_cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA)
5000 info->location = RESOURCE_LOCATION_EMBEDDED;
5003 case MONO_IMPLEMENTATION_ASSEMBLYREF:
5004 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5005 mono_assembly_load_reference (assembly->assembly->image, i - 1);
5006 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
5007 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
5008 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
5010 mono_set_pending_exception (ex);
5013 MonoReflectionAssembly *assm_obj;
5014 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5016 mono_error_set_pending_exception (&error);
5019 MONO_OBJECT_SETREF (info, assembly, assm_obj);
5021 /* Obtain info recursively */
5022 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5023 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5026 case MONO_IMPLEMENTATION_EXP_TYPE:
5027 g_assert_not_reached ();
5035 ICALL_EXPORT MonoObject*
5036 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
5039 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5040 MonoArray *result = NULL;
5045 /* check hash if needed */
5047 n = mono_string_to_utf8_checked (name, &error);
5048 if (mono_error_set_pending_exception (&error))
5051 for (i = 0; i < table->rows; ++i) {
5052 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5053 if (strcmp (val, n) == 0) {
5056 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5057 fn = mono_string_new (mono_object_domain (assembly), n);
5059 return (MonoObject*)fn;
5067 for (i = 0; i < table->rows; ++i) {
5068 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5072 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
5073 if (mono_error_set_pending_exception (&error))
5078 for (i = 0; i < table->rows; ++i) {
5079 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5080 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5081 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5082 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5087 return (MonoObject*)result;
5090 ICALL_EXPORT MonoArray*
5091 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5094 MonoDomain *domain = mono_domain_get();
5097 int i, j, file_count = 0;
5098 MonoImage **modules;
5099 guint32 module_count, real_module_count;
5100 MonoTableInfo *table;
5101 guint32 cols [MONO_FILE_SIZE];
5102 MonoImage *image = assembly->assembly->image;
5104 g_assert (image != NULL);
5105 g_assert (!assembly_is_dynamic (assembly->assembly));
5107 table = &image->tables [MONO_TABLE_FILE];
5108 file_count = table->rows;
5110 modules = image->modules;
5111 module_count = image->module_count;
5113 real_module_count = 0;
5114 for (i = 0; i < module_count; ++i)
5116 real_module_count ++;
5118 klass = mono_class_get_module_class ();
5119 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5120 if (mono_error_set_pending_exception (&error))
5123 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5124 if (mono_error_set_pending_exception (&error))
5127 mono_array_setref (res, 0, image_obj);
5129 for (i = 0; i < module_count; ++i)
5131 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5132 if (mono_error_set_pending_exception (&error))
5134 mono_array_setref (res, j, rm);
5138 for (i = 0; i < file_count; ++i, ++j) {
5139 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5140 if (cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA) {
5141 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5142 if (mono_error_set_pending_exception (&error))
5144 mono_array_setref (res, j, rm);
5147 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5149 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5150 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5153 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5154 if (mono_error_set_pending_exception (&error))
5156 mono_array_setref (res, j, rm);
5163 ICALL_EXPORT MonoReflectionMethod*
5164 ves_icall_GetCurrentMethod (void)
5166 MonoReflectionMethod *res = NULL;
5169 MonoMethod *m = mono_method_get_last_managed ();
5172 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5176 while (m->is_inflated)
5177 m = ((MonoMethodInflated*)m)->declaring;
5179 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5180 mono_error_set_pending_exception (&error);
5186 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5189 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5192 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5193 //method is inflated, we should inflate it on the other class
5194 MonoGenericContext ctx;
5195 ctx.method_inst = inflated->context.method_inst;
5196 ctx.class_inst = inflated->context.class_inst;
5197 if (klass->generic_class)
5198 ctx.class_inst = klass->generic_class->context.class_inst;
5199 else if (klass->generic_container)
5200 ctx.class_inst = klass->generic_container->context.class_inst;
5201 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5202 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5206 mono_class_setup_methods (method->klass);
5207 if (mono_class_has_failure (method->klass))
5209 for (i = 0; i < method->klass->method.count; ++i) {
5210 if (method->klass->methods [i] == method) {
5215 mono_class_setup_methods (klass);
5216 if (mono_class_has_failure (klass))
5218 g_assert (offset >= 0 && offset < klass->method.count);
5219 return klass->methods [offset];
5222 ICALL_EXPORT MonoReflectionMethod*
5223 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check)
5225 MonoReflectionMethod *res = NULL;
5228 if (type && generic_check) {
5229 klass = mono_class_from_mono_type (type);
5230 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5233 if (method->klass != klass) {
5234 method = mono_method_get_equivalent_method (method, klass);
5239 klass = mono_class_from_mono_type (type);
5241 klass = method->klass;
5242 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5243 mono_error_set_pending_exception (&error);
5247 ICALL_EXPORT MonoReflectionMethodBody*
5248 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5251 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5252 mono_error_set_pending_exception (&error);
5256 ICALL_EXPORT MonoReflectionAssembly*
5257 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5260 MonoReflectionAssembly *result;
5261 MonoMethod *dest = NULL;
5263 mono_stack_walk_no_il (get_executing, &dest);
5265 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5267 mono_error_set_pending_exception (&error);
5272 ICALL_EXPORT MonoReflectionAssembly*
5273 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5276 MonoReflectionAssembly *result;
5277 MonoDomain* domain = mono_domain_get ();
5279 if (!domain->entry_assembly)
5282 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5284 mono_error_set_pending_exception (&error);
5288 ICALL_EXPORT MonoReflectionAssembly*
5289 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5294 MonoReflectionAssembly *result;
5297 mono_stack_walk_no_il (get_executing, &dest);
5299 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5303 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5306 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5308 mono_error_set_pending_exception (&error);
5312 ICALL_EXPORT MonoString *
5313 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5314 gboolean assembly_qualified)
5316 MonoDomain *domain = mono_object_domain (object);
5317 MonoTypeNameFormat format;
5322 format = assembly_qualified ?
5323 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5324 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5326 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5328 name = mono_type_get_name_full (object->type, format);
5332 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5337 res = mono_string_new (domain, name);
5344 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5347 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5349 mono_class_init_checked (klass, &error);
5350 mono_error_set_pending_exception (&error);
5351 return mono_security_core_clr_class_level (klass);
5355 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5357 MonoClassField *field = rfield->field;
5358 return mono_security_core_clr_field_level (field, TRUE);
5362 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5364 MonoMethod *method = rfield->method;
5365 return mono_security_core_clr_method_level (method, TRUE);
5369 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)
5371 static MonoMethod *create_culture = NULL;
5375 const char *pkey_ptr;
5377 MonoBoolean assembly_ref = 0;
5379 mono_error_init (error);
5381 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5382 aname->major = name->major;
5383 aname->minor = name->minor;
5384 aname->build = name->build;
5385 aname->flags = name->flags;
5386 aname->revision = name->revision;
5387 aname->hashalg = name->hash_alg;
5388 aname->versioncompat = 1; /* SameMachine (default) */
5389 aname->processor_architecture = name->arch;
5391 if (by_default_version) {
5392 MonoObject *version;
5394 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5395 return_if_nok (error);
5397 MONO_OBJECT_SETREF (aname, version, version);
5401 if (absolute != NULL && *absolute != '\0') {
5402 const gchar *prepend = "file://";
5405 codebase = g_strdup (absolute);
5410 for (i = strlen (codebase) - 1; i >= 0; i--)
5411 if (codebase [i] == '\\')
5414 if (*codebase == '/' && *(codebase + 1) == '/') {
5417 prepend = "file:///";
5421 result = g_strconcat (prepend, codebase, NULL);
5427 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5431 if (!create_culture) {
5432 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5433 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5434 g_assert (create_culture);
5435 mono_method_desc_free (desc);
5438 if (name->culture) {
5439 args [0] = mono_string_new (domain, name->culture);
5440 args [1] = &assembly_ref;
5442 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5443 return_if_nok (error);
5445 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5448 if (name->public_key) {
5449 pkey_ptr = (char*)name->public_key;
5450 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5452 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5453 return_if_nok (error);
5454 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5455 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5456 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5457 } else if (default_publickey) {
5458 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5459 return_if_nok (error);
5460 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5461 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5464 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5465 if (name->public_key_token [0]) {
5469 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5470 return_if_nok (error);
5472 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5473 p = mono_array_addr (keyToken, char, 0);
5475 for (i = 0, j = 0; i < 8; i++) {
5476 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5477 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5480 } else if (default_token) {
5481 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5482 return_if_nok (error);
5483 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5487 ICALL_EXPORT MonoString *
5488 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5490 MonoDomain *domain = mono_object_domain (assembly);
5491 MonoAssembly *mass = assembly->assembly;
5495 name = mono_stringify_assembly_name (&mass->aname);
5496 res = mono_string_new (domain, name);
5503 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5506 gchar *absolute, *dirname;
5507 MonoAssembly *mass = assembly->assembly;
5509 /* XXX this is duplicated code to compute the codebase URI, unify it */
5510 if (g_path_is_absolute (mass->image->name)) {
5511 absolute = g_strdup (mass->image->name);
5512 dirname = g_path_get_dirname (absolute);
5514 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5515 dirname = g_strdup (mass->basedir);
5518 replace_shadow_path (mono_object_domain (assembly), dirname, &absolute);
5521 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5522 mono_error_set_pending_exception (&error);
5528 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5532 MonoImageOpenStatus status = MONO_IMAGE_OK;
5535 MonoAssemblyName name;
5538 filename = mono_string_to_utf8_checked (fname, &error);
5539 if (mono_error_set_pending_exception (&error))
5542 dirname = g_path_get_dirname (filename);
5543 replace_shadow_path (mono_domain_get (), dirname, &filename);
5546 image = mono_image_open (filename, &status);
5552 if (status == MONO_IMAGE_IMAGE_INVALID)
5553 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5555 exc = mono_get_exception_file_not_found2 (NULL, fname);
5556 mono_set_pending_exception (exc);
5560 res = mono_assembly_fill_assembly_name (image, &name);
5562 mono_image_close (image);
5564 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5568 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5569 mono_error_set_pending_exception (&error);
5571 mono_image_close (image);
5575 ICALL_EXPORT MonoBoolean
5576 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5577 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5579 MonoBoolean result = FALSE;
5580 MonoDeclSecurityEntry entry;
5582 /* SecurityAction.RequestMinimum */
5583 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5584 *minimum = entry.blob;
5585 *minLength = entry.size;
5588 /* SecurityAction.RequestOptional */
5589 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5590 *optional = entry.blob;
5591 *optLength = entry.size;
5594 /* SecurityAction.RequestRefuse */
5595 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5596 *refused = entry.blob;
5597 *refLength = entry.size;
5605 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5607 guint32 attrs, visibility;
5609 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5610 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5611 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5614 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5620 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5622 MonoReflectionType *rt;
5625 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5628 mono_error_init (error);
5630 /* we start the count from 1 because we skip the special type <Module> */
5633 for (i = 1; i < tdef->rows; ++i) {
5634 if (mono_module_type_is_visible (tdef, image, i + 1))
5638 count = tdef->rows - 1;
5640 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5641 return_val_if_nok (error, NULL);
5642 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5643 return_val_if_nok (error, NULL);
5645 for (i = 1; i < tdef->rows; ++i) {
5646 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5647 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5650 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5651 return_val_if_nok (error, NULL);
5653 mono_array_setref (res, count, rt);
5655 MonoException *ex = mono_error_convert_to_exception (error);
5656 mono_array_setref (*exceptions, count, ex);
5665 ICALL_EXPORT MonoArray*
5666 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5669 MonoArray *res = NULL;
5670 MonoArray *exceptions = NULL;
5671 MonoImage *image = NULL;
5672 MonoTableInfo *table = NULL;
5675 int i, len, ex_count;
5677 domain = mono_object_domain (assembly);
5679 g_assert (!assembly_is_dynamic (assembly->assembly));
5680 image = assembly->assembly->image;
5681 table = &image->tables [MONO_TABLE_FILE];
5682 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5683 if (mono_error_set_pending_exception (&error))
5686 /* Append data from all modules in the assembly */
5687 for (i = 0; i < table->rows; ++i) {
5688 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5689 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5694 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5695 if (mono_error_set_pending_exception (&error))
5699 /* Append the new types to the end of the array */
5700 if (mono_array_length (res2) > 0) {
5702 MonoArray *res3, *ex3;
5704 len1 = mono_array_length (res);
5705 len2 = mono_array_length (res2);
5707 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5708 if (mono_error_set_pending_exception (&error))
5710 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5711 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5714 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5715 if (mono_error_set_pending_exception (&error))
5717 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5718 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5725 /* the ReflectionTypeLoadException must have all the types (Types property),
5726 * NULL replacing types which throws an exception. The LoaderException must
5727 * contain all exceptions for NULL items.
5730 len = mono_array_length (res);
5733 for (i = 0; i < len; i++) {
5734 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5738 klass = mono_type_get_class (t->type);
5739 if ((klass != NULL) && mono_class_has_failure (klass)) {
5740 /* keep the class in the list */
5741 list = g_list_append (list, klass);
5742 /* and replace Type with NULL */
5743 mono_array_setref (res, i, NULL);
5750 if (list || ex_count) {
5752 MonoException *exc = NULL;
5753 MonoArray *exl = NULL;
5754 int j, length = g_list_length (list) + ex_count;
5756 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5757 if (mono_error_set_pending_exception (&error)) {
5761 /* Types for which mono_class_get_checked () succeeded */
5762 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5763 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5764 mono_array_setref (exl, i, exc);
5766 /* Types for which it don't */
5767 for (j = 0; j < mono_array_length (exceptions); ++j) {
5768 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5770 g_assert (i < length);
5771 mono_array_setref (exl, i, exc);
5778 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5779 if (!is_ok (&error)) {
5780 mono_error_set_pending_exception (&error);
5783 mono_set_pending_exception (exc);
5790 ICALL_EXPORT gboolean
5791 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5794 MonoAssemblyName aname;
5795 MonoDomain *domain = mono_object_domain (name);
5797 gboolean is_version_defined;
5798 gboolean is_token_defined;
5800 aname.public_key = NULL;
5801 val = mono_string_to_utf8_checked (assname, &error);
5802 if (mono_error_set_pending_exception (&error))
5805 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5806 g_free ((guint8*) aname.public_key);
5811 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5812 mono_error_set_pending_exception (&error);
5814 mono_assembly_name_free (&aname);
5815 g_free ((guint8*) aname.public_key);
5821 ICALL_EXPORT MonoReflectionType*
5822 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5825 MonoReflectionType *ret;
5826 MonoDomain *domain = mono_object_domain (module);
5829 g_assert (module->image);
5831 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5832 /* These images do not have a global type */
5835 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5836 if (!mono_error_ok (&error)) {
5837 mono_error_set_pending_exception (&error);
5841 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5842 if (!mono_error_ok (&error)) {
5843 mono_error_set_pending_exception (&error);
5851 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5853 /*if (module->image)
5854 mono_image_close (module->image);*/
5857 ICALL_EXPORT MonoString*
5858 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5860 MonoDomain *domain = mono_object_domain (module);
5862 g_assert (module->image);
5863 return mono_string_new (domain, module->image->guid);
5866 ICALL_EXPORT gpointer
5867 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5870 if (module->image && module->image->is_module_handle)
5871 return module->image->raw_data;
5874 return (gpointer) (-1);
5878 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5880 if (image_is_dynamic (image)) {
5881 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5882 *pe_kind = dyn->pe_kind;
5883 *machine = dyn->machine;
5886 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5887 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5892 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5894 return (image->md_version_major << 16) | (image->md_version_minor);
5897 ICALL_EXPORT MonoArray*
5898 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5901 MonoArray *exceptions;
5904 if (!module->image) {
5905 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
5906 mono_error_set_pending_exception (&error);
5911 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5912 if (mono_error_set_pending_exception (&error))
5915 for (i = 0; i < mono_array_length (exceptions); ++i) {
5916 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5918 mono_set_pending_exception (ex);
5927 mono_memberref_is_method (MonoImage *image, guint32 token)
5929 if (!image_is_dynamic (image)) {
5930 guint32 cols [MONO_MEMBERREF_SIZE];
5932 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5933 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5934 mono_metadata_decode_blob_size (sig, &sig);
5935 return (*sig != 0x6);
5938 MonoClass *handle_class;
5940 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5941 mono_error_cleanup (&error); /* just probing, ignore error */
5945 return mono_defaults.methodhandle_class == handle_class;
5950 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5953 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5954 mono_array_addr (type_args, MonoType*, 0));
5956 context->class_inst = NULL;
5958 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5959 mono_array_addr (method_args, MonoType*, 0));
5961 context->method_inst = NULL;
5964 ICALL_EXPORT MonoType*
5965 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5968 int table = mono_metadata_token_table (token);
5969 int index = mono_metadata_token_index (token);
5970 MonoGenericContext context;
5973 *resolve_error = ResolveTokenError_Other;
5975 /* Validate token */
5976 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5977 (table != MONO_TABLE_TYPESPEC)) {
5978 *resolve_error = ResolveTokenError_BadTable;
5982 if (image_is_dynamic (image)) {
5983 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5984 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5985 mono_error_cleanup (&error);
5986 return klass ? &klass->byval_arg : NULL;
5989 init_generic_context_from_args (&context, type_args, method_args);
5990 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5991 mono_error_cleanup (&error);
5992 return klass ? &klass->byval_arg : NULL;
5995 if ((index <= 0) || (index > image->tables [table].rows)) {
5996 *resolve_error = ResolveTokenError_OutOfRange;
6000 init_generic_context_from_args (&context, type_args, method_args);
6001 klass = mono_class_get_checked (image, token, &error);
6003 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
6004 if (!mono_error_ok (&error)) {
6005 mono_error_set_pending_exception (&error);
6010 return &klass->byval_arg;
6015 ICALL_EXPORT MonoMethod*
6016 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6019 int table = mono_metadata_token_table (token);
6020 int index = mono_metadata_token_index (token);
6021 MonoGenericContext context;
6024 *resolve_error = ResolveTokenError_Other;
6026 /* Validate token */
6027 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
6028 (table != MONO_TABLE_MEMBERREF)) {
6029 *resolve_error = ResolveTokenError_BadTable;
6033 if (image_is_dynamic (image)) {
6034 if (table == MONO_TABLE_METHOD) {
6035 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6036 mono_error_cleanup (&error);
6040 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
6041 *resolve_error = ResolveTokenError_BadTable;
6045 init_generic_context_from_args (&context, type_args, method_args);
6046 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6047 mono_error_cleanup (&error);
6051 if ((index <= 0) || (index > image->tables [table].rows)) {
6052 *resolve_error = ResolveTokenError_OutOfRange;
6055 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6056 *resolve_error = ResolveTokenError_BadTable;
6060 init_generic_context_from_args (&context, type_args, method_args);
6061 method = mono_get_method_checked (image, token, NULL, &context, &error);
6062 mono_error_set_pending_exception (&error);
6067 ICALL_EXPORT MonoString*
6068 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6071 int index = mono_metadata_token_index (token);
6073 *resolve_error = ResolveTokenError_Other;
6075 /* Validate token */
6076 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6077 *resolve_error = ResolveTokenError_BadTable;
6081 if (image_is_dynamic (image)) {
6082 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6083 mono_error_cleanup (&error);
6087 if ((index <= 0) || (index >= image->heap_us.size)) {
6088 *resolve_error = ResolveTokenError_OutOfRange;
6092 /* FIXME: What to do if the index points into the middle of a string ? */
6094 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
6095 mono_error_set_pending_exception (&error);
6099 ICALL_EXPORT MonoClassField*
6100 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6104 int table = mono_metadata_token_table (token);
6105 int index = mono_metadata_token_index (token);
6106 MonoGenericContext context;
6107 MonoClassField *field;
6109 *resolve_error = ResolveTokenError_Other;
6111 /* Validate token */
6112 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6113 *resolve_error = ResolveTokenError_BadTable;
6117 if (image_is_dynamic (image)) {
6118 if (table == MONO_TABLE_FIELD) {
6119 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6120 mono_error_cleanup (&error);
6124 if (mono_memberref_is_method (image, token)) {
6125 *resolve_error = ResolveTokenError_BadTable;
6129 init_generic_context_from_args (&context, type_args, method_args);
6130 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6131 mono_error_cleanup (&error);
6135 if ((index <= 0) || (index > image->tables [table].rows)) {
6136 *resolve_error = ResolveTokenError_OutOfRange;
6139 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6140 *resolve_error = ResolveTokenError_BadTable;
6144 init_generic_context_from_args (&context, type_args, method_args);
6145 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6146 mono_error_set_pending_exception (&error);
6152 ICALL_EXPORT MonoObject*
6153 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6157 int table = mono_metadata_token_table (token);
6159 *error = ResolveTokenError_Other;
6162 case MONO_TABLE_TYPEDEF:
6163 case MONO_TABLE_TYPEREF:
6164 case MONO_TABLE_TYPESPEC: {
6165 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6167 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6168 mono_error_set_pending_exception (&merror);
6175 case MONO_TABLE_METHOD:
6176 case MONO_TABLE_METHODSPEC: {
6177 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6179 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6180 mono_error_set_pending_exception (&merror);
6186 case MONO_TABLE_FIELD: {
6187 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6189 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6190 mono_error_set_pending_exception (&merror);
6196 case MONO_TABLE_MEMBERREF:
6197 if (mono_memberref_is_method (image, token)) {
6198 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6200 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6201 mono_error_set_pending_exception (&merror);
6208 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6210 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6211 mono_error_set_pending_exception (&merror);
6220 *error = ResolveTokenError_BadTable;
6226 ICALL_EXPORT MonoArray*
6227 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6230 int table = mono_metadata_token_table (token);
6231 int idx = mono_metadata_token_index (token);
6232 MonoTableInfo *tables = image->tables;
6237 *resolve_error = ResolveTokenError_OutOfRange;
6239 /* FIXME: Support other tables ? */
6240 if (table != MONO_TABLE_STANDALONESIG)
6243 if (image_is_dynamic (image))
6246 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6249 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6251 ptr = mono_metadata_blob_heap (image, sig);
6252 len = mono_metadata_decode_blob_size (ptr, &ptr);
6254 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6255 if (mono_error_set_pending_exception (&error))
6257 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6261 ICALL_EXPORT MonoReflectionType*
6262 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6265 MonoReflectionType *ret;
6267 int isbyref = 0, rank;
6269 char *str = mono_string_to_utf8_checked (smodifiers, &error);
6270 if (mono_error_set_pending_exception (&error))
6273 klass = mono_class_from_mono_type (tb->type.type);
6275 /* logic taken from mono_reflection_parse_type(): keep in sync */
6279 if (isbyref) { /* only one level allowed by the spec */
6288 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6289 mono_error_set_pending_exception (&error);
6293 klass = mono_ptr_class_get (&klass->byval_arg);
6294 mono_class_init (klass);
6305 else if (*p != '*') { /* '*' means unknown lower bound */
6316 klass = mono_array_class_get (klass, rank);
6317 mono_class_init (klass);
6326 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6327 mono_error_set_pending_exception (&error);
6332 ICALL_EXPORT MonoBoolean
6333 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6339 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6345 check_for_invalid_type (MonoClass *klass, MonoError *error)
6350 mono_error_init (error);
6352 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6355 name = mono_type_get_full_name (klass);
6356 str = mono_string_new (mono_domain_get (), name);
6358 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6361 ICALL_EXPORT MonoReflectionType *
6362 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6365 MonoReflectionType *ret;
6366 MonoClass *klass, *aklass;
6368 klass = mono_class_from_mono_type (type->type);
6369 check_for_invalid_type (klass, &error);
6370 mono_error_set_pending_exception (&error);
6372 if (rank == 0) //single dimentional array
6373 aklass = mono_array_class_get (klass, 1);
6375 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6377 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6378 mono_error_set_pending_exception (&error);
6383 ICALL_EXPORT MonoReflectionType *
6384 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6387 MonoReflectionType *ret;
6390 klass = mono_class_from_mono_type (type->type);
6391 mono_class_init_checked (klass, &error);
6392 if (mono_error_set_pending_exception (&error))
6395 check_for_invalid_type (klass, &error);
6396 if (mono_error_set_pending_exception (&error))
6399 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6400 mono_error_set_pending_exception (&error);
6405 ICALL_EXPORT MonoReflectionType *
6406 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6409 MonoReflectionType *ret;
6410 MonoClass *klass, *pklass;
6412 klass = mono_class_from_mono_type (type->type);
6413 mono_class_init_checked (klass, &error);
6414 if (mono_error_set_pending_exception (&error))
6416 check_for_invalid_type (klass, &error);
6417 if (mono_error_set_pending_exception (&error))
6420 pklass = mono_ptr_class_get (type->type);
6422 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6423 mono_error_set_pending_exception (&error);
6428 ICALL_EXPORT MonoObject *
6429 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6430 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6433 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6434 MonoObject *delegate;
6436 MonoMethod *method = info->method;
6438 mono_class_init_checked (delegate_class, &error);
6439 if (mono_error_set_pending_exception (&error))
6442 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6443 /* FIXME improve this exception message */
6444 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6446 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6447 mono_error_set_pending_exception (&error);
6451 if (mono_security_core_clr_enabled ()) {
6452 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6453 if (throwOnBindFailure)
6454 mono_error_set_pending_exception (&error);
6456 mono_error_cleanup (&error);
6461 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6462 if (mono_error_set_pending_exception (&error))
6465 if (method_is_dynamic (method)) {
6466 /* Creating a trampoline would leak memory */
6467 func = mono_compile_method_checked (method, &error);
6468 if (mono_error_set_pending_exception (&error))
6471 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6472 method = mono_object_get_virtual_method (target, method);
6473 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6474 if (mono_error_set_pending_exception (&error))
6476 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6479 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6480 if (mono_error_set_pending_exception (&error))
6485 ICALL_EXPORT MonoMulticastDelegate *
6486 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6489 MonoMulticastDelegate *ret;
6491 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6493 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6494 if (mono_error_set_pending_exception (&error))
6497 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6502 ICALL_EXPORT MonoReflectionMethod*
6503 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6505 MonoReflectionMethod *ret = NULL;
6507 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6508 mono_error_set_pending_exception (&error);
6514 static inline gint32
6515 mono_array_get_byte_length (MonoArray *array)
6521 klass = array->obj.vtable->klass;
6523 if (array->bounds == NULL)
6524 length = array->max_length;
6527 for (i = 0; i < klass->rank; ++ i)
6528 length *= array->bounds [i].length;
6531 switch (klass->element_class->byval_arg.type) {
6534 case MONO_TYPE_BOOLEAN:
6538 case MONO_TYPE_CHAR:
6546 return length * sizeof (gpointer);
6557 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6559 return mono_array_get_byte_length (array);
6563 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6565 return mono_array_get (array, gint8, idx);
6569 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6571 mono_array_set (array, gint8, idx, value);
6574 ICALL_EXPORT MonoBoolean
6575 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6577 guint8 *src_buf, *dest_buf;
6580 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6584 g_assert (count >= 0);
6586 /* This is called directly from the class libraries without going through the managed wrapper */
6587 MONO_CHECK_ARG_NULL (src, FALSE);
6588 MONO_CHECK_ARG_NULL (dest, FALSE);
6590 /* watch out for integer overflow */
6591 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6594 src_buf = (guint8 *)src->vector + src_offset;
6595 dest_buf = (guint8 *)dest->vector + dest_offset;
6598 memcpy (dest_buf, src_buf, count);
6600 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6605 #ifndef DISABLE_REMOTING
6606 ICALL_EXPORT MonoObject *
6607 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6610 MonoDomain *domain = mono_object_domain (this_obj);
6612 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6613 MonoTransparentProxy *tp;
6617 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6618 if (mono_error_set_pending_exception (&error))
6621 tp = (MonoTransparentProxy*) res;
6623 MONO_OBJECT_SETREF (tp, rp, rp);
6624 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6625 klass = mono_class_from_mono_type (type);
6627 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6628 mono_class_setup_vtable (klass);
6629 if (mono_class_has_failure (klass)) {
6630 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6634 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6635 if (mono_error_set_pending_exception (&error))
6637 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6638 if (mono_error_set_pending_exception (&error))
6641 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6642 if (mono_error_set_pending_exception (&error))
6647 ICALL_EXPORT MonoReflectionType *
6648 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6651 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6652 mono_error_set_pending_exception (&error);
6658 /* System.Environment */
6661 ves_icall_System_Environment_get_UserName (void)
6663 /* using glib is more portable */
6664 return mono_string_new (mono_domain_get (), g_get_user_name ());
6668 ICALL_EXPORT MonoString *
6669 ves_icall_System_Environment_get_MachineName (void)
6671 #if defined (HOST_WIN32)
6676 len = MAX_COMPUTERNAME_LENGTH + 1;
6677 buf = g_new (gunichar2, len);
6680 if (GetComputerName (buf, (PDWORD) &len)) {
6682 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6683 mono_error_set_pending_exception (&error);
6688 #elif !defined(DISABLE_SOCKETS)
6692 #if defined _SC_HOST_NAME_MAX
6693 n = sysconf (_SC_HOST_NAME_MAX);
6697 buf = g_malloc (n+1);
6699 if (gethostname (buf, n) == 0){
6701 result = mono_string_new (mono_domain_get (), buf);
6708 return mono_string_new (mono_domain_get (), "mono");
6713 ves_icall_System_Environment_get_Platform (void)
6715 #if defined (TARGET_WIN32)
6718 #elif defined(__MACH__)
6721 // Notice that the value is hidden from user code, and only exposed
6722 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6723 // define and making assumptions based on Unix/128/4 values before there
6724 // was a MacOS define. Lots of code would assume that not-Unix meant
6725 // Windows, but in this case, it would be OSX.
6734 ICALL_EXPORT MonoString *
6735 ves_icall_System_Environment_get_NewLine (void)
6737 #if defined (HOST_WIN32)
6738 return mono_string_new (mono_domain_get (), "\r\n");
6740 return mono_string_new (mono_domain_get (), "\n");
6744 ICALL_EXPORT MonoBoolean
6745 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6747 #if SIZEOF_VOID_P == 8
6751 gboolean isWow64Process = FALSE;
6752 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6753 return (MonoBoolean)isWow64Process;
6755 #elif defined(HAVE_SYS_UTSNAME_H)
6756 struct utsname name;
6758 if (uname (&name) >= 0) {
6759 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6766 ICALL_EXPORT MonoString *
6767 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6776 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6777 if (mono_error_set_pending_exception (&error))
6779 value = g_getenv (utf8_name);
6786 return mono_string_new (mono_domain_get (), value);
6790 * There is no standard way to get at environ.
6793 #ifndef __MINGW32_VERSION
6794 #if defined(__APPLE__)
6795 #if defined (TARGET_OSX)
6796 /* Apple defines this in crt_externs.h but doesn't provide that header for
6797 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6798 * in fact exist on all implementations (so far)
6800 gchar ***_NSGetEnviron(void);
6801 #define environ (*_NSGetEnviron())
6803 static char *mono_environ[1] = { NULL };
6804 #define environ mono_environ
6805 #endif /* defined (TARGET_OSX) */
6813 ICALL_EXPORT MonoArray *
6814 ves_icall_System_Environment_GetCoomandLineArgs (void)
6817 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6818 mono_error_set_pending_exception (&error);
6822 ICALL_EXPORT MonoArray *
6823 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6835 env_strings = GetEnvironmentStrings();
6838 env_string = env_strings;
6839 while (*env_string != '\0') {
6840 /* weird case that MS seems to skip */
6841 if (*env_string != '=')
6843 while (*env_string != '\0')
6849 domain = mono_domain_get ();
6850 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6851 if (mono_error_set_pending_exception (&error))
6856 env_string = env_strings;
6857 while (*env_string != '\0') {
6858 /* weird case that MS seems to skip */
6859 if (*env_string != '=') {
6860 equal_str = wcschr(env_string, '=');
6861 g_assert(equal_str);
6863 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6864 if (mono_error_set_pending_exception (&error))
6867 mono_array_setref (names, n, str);
6870 while (*env_string != '\0')
6875 FreeEnvironmentStrings (env_strings);
6889 for (e = environ; *e != 0; ++ e)
6892 domain = mono_domain_get ();
6893 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6894 if (mono_error_set_pending_exception (&error))
6898 for (e = environ; *e != 0; ++ e) {
6899 parts = g_strsplit (*e, "=", 2);
6901 str = mono_string_new (domain, *parts);
6902 mono_array_setref (names, n, str);
6915 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6918 gunichar2 *utf16_name, *utf16_value;
6920 gchar *utf8_name, *utf8_value;
6925 utf16_name = mono_string_to_utf16 (name);
6926 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6927 SetEnvironmentVariable (utf16_name, NULL);
6928 g_free (utf16_name);
6932 utf16_value = mono_string_to_utf16 (value);
6934 SetEnvironmentVariable (utf16_name, utf16_value);
6936 g_free (utf16_name);
6937 g_free (utf16_value);
6939 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6940 if (mono_error_set_pending_exception (&error))
6943 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6944 g_unsetenv (utf8_name);
6949 utf8_value = mono_string_to_utf8_checked (value, &error);
6950 if (!mono_error_ok (&error)) {
6952 mono_error_set_pending_exception (&error);
6955 g_setenv (utf8_name, utf8_value, TRUE);
6958 g_free (utf8_value);
6963 ves_icall_System_Environment_Exit (int result)
6965 mono_environment_exitcode_set (result);
6967 /* FIXME: There are some cleanup hangs that should be worked out, but
6968 * if the program is going to exit, everything will be cleaned up when
6969 * NaCl exits anyway.
6971 #ifndef __native_client__
6972 if (!mono_runtime_try_shutdown ())
6973 mono_thread_exit ();
6975 /* Suspend all managed threads since the runtime is going away */
6976 mono_thread_suspend_all_other_threads ();
6978 mono_runtime_quit ();
6981 /* we may need to do some cleanup here... */
6985 ICALL_EXPORT MonoString*
6986 ves_icall_System_Environment_GetGacPath (void)
6988 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6991 ICALL_EXPORT MonoString*
6992 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6994 #if defined (HOST_WIN32)
6995 #ifndef CSIDL_FLAG_CREATE
6996 #define CSIDL_FLAG_CREATE 0x8000
6999 WCHAR path [MAX_PATH];
7000 /* Create directory if no existing */
7001 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
7006 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
7007 mono_error_set_pending_exception (&error);
7011 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7013 return mono_string_new (mono_domain_get (), "");
7016 ICALL_EXPORT MonoArray *
7017 ves_icall_System_Environment_GetLogicalDrives (void)
7020 gunichar2 buf [256], *ptr, *dname;
7022 guint initial_size = 127, size = 128;
7025 MonoString *drivestr;
7026 MonoDomain *domain = mono_domain_get ();
7032 while (size > initial_size) {
7033 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
7034 if (size > initial_size) {
7037 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7038 initial_size = size;
7052 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7053 if (mono_error_set_pending_exception (&error))
7060 while (*u16) { u16++; len ++; }
7061 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7062 if (mono_error_set_pending_exception (&error))
7065 mono_array_setref (result, ndrives++, drivestr);
7076 ICALL_EXPORT MonoString *
7077 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7080 gunichar2 volume_name [MAX_PATH + 1];
7082 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7084 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
7085 mono_error_set_pending_exception (&error);
7089 ICALL_EXPORT MonoString *
7090 ves_icall_System_Environment_InternalGetHome (void)
7092 return mono_string_new (mono_domain_get (), g_get_home_dir ());
7095 static const char *encodings [] = {
7097 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7098 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7099 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7101 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7102 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7103 "x_unicode_2_0_utf_7",
7105 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7106 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7108 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7111 "unicodefffe", "utf_16be",
7118 * Returns the internal codepage, if the value of "int_code_page" is
7119 * 1 at entry, and we can not compute a suitable code page number,
7120 * returns the code page as a string
7122 ICALL_EXPORT MonoString*
7123 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
7128 char *codepage = NULL;
7130 int want_name = *int_code_page;
7133 *int_code_page = -1;
7135 g_get_charset (&cset);
7136 c = codepage = strdup (cset);
7137 for (c = codepage; *c; c++){
7138 if (isascii (*c) && isalpha (*c))
7143 /* g_print ("charset: %s\n", cset); */
7145 /* handle some common aliases */
7148 for (i = 0; p != 0; ){
7151 p = encodings [++i];
7154 if (strcmp (p, codepage) == 0){
7155 *int_code_page = code;
7158 p = encodings [++i];
7161 if (strstr (codepage, "utf_8") != NULL)
7162 *int_code_page |= 0x10000000;
7165 if (want_name && *int_code_page == -1)
7166 return mono_string_new (mono_domain_get (), cset);
7171 ICALL_EXPORT MonoBoolean
7172 ves_icall_System_Environment_get_HasShutdownStarted (void)
7174 if (mono_runtime_is_shutting_down ())
7177 if (mono_domain_is_unloading (mono_domain_get ()))
7184 ves_icall_System_Environment_BroadcastSettingChange (void)
7187 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7193 ves_icall_System_Environment_get_TickCount (void)
7195 /* this will overflow after ~24 days */
7196 return (gint32) (mono_msec_boottime () & 0xffffffff);
7200 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7205 #ifndef DISABLE_REMOTING
7206 ICALL_EXPORT MonoBoolean
7207 ves_icall_IsTransparentProxy (MonoObject *proxy)
7212 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7218 ICALL_EXPORT MonoReflectionMethod *
7219 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7220 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7222 MonoReflectionMethod *ret = NULL;
7227 MonoMethod **vtable;
7228 MonoMethod *res = NULL;
7230 MONO_CHECK_ARG_NULL (rtype, NULL);
7231 MONO_CHECK_ARG_NULL (rmethod, NULL);
7233 method = rmethod->method;
7234 klass = mono_class_from_mono_type (rtype->type);
7235 mono_class_init_checked (klass, &error);
7236 if (mono_error_set_pending_exception (&error))
7239 if (MONO_CLASS_IS_INTERFACE (klass))
7242 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7245 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7246 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7252 mono_class_setup_vtable (klass);
7253 vtable = klass->vtable;
7255 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7256 gboolean variance_used = FALSE;
7257 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7258 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7260 res = vtable [offs + method->slot];
7262 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7265 if (method->slot != -1)
7266 res = vtable [method->slot];
7272 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7273 mono_error_set_pending_exception (&error);
7278 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7284 klass = mono_class_from_mono_type (type->type);
7285 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7286 if (!is_ok (&error)) {
7287 mono_error_set_pending_exception (&error);
7291 mono_vtable_set_is_remote (vtable, enable);
7294 #else /* DISABLE_REMOTING */
7297 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7299 g_assert_not_reached ();
7304 ICALL_EXPORT MonoObject *
7305 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7312 domain = mono_object_domain (type);
7313 klass = mono_class_from_mono_type (type->type);
7314 mono_class_init_checked (klass, &error);
7315 if (mono_error_set_pending_exception (&error))
7318 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7319 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7323 if (klass->rank >= 1) {
7324 g_assert (klass->rank == 1);
7325 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7326 mono_error_set_pending_exception (&error);
7329 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7330 if (!is_ok (&error)) {
7331 mono_error_set_pending_exception (&error);
7334 /* Bypass remoting object creation check */
7335 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7336 mono_error_set_pending_exception (&error);
7342 ICALL_EXPORT MonoString *
7343 ves_icall_System_IO_get_temp_path (void)
7345 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7348 #ifndef PLATFORM_NO_DRIVEINFO
7349 ICALL_EXPORT MonoBoolean
7350 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7351 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7355 ULARGE_INTEGER wapi_free_bytes_avail;
7356 ULARGE_INTEGER wapi_total_number_of_bytes;
7357 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7359 *error = ERROR_SUCCESS;
7360 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7361 &wapi_total_number_of_free_bytes);
7364 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7365 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7366 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7368 *free_bytes_avail = 0;
7369 *total_number_of_bytes = 0;
7370 *total_number_of_free_bytes = 0;
7371 *error = GetLastError ();
7377 ICALL_EXPORT guint32
7378 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7380 return GetDriveType (mono_string_chars (root_path_name));
7384 ICALL_EXPORT gpointer
7385 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7388 gpointer result = mono_compile_method_checked (method, &error);
7389 mono_error_set_pending_exception (&error);
7393 ICALL_EXPORT MonoString *
7394 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7399 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7401 #if defined (HOST_WIN32)
7402 /* Avoid mixing '/' and '\\' */
7405 for (i = strlen (path) - 1; i >= 0; i--)
7406 if (path [i] == '/')
7410 mcpath = mono_string_new (mono_domain_get (), path);
7416 /* this is an icall */
7418 get_bundled_app_config (void)
7421 const gchar *app_config;
7424 gchar *config_file_name, *config_file_path;
7425 gsize len, config_file_path_length, config_ext_length;
7428 domain = mono_domain_get ();
7429 file = domain->setup->configuration_file;
7430 if (!file || file->length == 0)
7433 // Retrieve config file and remove the extension
7434 config_file_name = mono_string_to_utf8_checked (file, &error);
7435 if (mono_error_set_pending_exception (&error))
7437 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7438 if (!config_file_path)
7439 config_file_path = config_file_name;
7441 config_file_path_length = strlen (config_file_path);
7442 config_ext_length = strlen (".config");
7443 if (config_file_path_length <= config_ext_length)
7446 len = config_file_path_length - config_ext_length;
7447 module = (gchar *)g_malloc0 (len + 1);
7448 memcpy (module, config_file_path, len);
7449 // Get the config file from the module name
7450 app_config = mono_config_string_for_assembly_file (module);
7453 if (config_file_name != config_file_path)
7454 g_free (config_file_name);
7455 g_free (config_file_path);
7460 return mono_string_new (mono_domain_get (), app_config);
7464 get_bundled_machine_config (void)
7466 const gchar *machine_config;
7468 machine_config = mono_get_machine_config ();
7470 if (!machine_config)
7473 return mono_string_new (mono_domain_get (), machine_config);
7476 ICALL_EXPORT MonoString *
7477 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7482 path = g_path_get_dirname (mono_get_config_dir ());
7484 #if defined (HOST_WIN32)
7485 /* Avoid mixing '/' and '\\' */
7488 for (i = strlen (path) - 1; i >= 0; i--)
7489 if (path [i] == '/')
7493 ipath = mono_string_new (mono_domain_get (), path);
7499 ICALL_EXPORT gboolean
7500 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7502 MonoPEResourceDataEntry *entry;
7505 if (!assembly || !result || !size)
7510 image = assembly->assembly->image;
7511 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7515 *result = mono_image_rva_map (image, entry->rde_data_offset);
7520 *size = entry->rde_size;
7525 ICALL_EXPORT MonoBoolean
7526 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7528 return mono_is_debugger_attached ();
7531 ICALL_EXPORT MonoBoolean
7532 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7534 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7535 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7541 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7543 if (mono_get_runtime_callbacks ()->debug_log)
7544 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7548 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7550 #if defined (HOST_WIN32)
7551 OutputDebugString (mono_string_chars (message));
7553 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7557 /* Only used for value types */
7558 ICALL_EXPORT MonoObject *
7559 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7566 domain = mono_object_domain (type);
7567 klass = mono_class_from_mono_type (type->type);
7568 mono_class_init_checked (klass, &error);
7569 if (mono_error_set_pending_exception (&error))
7572 if (mono_class_is_nullable (klass))
7573 /* No arguments -> null */
7576 result = mono_object_new_checked (domain, klass, &error);
7577 mono_error_set_pending_exception (&error);
7581 ICALL_EXPORT MonoReflectionMethod *
7582 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7584 MonoReflectionMethod *ret = NULL;
7587 MonoClass *klass, *parent;
7588 MonoGenericContext *generic_inst = NULL;
7589 MonoMethod *method = m->method;
7590 MonoMethod *result = NULL;
7593 if (method->klass == NULL)
7596 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7597 MONO_CLASS_IS_INTERFACE (method->klass) ||
7598 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7601 slot = mono_method_get_vtable_slot (method);
7605 klass = method->klass;
7606 if (klass->generic_class) {
7607 generic_inst = mono_class_get_context (klass);
7608 klass = klass->generic_class->container_class;
7612 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7613 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7614 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7615 or klass is the generic container class and generic_inst is the instantiation.
7617 when we go to the parent, if the parent is an open constructed type, we need to
7618 replace the type parameters by the definitions from the generic_inst, and then take it
7619 apart again into the klass and the generic_inst.
7621 For cases like this:
7622 class C<T> : B<T, int> {
7623 public override void Foo () { ... }
7625 class B<U,V> : A<HashMap<U,V>> {
7626 public override void Foo () { ... }
7629 public virtual void Foo () { ... }
7632 if at each iteration the parent isn't open, we can skip inflating it. if at some
7633 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7636 MonoGenericContext *parent_inst = NULL;
7637 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7638 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7639 if (!mono_error_ok (&error)) {
7640 mono_error_set_pending_exception (&error);
7644 if (parent->generic_class) {
7645 parent_inst = mono_class_get_context (parent);
7646 parent = parent->generic_class->container_class;
7649 mono_class_setup_vtable (parent);
7650 if (parent->vtable_size <= slot)
7653 generic_inst = parent_inst;
7656 klass = klass->parent;
7659 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7660 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7661 if (!mono_error_ok (&error)) {
7662 mono_error_set_pending_exception (&error);
7666 generic_inst = NULL;
7668 if (klass->generic_class) {
7669 generic_inst = mono_class_get_context (klass);
7670 klass = klass->generic_class->container_class;
7676 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7677 if (!mono_error_ok (&error)) {
7678 mono_error_set_pending_exception (&error);
7683 if (klass == method->klass)
7686 /*This is possible if definition == FALSE.
7687 * Do it here to be really sure we don't read invalid memory.
7689 if (slot >= klass->vtable_size)
7692 mono_class_setup_vtable (klass);
7694 result = klass->vtable [slot];
7695 if (result == NULL) {
7696 /* It is an abstract method */
7697 gpointer iter = NULL;
7698 while ((result = mono_class_get_methods (klass, &iter)))
7699 if (result->slot == slot)
7706 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7707 mono_error_set_pending_exception (&error);
7711 ICALL_EXPORT MonoString*
7712 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7714 MonoMethod *method = m->method;
7716 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7721 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7723 iter->sig = *(MonoMethodSignature**)argsp;
7725 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7726 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7729 /* FIXME: it's not documented what start is exactly... */
7733 iter->args = argsp + sizeof (gpointer);
7735 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7737 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7740 ICALL_EXPORT MonoTypedRef
7741 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7743 guint32 i, arg_size;
7747 i = iter->sig->sentinelpos + iter->next_arg;
7749 g_assert (i < iter->sig->param_count);
7751 res.type = iter->sig->params [i];
7752 res.klass = mono_class_from_mono_type (res.type);
7753 arg_size = mono_type_stack_size (res.type, &align);
7754 #if defined(__arm__) || defined(__mips__)
7755 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7757 res.value = iter->args;
7758 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7759 /* Values are stored as 8 byte register sized objects, but 'value'
7760 * is dereferenced as a pointer in other routines.
7762 res.value = (char*)res.value + 4;
7764 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7765 if (arg_size <= sizeof (gpointer)) {
7767 int padding = arg_size - mono_type_size (res.type, &dummy);
7768 res.value = (guint8*)res.value + padding;
7771 iter->args = (char*)iter->args + arg_size;
7774 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7779 ICALL_EXPORT MonoTypedRef
7780 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7782 guint32 i, arg_size;
7786 i = iter->sig->sentinelpos + iter->next_arg;
7788 g_assert (i < iter->sig->param_count);
7790 while (i < iter->sig->param_count) {
7791 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7793 res.type = iter->sig->params [i];
7794 res.klass = mono_class_from_mono_type (res.type);
7795 /* FIXME: endianess issue... */
7796 arg_size = mono_type_stack_size (res.type, &align);
7797 #if defined(__arm__) || defined(__mips__)
7798 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7800 res.value = iter->args;
7801 iter->args = (char*)iter->args + arg_size;
7803 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7806 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7814 ICALL_EXPORT MonoType*
7815 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7819 i = iter->sig->sentinelpos + iter->next_arg;
7821 g_assert (i < iter->sig->param_count);
7823 return iter->sig->params [i];
7826 ICALL_EXPORT MonoObject*
7827 mono_TypedReference_ToObject (MonoTypedRef* tref)
7830 MonoObject *result = NULL;
7831 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7832 MonoObject** objp = (MonoObject **)tref->value;
7836 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7837 mono_error_set_pending_exception (&error);
7841 ICALL_EXPORT MonoTypedRef
7842 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7845 MonoReflectionField *f;
7847 MonoType *ftype = NULL;
7851 memset (&res, 0, sizeof (res));
7854 g_assert (mono_array_length (fields) > 0);
7856 klass = target->vtable->klass;
7858 for (i = 0; i < mono_array_length (fields); ++i) {
7859 f = mono_array_get (fields, MonoReflectionField*, i);
7861 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7864 if (f->field->parent != klass) {
7865 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7869 p = (guint8*)target + f->field->offset;
7871 p += f->field->offset - sizeof (MonoObject);
7872 klass = mono_class_from_mono_type (f->field->type);
7873 ftype = f->field->type;
7877 res.klass = mono_class_from_mono_type (ftype);
7884 prelink_method (MonoMethod *method, MonoError *error)
7886 const char *exc_class, *exc_arg;
7888 mono_error_init (error);
7889 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7891 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7893 mono_error_set_exception_instance (error,
7894 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7897 /* create the wrapper, too? */
7901 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7905 prelink_method (method->method, &error);
7906 mono_error_set_pending_exception (&error);
7910 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7913 MonoClass *klass = mono_class_from_mono_type (type->type);
7915 gpointer iter = NULL;
7917 mono_class_init_checked (klass, &error);
7918 if (mono_error_set_pending_exception (&error))
7921 while ((m = mono_class_get_methods (klass, &iter))) {
7922 prelink_method (m, &error);
7923 if (mono_error_set_pending_exception (&error))
7928 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7930 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7931 gint32 const **exponents,
7932 gunichar2 const **digitLowerTable,
7933 gunichar2 const **digitUpperTable,
7934 gint64 const **tenPowersList,
7935 gint32 const **decHexDigits)
7937 *mantissas = Formatter_MantissaBitsTable;
7938 *exponents = Formatter_TensExponentTable;
7939 *digitLowerTable = Formatter_DigitLowerTable;
7940 *digitUpperTable = Formatter_DigitUpperTable;
7941 *tenPowersList = Formatter_TenPowersList;
7942 *decHexDigits = Formatter_DecHexDigits;
7946 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7947 * and avoid useless allocations.
7950 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7952 MonoReflectionType *rt;
7956 mono_error_init (error);
7957 for (i = 0; i < type->num_mods; ++i) {
7958 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7963 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7964 return_val_if_nok (error, NULL);
7966 for (i = 0; i < type->num_mods; ++i) {
7967 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7968 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7969 return_val_if_nok (error, NULL);
7971 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7972 return_val_if_nok (error, NULL);
7974 mono_array_setref (res, count, rt);
7981 ICALL_EXPORT MonoArray*
7982 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7985 MonoType *type = param->ClassImpl->type;
7986 MonoClass *member_class = mono_object_class (param->MemberImpl);
7987 MonoMethod *method = NULL;
7990 MonoMethodSignature *sig;
7993 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7994 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7995 method = rmethod->method;
7996 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7997 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7998 if (!(method = prop->property->get))
7999 method = prop->property->set;
8002 char *type_name = mono_type_get_full_name (member_class);
8003 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
8004 MonoException *ex = mono_get_exception_not_supported (msg);
8007 mono_set_pending_exception (ex);
8011 image = method->klass->image;
8012 pos = param->PositionImpl;
8013 sig = mono_method_signature (method);
8017 type = sig->params [pos];
8019 res = type_array_from_modifiers (image, type, optional, &error);
8020 mono_error_set_pending_exception (&error);
8025 get_property_type (MonoProperty *prop)
8027 MonoMethodSignature *sig;
8029 sig = mono_method_signature (prop->get);
8031 } else if (prop->set) {
8032 sig = mono_method_signature (prop->set);
8033 return sig->params [sig->param_count - 1];
8038 ICALL_EXPORT MonoArray*
8039 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
8042 MonoType *type = get_property_type (property->property);
8043 MonoImage *image = property->klass->image;
8048 res = type_array_from_modifiers (image, type, optional, &error);
8049 mono_error_set_pending_exception (&error);
8054 *Construct a MonoType suited to be used to decode a constant blob object.
8056 * @type is the target type which will be constructed
8057 * @blob_type is the blob type, for example, that comes from the constant table
8058 * @real_type is the expected constructed type.
8061 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8063 type->type = blob_type;
8064 type->data.klass = NULL;
8065 if (blob_type == MONO_TYPE_CLASS)
8066 type->data.klass = mono_defaults.object_class;
8067 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8068 /* For enums, we need to use the base type */
8069 type->type = MONO_TYPE_VALUETYPE;
8070 type->data.klass = mono_class_from_mono_type (real_type);
8072 type->data.klass = mono_class_from_mono_type (real_type);
8075 ICALL_EXPORT MonoObject*
8076 property_info_get_default_value (MonoReflectionProperty *property)
8080 MonoProperty *prop = property->property;
8081 MonoType *type = get_property_type (prop);
8082 MonoDomain *domain = mono_object_domain (property);
8083 MonoTypeEnum def_type;
8084 const char *def_value;
8087 mono_class_init (prop->parent);
8089 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8090 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8094 def_value = mono_class_get_property_default_value (prop, &def_type);
8096 mono_type_from_blob_type (&blob_type, def_type, type);
8097 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8099 mono_error_set_pending_exception (&error);
8103 ICALL_EXPORT MonoBoolean
8104 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8107 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8108 MonoCustomAttrInfo *cinfo;
8111 mono_class_init_checked (attr_class, &error);
8112 if (mono_error_set_pending_exception (&error))
8115 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8116 if (!is_ok (&error)) {
8117 mono_error_set_pending_exception (&error);
8122 found = mono_custom_attrs_has_attr (cinfo, attr_class);
8124 mono_custom_attrs_free (cinfo);
8128 ICALL_EXPORT MonoArray*
8129 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8131 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8136 mono_class_init_checked (attr_class, &error);
8137 if (mono_error_set_pending_exception (&error))
8141 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8142 if (!mono_error_ok (&error)) {
8143 mono_error_set_pending_exception (&error);
8150 ICALL_EXPORT MonoArray*
8151 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8155 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8156 mono_error_set_pending_exception (&error);
8161 ICALL_EXPORT MonoString*
8162 ves_icall_Mono_Runtime_GetDisplayName (void)
8165 MonoString *display_name;
8167 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8168 display_name = mono_string_new (mono_domain_get (), info);
8170 return display_name;
8173 ICALL_EXPORT MonoString*
8174 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8177 MonoString *message;
8181 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8182 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8185 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8187 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8188 if (mono_error_set_pending_exception (&error))
8195 ICALL_EXPORT gpointer
8196 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8198 return GetCurrentProcess ();
8201 ICALL_EXPORT MonoBoolean
8202 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8204 return GetExitCodeProcess (handle, (guint32*) exitcode);
8207 ICALL_EXPORT MonoBoolean
8208 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8210 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8211 return CloseHandle (handle);
8213 return CloseProcess (handle);
8217 ICALL_EXPORT MonoBoolean
8218 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8220 return TerminateProcess (handle, exitcode);
8224 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8226 return WaitForInputIdle (handle, milliseconds);
8229 ICALL_EXPORT MonoBoolean
8230 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8232 return GetProcessWorkingSetSize (handle, min, max);
8235 ICALL_EXPORT MonoBoolean
8236 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8238 return SetProcessWorkingSetSize (handle, min, max);
8241 ICALL_EXPORT MonoBoolean
8242 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8244 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8248 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8250 return mono_process_current_pid ();
8254 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8256 return GetPriorityClass (handle);
8259 ICALL_EXPORT MonoBoolean
8260 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8262 return SetPriorityClass (handle, priorityClass);
8265 #ifndef DISABLE_ICALL_TABLES
8267 #define ICALL_TYPE(id,name,first)
8268 #define ICALL(id,name,func) Icall_ ## id,
8271 #include "metadata/icall-def.h"
8277 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8278 #define ICALL(id,name,func)
8280 #include "metadata/icall-def.h"
8286 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8287 #define ICALL(id,name,func)
8289 guint16 first_icall;
8292 static const IcallTypeDesc
8293 icall_type_descs [] = {
8294 #include "metadata/icall-def.h"
8298 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8301 #define ICALL_TYPE(id,name,first)
8304 #ifdef HAVE_ARRAY_ELEM_INIT
8305 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8306 #define MSGSTRFIELD1(line) str##line
8308 static const struct msgstrtn_t {
8309 #define ICALL(id,name,func)
8311 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8312 #include "metadata/icall-def.h"
8314 } icall_type_names_str = {
8315 #define ICALL_TYPE(id,name,first) (name),
8316 #include "metadata/icall-def.h"
8319 static const guint16 icall_type_names_idx [] = {
8320 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8321 #include "metadata/icall-def.h"
8324 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8326 static const struct msgstr_t {
8328 #define ICALL_TYPE(id,name,first)
8329 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8330 #include "metadata/icall-def.h"
8332 } icall_names_str = {
8333 #define ICALL(id,name,func) (name),
8334 #include "metadata/icall-def.h"
8337 static const guint16 icall_names_idx [] = {
8338 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8339 #include "metadata/icall-def.h"
8342 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8348 #define ICALL_TYPE(id,name,first) name,
8349 #define ICALL(id,name,func)
8350 static const char* const
8351 icall_type_names [] = {
8352 #include "metadata/icall-def.h"
8356 #define icall_type_name_get(id) (icall_type_names [(id)])
8360 #define ICALL_TYPE(id,name,first)
8361 #define ICALL(id,name,func) name,
8362 static const char* const
8364 #include "metadata/icall-def.h"
8367 #define icall_name_get(id) icall_names [(id)]
8369 #endif /* !HAVE_ARRAY_ELEM_INIT */
8373 #define ICALL_TYPE(id,name,first)
8374 #define ICALL(id,name,func) func,
8375 static const gconstpointer
8376 icall_functions [] = {
8377 #include "metadata/icall-def.h"
8381 #ifdef ENABLE_ICALL_SYMBOL_MAP
8384 #define ICALL_TYPE(id,name,first)
8385 #define ICALL(id,name,func) #func,
8386 static const gconstpointer
8387 icall_symbols [] = {
8388 #include "metadata/icall-def.h"
8393 #endif /* DISABLE_ICALL_TABLES */
8395 static mono_mutex_t icall_mutex;
8396 static GHashTable *icall_hash = NULL;
8397 static GHashTable *jit_icall_hash_name = NULL;
8398 static GHashTable *jit_icall_hash_addr = NULL;
8401 mono_icall_init (void)
8403 #ifndef DISABLE_ICALL_TABLES
8406 /* check that tables are sorted: disable in release */
8409 const char *prev_class = NULL;
8410 const char *prev_method;
8412 for (i = 0; i < Icall_type_num; ++i) {
8413 const IcallTypeDesc *desc;
8416 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8417 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8418 prev_class = icall_type_name_get (i);
8419 desc = &icall_type_descs [i];
8420 num_icalls = icall_desc_num_icalls (desc);
8421 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8422 for (j = 0; j < num_icalls; ++j) {
8423 const char *methodn = icall_name_get (desc->first_icall + j);
8424 if (prev_method && strcmp (prev_method, methodn) >= 0)
8425 g_print ("method %s should come before method %s\n", methodn, prev_method);
8426 prev_method = methodn;
8432 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8433 mono_os_mutex_init (&icall_mutex);
8437 mono_icall_lock (void)
8439 mono_locks_os_acquire (&icall_mutex, IcallLock);
8443 mono_icall_unlock (void)
8445 mono_locks_os_release (&icall_mutex, IcallLock);
8449 mono_icall_cleanup (void)
8451 g_hash_table_destroy (icall_hash);
8452 g_hash_table_destroy (jit_icall_hash_name);
8453 g_hash_table_destroy (jit_icall_hash_addr);
8454 mono_os_mutex_destroy (&icall_mutex);
8458 * mono_add_internal_call:
8459 * @name: method specification to surface to the managed world
8460 * @method: pointer to a C method to invoke when the method is called
8462 * This method surfaces the C function pointed by @method as a method
8463 * that has been surfaced in managed code with the method specified in
8464 * @name as an internal call.
8466 * Internal calls are surfaced to all app domains loaded and they are
8467 * accessibly by a type with the specified name.
8469 * You must provide a fully qualified type name, that is namespaces
8470 * and type name, followed by a colon and the method name, with an
8471 * optional signature to bind.
8473 * For example, the following are all valid declarations:
8475 * "MyApp.Services.ScriptService:Accelerate"
8476 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8478 * You use method parameters in cases where there might be more than
8479 * one surface method to managed code. That way you can register different
8480 * internal calls for different method overloads.
8482 * The internal calls are invoked with no marshalling. This means that .NET
8483 * types like System.String are exposed as `MonoString *` parameters. This is
8484 * different than the way that strings are surfaced in P/Invoke.
8486 * For more information on how the parameters are marshalled, see the
8487 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8490 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8491 * reference for more information on the format of method descriptions.
8494 mono_add_internal_call (const char *name, gconstpointer method)
8498 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8500 mono_icall_unlock ();
8503 #ifndef DISABLE_ICALL_TABLES
8505 #ifdef HAVE_ARRAY_ELEM_INIT
8507 compare_method_imap (const void *key, const void *elem)
8509 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8510 return strcmp (key, method_name);
8514 find_method_icall (const IcallTypeDesc *imap, const char *name)
8516 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);
8519 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8523 compare_class_imap (const void *key, const void *elem)
8525 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8526 return strcmp (key, class_name);
8529 static const IcallTypeDesc*
8530 find_class_icalls (const char *name)
8532 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);
8535 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8538 #else /* HAVE_ARRAY_ELEM_INIT */
8541 compare_method_imap (const void *key, const void *elem)
8543 const char** method_name = (const char**)elem;
8544 return strcmp (key, *method_name);
8548 find_method_icall (const IcallTypeDesc *imap, const char *name)
8550 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8553 return (gpointer)icall_functions [(nameslot - icall_names)];
8557 compare_class_imap (const void *key, const void *elem)
8559 const char** class_name = (const char**)elem;
8560 return strcmp (key, *class_name);
8563 static const IcallTypeDesc*
8564 find_class_icalls (const char *name)
8566 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8569 return &icall_type_descs [nameslot - icall_type_names];
8572 #endif /* HAVE_ARRAY_ELEM_INIT */
8574 #endif /* DISABLE_ICALL_TABLES */
8577 * we should probably export this as an helper (handle nested types).
8578 * Returns the number of chars written in buf.
8581 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8583 int nspacelen, cnamelen;
8584 nspacelen = strlen (klass->name_space);
8585 cnamelen = strlen (klass->name);
8586 if (nspacelen + cnamelen + 2 > bufsize)
8589 memcpy (buf, klass->name_space, nspacelen);
8590 buf [nspacelen ++] = '.';
8592 memcpy (buf + nspacelen, klass->name, cnamelen);
8593 buf [nspacelen + cnamelen] = 0;
8594 return nspacelen + cnamelen;
8597 #ifdef DISABLE_ICALL_TABLES
8599 no_icall_table (void)
8601 g_assert_not_reached ();
8606 mono_lookup_internal_call (MonoMethod *method)
8611 int typelen = 0, mlen, siglen;
8613 #ifndef DISABLE_ICALL_TABLES
8614 const IcallTypeDesc *imap = NULL;
8617 g_assert (method != NULL);
8619 if (method->is_inflated)
8620 method = ((MonoMethodInflated *) method)->declaring;
8622 if (method->klass->nested_in) {
8623 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8627 mname [pos++] = '/';
8630 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8636 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8641 #ifndef DISABLE_ICALL_TABLES
8642 imap = find_class_icalls (mname);
8645 mname [typelen] = ':';
8646 mname [typelen + 1] = ':';
8648 mlen = strlen (method->name);
8649 memcpy (mname + typelen + 2, method->name, mlen);
8650 sigstart = mname + typelen + 2 + mlen;
8653 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8654 siglen = strlen (tmpsig);
8655 if (typelen + mlen + siglen + 6 > sizeof (mname))
8658 memcpy (sigstart + 1, tmpsig, siglen);
8659 sigstart [siglen + 1] = ')';
8660 sigstart [siglen + 2] = 0;
8665 res = g_hash_table_lookup (icall_hash, mname);
8667 mono_icall_unlock ();;
8670 /* try without signature */
8672 res = g_hash_table_lookup (icall_hash, mname);
8674 mono_icall_unlock ();
8678 #ifdef DISABLE_ICALL_TABLES
8679 mono_icall_unlock ();
8680 /* Fail only when the result is actually used */
8681 /* mono_marshal_get_native_wrapper () depends on this */
8682 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8683 return ves_icall_System_String_ctor_RedirectToCreateString;
8685 return no_icall_table;
8687 /* it wasn't found in the static call tables */
8689 mono_icall_unlock ();
8692 res = find_method_icall (imap, sigstart - mlen);
8694 mono_icall_unlock ();
8697 /* try _with_ signature */
8699 res = find_method_icall (imap, sigstart - mlen);
8701 mono_icall_unlock ();
8705 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8706 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8707 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8708 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8709 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");
8710 g_print ("If you see other errors or faults after this message they are probably related\n");
8711 g_print ("and you need to fix your mono install first.\n");
8713 mono_icall_unlock ();
8719 #ifdef ENABLE_ICALL_SYMBOL_MAP
8721 func_cmp (gconstpointer key, gconstpointer p)
8723 return (gsize)key - (gsize)*(gsize*)p;
8728 * mono_lookup_icall_symbol:
8730 * Given the icall METHOD, returns its C symbol.
8733 mono_lookup_icall_symbol (MonoMethod *m)
8735 #ifdef DISABLE_ICALL_TABLES
8736 g_assert_not_reached ();
8739 #ifdef ENABLE_ICALL_SYMBOL_MAP
8743 static gconstpointer *functions_sorted;
8744 static const char**symbols_sorted;
8745 static gboolean inited;
8750 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8751 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8752 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8753 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8754 /* Bubble sort the two arrays */
8758 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8759 if (functions_sorted [i] > functions_sorted [i + 1]) {
8762 tmp = functions_sorted [i];
8763 functions_sorted [i] = functions_sorted [i + 1];
8764 functions_sorted [i + 1] = tmp;
8765 tmp = symbols_sorted [i];
8766 symbols_sorted [i] = symbols_sorted [i + 1];
8767 symbols_sorted [i + 1] = tmp;
8774 func = mono_lookup_internal_call (m);
8777 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8781 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8783 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8784 g_assert_not_reached ();
8791 type_from_typename (char *type_name)
8793 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8795 if (!strcmp (type_name, "int"))
8796 klass = mono_defaults.int_class;
8797 else if (!strcmp (type_name, "ptr"))
8798 klass = mono_defaults.int_class;
8799 else if (!strcmp (type_name, "void"))
8800 klass = mono_defaults.void_class;
8801 else if (!strcmp (type_name, "int32"))
8802 klass = mono_defaults.int32_class;
8803 else if (!strcmp (type_name, "uint32"))
8804 klass = mono_defaults.uint32_class;
8805 else if (!strcmp (type_name, "int8"))
8806 klass = mono_defaults.sbyte_class;
8807 else if (!strcmp (type_name, "uint8"))
8808 klass = mono_defaults.byte_class;
8809 else if (!strcmp (type_name, "int16"))
8810 klass = mono_defaults.int16_class;
8811 else if (!strcmp (type_name, "uint16"))
8812 klass = mono_defaults.uint16_class;
8813 else if (!strcmp (type_name, "long"))
8814 klass = mono_defaults.int64_class;
8815 else if (!strcmp (type_name, "ulong"))
8816 klass = mono_defaults.uint64_class;
8817 else if (!strcmp (type_name, "float"))
8818 klass = mono_defaults.single_class;
8819 else if (!strcmp (type_name, "double"))
8820 klass = mono_defaults.double_class;
8821 else if (!strcmp (type_name, "object"))
8822 klass = mono_defaults.object_class;
8823 else if (!strcmp (type_name, "obj"))
8824 klass = mono_defaults.object_class;
8825 else if (!strcmp (type_name, "string"))
8826 klass = mono_defaults.string_class;
8827 else if (!strcmp (type_name, "bool"))
8828 klass = mono_defaults.boolean_class;
8829 else if (!strcmp (type_name, "boolean"))
8830 klass = mono_defaults.boolean_class;
8832 g_error ("%s", type_name);
8833 g_assert_not_reached ();
8835 return &klass->byval_arg;
8839 * LOCKING: Take the corlib image lock.
8841 MonoMethodSignature*
8842 mono_create_icall_signature (const char *sigstr)
8847 MonoMethodSignature *res, *res2;
8848 MonoImage *corlib = mono_defaults.corlib;
8850 mono_image_lock (corlib);
8851 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8852 mono_image_unlock (corlib);
8857 parts = g_strsplit (sigstr, " ", 256);
8866 res = mono_metadata_signature_alloc (corlib, len - 1);
8871 * Under windows, the default pinvoke calling convention is STDCALL but
8874 res->call_convention = MONO_CALL_C;
8877 res->ret = type_from_typename (parts [0]);
8878 for (i = 1; i < len; ++i) {
8879 res->params [i - 1] = type_from_typename (parts [i]);
8884 mono_image_lock (corlib);
8885 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8887 res = res2; /*Value is allocated in the image pool*/
8889 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8890 mono_image_unlock (corlib);
8896 mono_find_jit_icall_by_name (const char *name)
8898 MonoJitICallInfo *info;
8899 g_assert (jit_icall_hash_name);
8902 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8903 mono_icall_unlock ();
8908 mono_find_jit_icall_by_addr (gconstpointer addr)
8910 MonoJitICallInfo *info;
8911 g_assert (jit_icall_hash_addr);
8914 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8915 mono_icall_unlock ();
8921 * mono_get_jit_icall_info:
8923 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8924 * caller should access it while holding the icall lock.
8927 mono_get_jit_icall_info (void)
8929 return jit_icall_hash_name;
8933 * mono_lookup_jit_icall_symbol:
8935 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8938 mono_lookup_jit_icall_symbol (const char *name)
8940 MonoJitICallInfo *info;
8941 const char *res = NULL;
8944 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8946 res = info->c_symbol;
8947 mono_icall_unlock ();
8952 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8955 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8956 mono_icall_unlock ();
8960 * 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
8961 * icalls without wrappers in some cases.
8964 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8966 MonoJitICallInfo *info;
8973 if (!jit_icall_hash_name) {
8974 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8975 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8978 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8979 g_warning ("jit icall already defined \"%s\"\n", name);
8980 g_assert_not_reached ();
8983 info = g_new0 (MonoJitICallInfo, 1);
8988 info->c_symbol = c_symbol;
8989 info->no_raise = no_raise;
8992 info->wrapper = func;
8994 info->wrapper = NULL;
8997 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8998 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
9000 mono_icall_unlock ();
9005 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
9007 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);