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 /* System.TypeCode */
1551 TYPECODE_STRING = 18
1554 ICALL_EXPORT guint32
1555 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1557 int t = type->type->type;
1559 if (type->type->byref)
1560 return TYPECODE_OBJECT;
1564 case MONO_TYPE_VOID:
1565 return TYPECODE_OBJECT;
1566 case MONO_TYPE_BOOLEAN:
1567 return TYPECODE_BOOLEAN;
1569 return TYPECODE_BYTE;
1571 return TYPECODE_SBYTE;
1573 return TYPECODE_UINT16;
1575 return TYPECODE_INT16;
1576 case MONO_TYPE_CHAR:
1577 return TYPECODE_CHAR;
1581 return TYPECODE_OBJECT;
1583 return TYPECODE_UINT32;
1585 return TYPECODE_INT32;
1587 return TYPECODE_UINT64;
1589 return TYPECODE_INT64;
1591 return TYPECODE_SINGLE;
1593 return TYPECODE_DOUBLE;
1594 case MONO_TYPE_VALUETYPE: {
1595 MonoClass *klass = type->type->data.klass;
1597 if (klass->enumtype) {
1598 t = mono_class_enum_basetype (klass)->type;
1600 } else if (mono_is_corlib_image (klass->image)) {
1601 if (strcmp (klass->name_space, "System") == 0) {
1602 if (strcmp (klass->name, "Decimal") == 0)
1603 return TYPECODE_DECIMAL;
1604 else if (strcmp (klass->name, "DateTime") == 0)
1605 return TYPECODE_DATETIME;
1608 return TYPECODE_OBJECT;
1610 case MONO_TYPE_STRING:
1611 return TYPECODE_STRING;
1612 case MONO_TYPE_SZARRAY:
1613 case MONO_TYPE_ARRAY:
1614 case MONO_TYPE_OBJECT:
1616 case MONO_TYPE_MVAR:
1617 case MONO_TYPE_TYPEDBYREF:
1618 return TYPECODE_OBJECT;
1619 case MONO_TYPE_CLASS:
1621 MonoClass *klass = type->type->data.klass;
1622 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1623 if (strcmp (klass->name, "DBNull") == 0)
1624 return TYPECODE_DBNULL;
1627 return TYPECODE_OBJECT;
1628 case MONO_TYPE_GENERICINST:
1629 return TYPECODE_OBJECT;
1631 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1637 mono_type_is_primitive (MonoType *type)
1639 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1640 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1644 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1646 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1647 return mono_class_enum_basetype (type->data.klass);
1648 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1649 return mono_class_enum_basetype (type->data.generic_class->container_class);
1653 ICALL_EXPORT guint32
1654 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1659 g_assert (type != NULL);
1661 klass = mono_class_from_mono_type (type->type);
1662 klassc = mono_class_from_mono_type (c->type);
1664 if (type->type->byref ^ c->type->byref)
1667 if (type->type->byref) {
1668 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1669 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1671 klass = mono_class_from_mono_type (t);
1672 klassc = mono_class_from_mono_type (ot);
1674 if (mono_type_is_primitive (t)) {
1675 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1676 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1677 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1678 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1679 return t->type == ot->type;
1681 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1684 if (klass->valuetype)
1685 return klass == klassc;
1686 return klass->valuetype == klassc->valuetype;
1689 return mono_class_is_assignable_from (klass, klassc);
1692 ICALL_EXPORT guint32
1693 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1696 MonoClass *klass = mono_class_from_mono_type (type->type);
1697 mono_class_init_checked (klass, &error);
1698 if (!is_ok (&error)) {
1699 mono_error_set_pending_exception (&error);
1702 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1703 mono_error_set_pending_exception (&error);
1707 ICALL_EXPORT guint32
1708 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1710 MonoClass *klass = mono_class_from_mono_type (type->type);
1711 return klass->flags;
1714 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1715 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1718 MonoClass *klass = field->field->parent;
1719 MonoMarshalType *info;
1723 if (klass->generic_container ||
1724 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1727 ftype = mono_field_get_type (field->field);
1728 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1731 info = mono_marshal_load_type_info (klass);
1733 for (i = 0; i < info->num_fields; ++i) {
1734 if (info->fields [i].field == field->field) {
1735 if (!info->fields [i].mspec)
1738 MonoReflectionMarshalAsAttribute* obj;
1739 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1740 if (!mono_error_ok (&error))
1741 mono_error_set_pending_exception (&error);
1750 ICALL_EXPORT MonoReflectionField*
1751 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1754 gboolean found = FALSE;
1761 klass = handle->parent;
1763 klass = mono_class_from_mono_type (type);
1765 /* Check that the field belongs to the class */
1766 for (k = klass; k; k = k->parent) {
1767 if (k == handle->parent) {
1774 /* The managed code will throw the exception */
1778 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1779 mono_error_set_pending_exception (&error);
1783 ICALL_EXPORT MonoArray*
1784 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1787 MonoType *type = mono_field_get_type_checked (field->field, &error);
1790 if (!mono_error_ok (&error)) {
1791 mono_error_set_pending_exception (&error);
1795 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1796 mono_error_set_pending_exception (&error);
1801 vell_icall_get_method_attributes (MonoMethod *method)
1803 return method->flags;
1807 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1810 MonoReflectionType *rt;
1811 MonoDomain *domain = mono_domain_get ();
1812 MonoMethodSignature* sig;
1814 sig = mono_method_signature_checked (method, &error);
1815 if (!mono_error_ok (&error)) {
1816 mono_error_set_pending_exception (&error);
1820 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1821 if (!mono_error_ok (&error)) {
1822 mono_error_set_pending_exception (&error);
1826 MONO_STRUCT_SETREF (info, parent, rt);
1828 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1829 if (!mono_error_ok (&error)) {
1830 mono_error_set_pending_exception (&error);
1834 MONO_STRUCT_SETREF (info, ret, rt);
1836 info->attrs = method->flags;
1837 info->implattrs = method->iflags;
1838 if (sig->call_convention == MONO_CALL_DEFAULT)
1839 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1841 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1846 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1849 ICALL_EXPORT MonoArray*
1850 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1853 MonoDomain *domain = mono_domain_get ();
1855 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1856 mono_error_set_pending_exception (&error);
1860 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1861 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1864 MonoDomain *domain = mono_domain_get ();
1865 MonoReflectionMarshalAsAttribute* res = NULL;
1866 MonoMarshalSpec **mspecs;
1869 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1870 mono_method_get_marshal_info (method, mspecs);
1873 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1874 if (!mono_error_ok (&error)) {
1875 mono_error_set_pending_exception (&error);
1880 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1882 mono_metadata_free_marshal_spec (mspecs [i]);
1889 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1891 MonoClass *parent = field->field->parent;
1892 if (!parent->size_inited)
1893 mono_class_init (parent);
1894 mono_class_setup_fields_locking (parent);
1896 return field->field->offset - sizeof (MonoObject);
1899 ICALL_EXPORT MonoReflectionType*
1900 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1903 MonoReflectionType *ret;
1906 parent = declaring? field->field->parent: field->klass;
1908 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1909 mono_error_set_pending_exception (&error);
1915 ICALL_EXPORT MonoObject *
1916 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1919 MonoClass *fklass = field->klass;
1920 MonoClassField *cf = field->field;
1921 MonoDomain *domain = mono_object_domain (field);
1923 if (fklass->image->assembly->ref_only) {
1924 mono_set_pending_exception (mono_get_exception_invalid_operation (
1925 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1929 if (mono_security_core_clr_enabled () &&
1930 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1931 mono_error_set_pending_exception (&error);
1935 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1936 mono_error_set_pending_exception (&error);
1941 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1944 MonoClassField *cf = field->field;
1948 if (field->klass->image->assembly->ref_only) {
1949 mono_set_pending_exception (mono_get_exception_invalid_operation (
1950 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1954 if (mono_security_core_clr_enabled () &&
1955 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1956 mono_error_set_pending_exception (&error);
1960 type = mono_field_get_type_checked (cf, &error);
1961 if (!mono_error_ok (&error)) {
1962 mono_error_set_pending_exception (&error);
1966 v = (gchar *) value;
1968 switch (type->type) {
1971 case MONO_TYPE_BOOLEAN:
1974 case MONO_TYPE_CHAR:
1983 case MONO_TYPE_VALUETYPE:
1986 v += sizeof (MonoObject);
1988 case MONO_TYPE_STRING:
1989 case MONO_TYPE_OBJECT:
1990 case MONO_TYPE_CLASS:
1991 case MONO_TYPE_ARRAY:
1992 case MONO_TYPE_SZARRAY:
1995 case MONO_TYPE_GENERICINST: {
1996 MonoGenericClass *gclass = type->data.generic_class;
1997 g_assert (!gclass->context.class_inst->is_open);
1999 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
2000 MonoClass *nklass = mono_class_from_mono_type (type);
2001 MonoObject *nullable;
2004 * Convert the boxed vtype into a Nullable structure.
2005 * This is complicated by the fact that Nullables have
2006 * a variable structure.
2008 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2009 if (!mono_error_ok (&error)) {
2010 mono_error_set_pending_exception (&error);
2014 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2016 v = (gchar *)mono_object_unbox (nullable);
2019 if (gclass->container_class->valuetype && (v != NULL))
2020 v += sizeof (MonoObject);
2024 g_error ("type 0x%x not handled in "
2025 "ves_icall_FieldInfo_SetValueInternal", type->type);
2030 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2031 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2032 if (!is_ok (&error)) {
2033 mono_error_set_pending_exception (&error);
2036 if (!vtable->initialized) {
2037 if (!mono_runtime_class_init_full (vtable, &error)) {
2038 mono_error_set_pending_exception (&error);
2042 mono_field_static_set_value (vtable, cf, v);
2044 mono_field_set_value (obj, cf, v);
2049 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2058 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2059 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2063 if (MONO_TYPE_IS_REFERENCE (f->type))
2064 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2066 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2069 ICALL_EXPORT MonoObject *
2070 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2072 MonoObject *o = NULL;
2073 MonoClassField *field = rfield->field;
2075 MonoDomain *domain = mono_object_domain (rfield);
2077 MonoTypeEnum def_type;
2078 const char *def_value;
2082 mono_class_init (field->parent);
2084 t = mono_field_get_type_checked (field, &error);
2085 if (!mono_error_ok (&error)) {
2086 mono_error_set_pending_exception (&error);
2090 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2091 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2095 if (image_is_dynamic (field->parent->image)) {
2096 MonoClass *klass = field->parent;
2097 int fidx = field - klass->fields;
2099 g_assert (fidx >= 0 && fidx < klass->field.count);
2100 g_assert (klass->ext);
2101 g_assert (klass->ext->field_def_values);
2102 def_type = klass->ext->field_def_values [fidx].def_type;
2103 def_value = klass->ext->field_def_values [fidx].data;
2104 if (def_type == MONO_TYPE_END) {
2105 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2109 def_value = mono_class_get_field_default_value (field, &def_type);
2110 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2112 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2117 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2121 case MONO_TYPE_BOOLEAN:
2124 case MONO_TYPE_CHAR:
2132 case MONO_TYPE_R8: {
2135 /* boxed value type */
2136 t = g_new0 (MonoType, 1);
2138 klass = mono_class_from_mono_type (t);
2140 o = mono_object_new_checked (domain, klass, &error);
2141 if (!mono_error_ok (&error)) {
2142 mono_error_set_pending_exception (&error);
2145 v = ((gchar *) o) + sizeof (MonoObject);
2146 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2147 if (mono_error_set_pending_exception (&error))
2151 case MONO_TYPE_STRING:
2152 case MONO_TYPE_CLASS:
2153 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2154 if (mono_error_set_pending_exception (&error))
2158 g_assert_not_reached ();
2164 ICALL_EXPORT MonoReflectionType*
2165 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2168 MonoReflectionType *ret;
2171 type = mono_field_get_type_checked (ref_field->field, &error);
2172 if (!mono_error_ok (&error)) {
2173 mono_error_set_pending_exception (&error);
2177 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2178 if (!mono_error_ok (&error)) {
2179 mono_error_set_pending_exception (&error);
2186 /* From MonoProperty.cs */
2188 PInfo_Attributes = 1,
2189 PInfo_GetMethod = 1 << 1,
2190 PInfo_SetMethod = 1 << 2,
2191 PInfo_ReflectedType = 1 << 3,
2192 PInfo_DeclaringType = 1 << 4,
2197 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2200 MonoReflectionType *rt;
2201 MonoReflectionMethod *rm;
2202 MonoDomain *domain = mono_object_domain (property);
2203 const MonoProperty *pproperty = property->property;
2205 if ((req_info & PInfo_ReflectedType) != 0) {
2206 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2207 if (mono_error_set_pending_exception (&error))
2210 MONO_STRUCT_SETREF (info, parent, rt);
2212 if ((req_info & PInfo_DeclaringType) != 0) {
2213 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2214 if (mono_error_set_pending_exception (&error))
2217 MONO_STRUCT_SETREF (info, declaring_type, rt);
2220 if ((req_info & PInfo_Name) != 0)
2221 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2223 if ((req_info & PInfo_Attributes) != 0)
2224 info->attrs = pproperty->attrs;
2226 if ((req_info & PInfo_GetMethod) != 0) {
2227 if (pproperty->get &&
2228 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2229 pproperty->get->klass == property->klass)) {
2230 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2231 if (mono_error_set_pending_exception (&error))
2237 MONO_STRUCT_SETREF (info, get, rm);
2239 if ((req_info & PInfo_SetMethod) != 0) {
2240 if (pproperty->set &&
2241 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2242 pproperty->set->klass == property->klass)) {
2243 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2244 if (mono_error_set_pending_exception (&error))
2250 MONO_STRUCT_SETREF (info, set, rm);
2253 * There may be other methods defined for properties, though, it seems they are not exposed
2254 * in the reflection API
2259 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2262 MonoReflectionType *rt;
2263 MonoReflectionMethod *rm;
2264 MonoDomain *domain = mono_object_domain (event);
2266 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2267 if (mono_error_set_pending_exception (&error))
2270 MONO_STRUCT_SETREF (info, reflected_type, rt);
2272 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2273 if (mono_error_set_pending_exception (&error))
2276 MONO_STRUCT_SETREF (info, declaring_type, rt);
2278 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2279 info->attrs = event->event->attrs;
2281 if (event->event->add) {
2282 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2283 if (mono_error_set_pending_exception (&error))
2289 MONO_STRUCT_SETREF (info, add_method, rm);
2291 if (event->event->remove) {
2292 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2293 if (mono_error_set_pending_exception (&error))
2299 MONO_STRUCT_SETREF (info, remove_method, rm);
2301 if (event->event->raise) {
2302 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2303 if (mono_error_set_pending_exception (&error))
2309 MONO_STRUCT_SETREF (info, raise_method, rm);
2311 #ifndef MONO_SMALL_CONFIG
2312 if (event->event->other) {
2314 while (event->event->other [n])
2316 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2317 if (mono_error_set_pending_exception (&error))
2319 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2321 for (i = 0; i < n; i++) {
2322 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2323 if (mono_error_set_pending_exception (&error))
2325 mono_array_setref (info->other_methods, i, rm);
2332 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2337 mono_class_setup_interfaces (klass, error);
2338 if (!mono_error_ok (error))
2341 for (i = 0; i < klass->interface_count; i++) {
2342 ic = klass->interfaces [i];
2343 g_hash_table_insert (ifaces, ic, ic);
2345 collect_interfaces (ic, ifaces, error);
2346 if (!mono_error_ok (error))
2352 MonoArray *iface_array;
2353 MonoGenericContext *context;
2357 } FillIfaceArrayData;
2360 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2362 MonoReflectionType *rt;
2363 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2364 MonoClass *ic = (MonoClass *)key;
2365 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2367 if (!mono_error_ok (data->error))
2370 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2371 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2372 if (!mono_error_ok (data->error))
2376 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2377 if (!mono_error_ok (data->error))
2380 mono_array_setref (data->iface_array, data->next_idx++, rt);
2383 mono_metadata_free_type (inflated);
2387 get_interfaces_hash (gconstpointer v1)
2389 MonoClass *k = (MonoClass*)v1;
2391 return k->type_token;
2394 ICALL_EXPORT MonoArray*
2395 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2398 MonoClass *klass = mono_class_from_mono_type (type->type);
2400 FillIfaceArrayData data = { 0 };
2403 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2405 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2406 data.context = mono_class_get_context (klass);
2407 klass = klass->generic_class->container_class;
2410 for (parent = klass; parent; parent = parent->parent) {
2411 mono_class_setup_interfaces (parent, &error);
2412 if (!mono_error_ok (&error))
2414 collect_interfaces (parent, iface_hash, &error);
2415 if (!mono_error_ok (&error))
2419 data.error = &error;
2420 data.domain = mono_object_domain (type);
2422 len = g_hash_table_size (iface_hash);
2424 g_hash_table_destroy (iface_hash);
2425 if (!data.domain->empty_types) {
2426 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2427 if (!is_ok (&error))
2430 return data.domain->empty_types;
2433 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2434 if (!is_ok (&error))
2436 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2437 if (!mono_error_ok (&error))
2440 g_hash_table_destroy (iface_hash);
2441 return data.iface_array;
2444 g_hash_table_destroy (iface_hash);
2445 mono_error_set_pending_exception (&error);
2450 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2452 gboolean variance_used;
2453 MonoClass *klass = mono_class_from_mono_type (type->type);
2454 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2455 MonoReflectionMethod *member;
2458 int i = 0, len, ioffset;
2462 mono_class_init_checked (klass, &error);
2463 if (mono_error_set_pending_exception (&error))
2465 mono_class_init_checked (iclass, &error);
2466 if (mono_error_set_pending_exception (&error))
2469 mono_class_setup_vtable (klass);
2471 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2475 len = mono_class_num_methods (iclass);
2476 domain = mono_object_domain (type);
2477 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2478 if (mono_error_set_pending_exception (&error))
2480 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2481 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2482 if (mono_error_set_pending_exception (&error))
2484 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2486 while ((method = mono_class_get_methods (iclass, &iter))) {
2487 member = mono_method_get_object_checked (domain, method, iclass, &error);
2488 if (mono_error_set_pending_exception (&error))
2490 mono_array_setref (*methods, i, member);
2491 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2492 if (mono_error_set_pending_exception (&error))
2494 mono_array_setref (*targets, i, member);
2501 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2504 MonoClass *klass = mono_class_from_mono_type (type->type);
2506 mono_class_init_checked (klass, &error);
2507 if (mono_error_set_pending_exception (&error))
2510 if (image_is_dynamic (klass->image)) {
2511 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2512 *packing = tb->packing_size;
2513 *size = tb->class_size;
2515 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2519 ICALL_EXPORT MonoReflectionType*
2520 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2523 MonoReflectionType *ret;
2526 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2527 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2528 mono_error_set_pending_exception (&error);
2532 klass = mono_class_from_mono_type (type->type);
2533 mono_class_init_checked (klass, &error);
2534 if (mono_error_set_pending_exception (&error))
2538 // GetElementType should only return a type for:
2539 // Array Pointer PassedByRef
2540 if (type->type->byref)
2541 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2542 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2543 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2544 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2545 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2549 mono_error_set_pending_exception (&error);
2554 ICALL_EXPORT MonoReflectionType*
2555 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2558 MonoReflectionType *ret;
2560 if (type->type->byref)
2563 MonoClass *klass = mono_class_from_mono_type (type->type);
2567 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2568 mono_error_set_pending_exception (&error);
2573 ICALL_EXPORT MonoBoolean
2574 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2576 return type->type->type == MONO_TYPE_PTR;
2579 ICALL_EXPORT MonoBoolean
2580 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2582 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)));
2585 ICALL_EXPORT MonoBoolean
2586 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2588 return type->type->byref;
2591 ICALL_EXPORT MonoBoolean
2592 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2595 MonoClass *klass = mono_class_from_mono_type (type->type);
2596 mono_class_init_checked (klass, &error);
2597 if (mono_error_set_pending_exception (&error))
2600 return mono_class_is_com_object (klass);
2603 ICALL_EXPORT guint32
2604 ves_icall_reflection_get_token (MonoObject* obj)
2607 guint32 result = mono_reflection_get_token_checked (obj, &error);
2608 mono_error_set_pending_exception (&error);
2612 ICALL_EXPORT MonoReflectionModule*
2613 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2616 MonoReflectionModule *result = NULL;
2617 MonoClass *klass = mono_class_from_mono_type (type->type);
2618 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2619 mono_error_set_pending_exception (&error);
2623 ICALL_EXPORT MonoReflectionAssembly*
2624 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2627 MonoDomain *domain = mono_domain_get ();
2628 MonoClass *klass = mono_class_from_mono_type (type->type);
2629 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2630 mono_error_set_pending_exception (&error);
2634 ICALL_EXPORT MonoReflectionType*
2635 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2638 MonoReflectionType *ret;
2639 MonoDomain *domain = mono_domain_get ();
2642 if (type->type->byref)
2644 if (type->type->type == MONO_TYPE_VAR) {
2645 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2646 klass = param ? param->owner.klass : NULL;
2647 } else if (type->type->type == MONO_TYPE_MVAR) {
2648 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2649 klass = param ? param->owner.method->klass : NULL;
2651 klass = mono_class_from_mono_type (type->type)->nested_in;
2657 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2658 mono_error_set_pending_exception (&error);
2663 ICALL_EXPORT MonoString*
2664 ves_icall_RuntimeType_get_Name (MonoReflectionType *type)
2666 MonoDomain *domain = mono_domain_get ();
2667 MonoClass *klass = mono_class_from_mono_type (type->type);
2669 if (type->type->byref) {
2670 char *n = g_strdup_printf ("%s&", klass->name);
2671 MonoString *res = mono_string_new (domain, n);
2677 return mono_string_new (domain, klass->name);
2681 ICALL_EXPORT MonoString*
2682 ves_icall_RuntimeType_get_Namespace (MonoReflectionType *type)
2684 MonoDomain *domain = mono_domain_get ();
2685 MonoClass *klass = mono_class_from_mono_type (type->type);
2687 while (klass->nested_in)
2688 klass = klass->nested_in;
2690 if (klass->name_space [0] == '\0')
2693 return mono_string_new (domain, klass->name_space);
2697 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2701 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2702 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2706 klass = mono_class_from_mono_type (type->type);
2712 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2714 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2717 ICALL_EXPORT MonoArray*
2718 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2721 MonoReflectionType *rt;
2723 MonoClass *klass, *pklass;
2724 MonoDomain *domain = mono_object_domain (type);
2727 klass = mono_class_from_mono_type (type->type);
2729 if (klass->generic_container) {
2730 MonoGenericContainer *container = klass->generic_container;
2731 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2732 if (mono_error_set_pending_exception (&error))
2734 for (i = 0; i < container->type_argc; ++i) {
2735 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2737 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2738 if (mono_error_set_pending_exception (&error))
2741 mono_array_setref (res, i, rt);
2743 } else if (klass->generic_class) {
2744 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2745 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2746 if (mono_error_set_pending_exception (&error))
2748 for (i = 0; i < inst->type_argc; ++i) {
2749 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2750 if (mono_error_set_pending_exception (&error))
2753 mono_array_setref (res, i, rt);
2761 ICALL_EXPORT gboolean
2762 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2766 if (!IS_MONOTYPE (type))
2769 if (type->type->byref)
2772 klass = mono_class_from_mono_type (type->type);
2773 return klass->generic_container != NULL;
2776 ICALL_EXPORT MonoReflectionType*
2777 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2780 MonoReflectionType *ret;
2783 if (type->type->byref)
2786 klass = mono_class_from_mono_type (type->type);
2788 if (klass->generic_container) {
2789 return type; /* check this one */
2791 if (klass->generic_class) {
2792 MonoClass *generic_class = klass->generic_class->container_class;
2795 tb = mono_class_get_ref_info (generic_class);
2797 if (generic_class->wastypebuilder && tb)
2798 return (MonoReflectionType *)tb;
2800 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2801 mono_error_set_pending_exception (&error);
2809 ICALL_EXPORT MonoReflectionType*
2810 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2813 MonoReflectionType *ret;
2815 MonoType *geninst, **types;
2818 g_assert (IS_MONOTYPE (type));
2819 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2820 if (mono_error_set_pending_exception (&error))
2823 count = mono_array_length (type_array);
2824 types = g_new0 (MonoType *, count);
2826 for (i = 0; i < count; i++) {
2827 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2828 types [i] = t->type;
2831 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2834 mono_error_set_pending_exception (&error);
2838 klass = mono_class_from_mono_type (geninst);
2840 /*we might inflate to the GTD*/
2841 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2842 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2846 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2847 mono_error_set_pending_exception (&error);
2852 ICALL_EXPORT gboolean
2853 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2857 if (!IS_MONOTYPE (type))
2860 if (type->type->byref)
2863 klass = mono_class_from_mono_type (type->type);
2864 return klass->generic_class != NULL || klass->generic_container != NULL;
2868 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2870 if (!IS_MONOTYPE (type))
2873 if (is_generic_parameter (type->type))
2874 return mono_type_get_generic_param_num (type->type);
2878 ICALL_EXPORT GenericParameterAttributes
2879 ves_icall_RuntimeType_GetGenericParameterAttributes (MonoReflectionType *type)
2881 g_assert (IS_MONOTYPE (type));
2882 g_assert (is_generic_parameter (type->type));
2883 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2886 ICALL_EXPORT MonoArray *
2887 ves_icall_RuntimeType_GetGenericParameterConstraints (MonoReflectionType *type)
2890 MonoReflectionType *rt;
2891 MonoGenericParamInfo *param_info;
2897 g_assert (IS_MONOTYPE (type));
2899 domain = mono_object_domain (type);
2900 param_info = mono_generic_param_info (type->type->data.generic_param);
2901 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2904 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, &error);
2905 if (mono_error_set_pending_exception (&error))
2907 for (i = 0; i < count; i++) {
2908 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2909 if (mono_error_set_pending_exception (&error))
2912 mono_array_setref (res, i, rt);
2919 ICALL_EXPORT MonoBoolean
2920 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2922 return is_generic_parameter (type->type);
2925 ICALL_EXPORT MonoBoolean
2926 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2928 return is_generic_parameter (tb->type.type);
2932 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2933 MonoReflectionType *t)
2935 enumtype->type = t->type;
2938 ICALL_EXPORT MonoReflectionMethod*
2939 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2940 MonoReflectionMethod* generic)
2947 MonoReflectionMethod *ret = NULL;
2949 domain = ((MonoObject *)type)->vtable->domain;
2951 klass = mono_class_from_mono_type (type->type);
2952 mono_class_init_checked (klass, &error);
2953 if (mono_error_set_pending_exception (&error))
2957 while ((method = mono_class_get_methods (klass, &iter))) {
2958 if (method->token == generic->method->token) {
2959 ret = mono_method_get_object_checked (domain, method, klass, &error);
2960 if (mono_error_set_pending_exception (&error))
2968 ICALL_EXPORT MonoReflectionMethod *
2969 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
2972 MonoType *type = ref_type->type;
2974 MonoReflectionMethod *ret = NULL;
2976 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2977 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2980 if (type->type == MONO_TYPE_VAR)
2983 method = mono_type_get_generic_param_owner (type)->owner.method;
2986 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2987 if (!mono_error_ok (&error))
2988 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2992 ICALL_EXPORT MonoBoolean
2993 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2995 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2999 ICALL_EXPORT MonoBoolean
3000 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
3002 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3007 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
3009 MonoDomain *domain = mono_domain_get ();
3010 MonoImage *image = method->method->klass->image;
3011 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
3012 MonoTableInfo *tables = image->tables;
3013 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
3014 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
3015 guint32 im_cols [MONO_IMPLMAP_SIZE];
3016 guint32 scope_token;
3017 const char *import = NULL;
3018 const char *scope = NULL;
3020 if (image_is_dynamic (image)) {
3021 MonoReflectionMethodAux *method_aux =
3022 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
3024 import = method_aux->dllentry;
3025 scope = method_aux->dll;
3028 if (!import || !scope) {
3029 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
3034 if (piinfo->implmap_idx) {
3035 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
3037 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
3038 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
3039 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
3040 scope = mono_metadata_string_heap (image, scope_token);
3044 *flags = piinfo->piflags;
3045 *entry_point = mono_string_new (domain, import);
3046 *dll_name = mono_string_new (domain, scope);
3049 ICALL_EXPORT MonoReflectionMethod *
3050 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3052 MonoMethodInflated *imethod;
3054 MonoReflectionMethod *ret = NULL;
3057 if (method->method->is_generic)
3060 if (!method->method->is_inflated)
3063 imethod = (MonoMethodInflated *) method->method;
3065 result = imethod->declaring;
3066 /* Not a generic method. */
3067 if (!result->is_generic)
3070 if (image_is_dynamic (method->method->klass->image)) {
3071 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3072 MonoReflectionMethod *res;
3075 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3076 * the dynamic case as well ?
3078 mono_image_lock ((MonoImage*)image);
3079 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3080 mono_image_unlock ((MonoImage*)image);
3086 if (imethod->context.class_inst) {
3087 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3088 /*Generic methods gets the context of the GTD.*/
3089 if (mono_class_get_context (klass)) {
3090 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3091 if (!mono_error_ok (&error))
3096 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3098 if (!mono_error_ok (&error))
3099 mono_error_set_pending_exception (&error);
3103 ICALL_EXPORT gboolean
3104 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3106 return mono_method_signature (method->method)->generic_param_count != 0;
3109 ICALL_EXPORT gboolean
3110 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3112 return method->method->is_generic;
3115 ICALL_EXPORT MonoArray*
3116 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3119 MonoReflectionType *rt;
3124 domain = mono_object_domain (method);
3126 if (method->method->is_inflated) {
3127 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3130 count = inst->type_argc;
3131 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3132 if (mono_error_set_pending_exception (&error))
3135 for (i = 0; i < count; i++) {
3136 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3137 if (mono_error_set_pending_exception (&error))
3140 mono_array_setref (res, i, rt);
3147 count = mono_method_signature (method->method)->generic_param_count;
3148 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3149 if (mono_error_set_pending_exception (&error))
3152 for (i = 0; i < count; i++) {
3153 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3154 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3155 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3157 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3158 if (mono_error_set_pending_exception (&error))
3161 mono_array_setref (res, i, rt);
3167 ICALL_EXPORT MonoObject *
3168 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3172 * Invoke from reflection is supposed to always be a virtual call (the API
3173 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3174 * greater flexibility.
3176 MonoMethod *m = method->method;
3177 MonoMethodSignature *sig = mono_method_signature (m);
3180 void *obj = this_arg;
3184 if (mono_security_core_clr_enabled () &&
3185 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3186 mono_error_set_pending_exception (&error);
3190 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3191 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3192 mono_error_cleanup (&error); /* FIXME does this make sense? */
3193 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3198 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3199 if (!is_ok (&error)) {
3200 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3203 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3204 char *target_name = mono_type_get_full_name (m->klass);
3205 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3206 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3208 g_free (target_name);
3212 m = mono_object_get_virtual_method (this_arg, m);
3213 /* must pass the pointer to the value for valuetype methods */
3214 if (m->klass->valuetype)
3215 obj = mono_object_unbox (this_arg);
3216 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3217 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3222 if (sig->ret->byref) {
3223 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"));
3227 pcount = params? mono_array_length (params): 0;
3228 if (pcount != sig->param_count) {
3229 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3233 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3234 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."));
3238 image = m->klass->image;
3239 if (image->assembly->ref_only) {
3240 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."));
3244 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3245 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3249 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3253 intptr_t *lower_bounds;
3254 pcount = mono_array_length (params);
3255 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3256 /* Note: the synthetized array .ctors have int32 as argument type */
3257 for (i = 0; i < pcount; ++i)
3258 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3260 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3261 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3262 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3263 if (!mono_error_ok (&error)) {
3264 mono_error_set_pending_exception (&error);
3268 for (i = 0; i < mono_array_length (arr); ++i) {
3269 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3270 if (!mono_error_ok (&error)) {
3271 mono_error_set_pending_exception (&error);
3274 mono_array_setref_fast (arr, i, subarray);
3276 return (MonoObject*)arr;
3279 if (m->klass->rank == pcount) {
3280 /* Only lengths provided. */
3281 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3282 if (!mono_error_ok (&error)) {
3283 mono_error_set_pending_exception (&error);
3287 return (MonoObject*)arr;
3289 g_assert (pcount == (m->klass->rank * 2));
3290 /* The arguments are lower-bound-length pairs */
3291 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3293 for (i = 0; i < pcount / 2; ++i) {
3294 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3295 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3298 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3299 if (!mono_error_ok (&error)) {
3300 mono_error_set_pending_exception (&error);
3304 return (MonoObject*)arr;
3307 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3308 mono_error_set_pending_exception (&error);
3312 #ifndef DISABLE_REMOTING
3313 ICALL_EXPORT MonoObject *
3314 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3317 MonoDomain *domain = mono_object_domain (method);
3318 MonoMethod *m = method->method;
3319 MonoMethodSignature *sig = mono_method_signature (m);
3320 MonoArray *out_args;
3322 int i, j, outarg_count = 0;
3324 if (m->klass == mono_defaults.object_class) {
3325 if (!strcmp (m->name, "FieldGetter")) {
3326 MonoClass *k = this_arg->vtable->klass;
3330 /* If this is a proxy, then it must be a CBO */
3331 if (k == mono_defaults.transparent_proxy_class) {
3332 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3333 this_arg = tp->rp->unwrapped_server;
3334 g_assert (this_arg);
3335 k = this_arg->vtable->klass;
3338 name = mono_array_get (params, MonoString *, 1);
3339 str = mono_string_to_utf8_checked (name, &error);
3340 if (mono_error_set_pending_exception (&error))
3344 MonoClassField* field = mono_class_get_field_from_name (k, str);
3347 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3348 if (field_klass->valuetype) {
3349 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3350 if (mono_error_set_pending_exception (&error))
3353 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3355 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3356 if (mono_error_set_pending_exception (&error))
3358 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3359 mono_array_setref (out_args, 0, result);
3366 g_assert_not_reached ();
3368 } else if (!strcmp (m->name, "FieldSetter")) {
3369 MonoClass *k = this_arg->vtable->klass;
3375 /* If this is a proxy, then it must be a CBO */
3376 if (k == mono_defaults.transparent_proxy_class) {
3377 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3378 this_arg = tp->rp->unwrapped_server;
3379 g_assert (this_arg);
3380 k = this_arg->vtable->klass;
3383 name = mono_array_get (params, MonoString *, 1);
3384 str = mono_string_to_utf8_checked (name, &error);
3385 if (mono_error_set_pending_exception (&error))
3389 MonoClassField* field = mono_class_get_field_from_name (k, str);
3392 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3393 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3395 if (field_klass->valuetype) {
3396 size = mono_type_size (field->type, &align);
3397 g_assert (size == mono_class_value_size (field_klass, NULL));
3398 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3400 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3403 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3404 if (mono_error_set_pending_exception (&error))
3406 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3415 g_assert_not_reached ();
3420 for (i = 0; i < mono_array_length (params); i++) {
3421 if (sig->params [i]->byref)
3425 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3426 if (mono_error_set_pending_exception (&error))
3429 /* handle constructors only for objects already allocated */
3430 if (!strcmp (method->method->name, ".ctor"))
3431 g_assert (this_arg);
3433 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3434 g_assert (!method->method->klass->valuetype);
3435 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3436 if (mono_error_set_pending_exception (&error))
3439 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3440 if (sig->params [i]->byref) {
3442 arg = mono_array_get (params, gpointer, i);
3443 mono_array_setref (out_args, j, arg);
3448 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3455 read_enum_value (const char *mem, int type)
3458 case MONO_TYPE_BOOLEAN:
3460 return *(guint8*)mem;
3462 return *(gint8*)mem;
3463 case MONO_TYPE_CHAR:
3465 return read16 (mem);
3467 return (gint16) read16 (mem);
3469 return read32 (mem);
3471 return (gint32) read32 (mem);
3474 return read64 (mem);
3476 g_assert_not_reached ();
3482 write_enum_value (char *mem, int type, guint64 value)
3486 case MONO_TYPE_I1: {
3487 guint8 *p = (guint8*)mem;
3493 case MONO_TYPE_CHAR: {
3494 guint16 *p = (guint16 *)mem;
3499 case MONO_TYPE_I4: {
3500 guint32 *p = (guint32 *)mem;
3505 case MONO_TYPE_I8: {
3506 guint64 *p = (guint64 *)mem;
3511 g_assert_not_reached ();
3516 ICALL_EXPORT MonoObject *
3517 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3525 domain = mono_object_domain (enumType);
3526 enumc = mono_class_from_mono_type (enumType->type);
3528 mono_class_init_checked (enumc, &error);
3529 if (mono_error_set_pending_exception (&error))
3532 etype = mono_class_enum_basetype (enumc);
3534 res = mono_object_new_checked (domain, enumc, &error);
3535 if (mono_error_set_pending_exception (&error))
3537 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3542 ICALL_EXPORT MonoBoolean
3543 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3545 int size = mono_class_value_size (a->vtable->klass, NULL);
3546 guint64 a_val = 0, b_val = 0;
3548 memcpy (&a_val, mono_object_unbox (a), size);
3549 memcpy (&b_val, mono_object_unbox (b), size);
3551 return (a_val & b_val) == b_val;
3554 ICALL_EXPORT MonoObject *
3555 ves_icall_System_Enum_get_value (MonoObject *eobj)
3567 g_assert (eobj->vtable->klass->enumtype);
3569 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3570 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3571 if (mono_error_set_pending_exception (&error))
3573 dst = (char *)res + sizeof (MonoObject);
3574 src = (char *)eobj + sizeof (MonoObject);
3575 size = mono_class_value_size (enumc, NULL);
3577 memcpy (dst, src, size);
3582 ICALL_EXPORT MonoReflectionType *
3583 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3586 MonoReflectionType *ret;
3590 klass = mono_class_from_mono_type (type->type);
3591 mono_class_init_checked (klass, &error);
3592 if (mono_error_set_pending_exception (&error))
3595 etype = mono_class_enum_basetype (klass);
3597 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3601 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3602 mono_error_set_pending_exception (&error);
3608 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3610 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3611 gpointer odata = (char *)other + sizeof (MonoObject);
3612 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3613 g_assert (basetype);
3618 if (eobj->vtable->klass != other->vtable->klass)
3621 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3622 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3623 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3626 return me > other ? 1 : -1; \
3629 switch (basetype->type) {
3631 COMPARE_ENUM_VALUES (guint8);
3633 COMPARE_ENUM_VALUES (gint8);
3634 case MONO_TYPE_CHAR:
3636 COMPARE_ENUM_VALUES (guint16);
3638 COMPARE_ENUM_VALUES (gint16);
3640 COMPARE_ENUM_VALUES (guint32);
3642 COMPARE_ENUM_VALUES (gint32);
3644 COMPARE_ENUM_VALUES (guint64);
3646 COMPARE_ENUM_VALUES (gint64);
3650 #undef COMPARE_ENUM_VALUES
3651 /* indicates that the enum was of an unsupported unerlying type */
3656 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3658 gpointer data = (char *)eobj + sizeof (MonoObject);
3659 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3660 g_assert (basetype);
3662 switch (basetype->type) {
3663 case MONO_TYPE_I1: {
3664 gint8 value = *((gint8*)data);
3665 return ((int)value ^ (int)value << 8);
3668 return *((guint8*)data);
3669 case MONO_TYPE_CHAR:
3671 return *((guint16*)data);
3673 case MONO_TYPE_I2: {
3674 gint16 value = *((gint16*)data);
3675 return ((int)(guint16)value | (((int)value) << 16));
3678 return *((guint32*)data);
3680 return *((gint32*)data);
3682 case MONO_TYPE_I8: {
3683 gint64 value = *((gint64*)data);
3684 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3687 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3692 ICALL_EXPORT MonoBoolean
3693 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3696 MonoDomain *domain = mono_object_domain (type);
3697 MonoClass *enumc = mono_class_from_mono_type (type->type);
3698 guint j = 0, nvalues;
3700 MonoClassField *field;
3702 guint64 field_value, previous_value = 0;
3703 gboolean sorted = TRUE;
3705 mono_class_init_checked (enumc, &error);
3706 if (mono_error_set_pending_exception (&error))
3710 if (!enumc->enumtype) {
3711 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3715 base_type = mono_class_enum_basetype (enumc)->type;
3717 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3718 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3719 if (mono_error_set_pending_exception (&error))
3721 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3722 if (mono_error_set_pending_exception (&error))
3726 while ((field = mono_class_get_fields (enumc, &iter))) {
3728 MonoTypeEnum def_type;
3730 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3732 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3734 if (mono_field_is_deleted (field))
3736 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3738 p = mono_class_get_field_default_value (field, &def_type);
3739 /* len = */ mono_metadata_decode_blob_size (p, &p);
3741 field_value = read_enum_value (p, base_type);
3742 mono_array_set (*values, guint64, j, field_value);
3744 if (previous_value > field_value)
3747 previous_value = field_value;
3755 BFLAGS_IgnoreCase = 1,
3756 BFLAGS_DeclaredOnly = 2,
3757 BFLAGS_Instance = 4,
3759 BFLAGS_Public = 0x10,
3760 BFLAGS_NonPublic = 0x20,
3761 BFLAGS_FlattenHierarchy = 0x40,
3762 BFLAGS_InvokeMethod = 0x100,
3763 BFLAGS_CreateInstance = 0x200,
3764 BFLAGS_GetField = 0x400,
3765 BFLAGS_SetField = 0x800,
3766 BFLAGS_GetProperty = 0x1000,
3767 BFLAGS_SetProperty = 0x2000,
3768 BFLAGS_ExactBinding = 0x10000,
3769 BFLAGS_SuppressChangeType = 0x20000,
3770 BFLAGS_OptionalParamBinding = 0x40000
3773 ICALL_EXPORT MonoArray*
3774 ves_icall_RuntimeType_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3778 MonoClass *startklass, *klass, *refklass;
3783 char *utf8_name = NULL;
3784 int (*compare_func) (const char *s1, const char *s2) = NULL;
3785 MonoClassField *field;
3786 MonoPtrArray tmp_array;
3788 domain = ((MonoObject *)type)->vtable->domain;
3789 if (type->type->byref) {
3790 MonoArray *result = mono_array_new_checked (domain, mono_defaults.field_info_class, 0, &error);
3791 mono_error_set_pending_exception (&error);
3795 klass = startklass = mono_class_from_mono_type (type->type);
3796 refklass = mono_class_from_mono_type (reftype->type);
3798 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3801 if (mono_class_has_failure (klass)) {
3802 mono_ptr_array_destroy (tmp_array);
3803 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3808 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3809 guint32 flags = mono_field_get_flags (field);
3811 if (mono_field_is_deleted_with_flags (field, flags))
3813 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3814 if (bflags & BFLAGS_Public)
3816 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3817 if (bflags & BFLAGS_NonPublic) {
3824 if (flags & FIELD_ATTRIBUTE_STATIC) {
3825 if (bflags & BFLAGS_Static)
3826 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3829 if (bflags & BFLAGS_Instance)
3837 if (utf8_name == NULL) {
3838 utf8_name = mono_string_to_utf8_checked (name, &error);
3839 if (!is_ok (&error))
3841 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3844 if (compare_func (mono_field_get_name (field), utf8_name))
3848 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3849 if (!mono_error_ok (&error))
3851 mono_ptr_array_append (tmp_array, member);
3853 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3856 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array), &error);
3857 if (!is_ok (&error))
3860 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3861 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3863 mono_ptr_array_destroy (tmp_array);
3865 if (utf8_name != NULL)
3870 mono_ptr_array_destroy (tmp_array);
3871 mono_error_set_pending_exception (&error);
3876 method_nonpublic (MonoMethod* method, gboolean start_klass)
3878 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3879 case METHOD_ATTRIBUTE_ASSEM:
3880 return (start_klass || mono_defaults.generic_ilist_class);
3881 case METHOD_ATTRIBUTE_PRIVATE:
3883 case METHOD_ATTRIBUTE_PUBLIC:
3891 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3894 MonoClass *startklass;
3898 /*FIXME, use MonoBitSet*/
3899 guint32 method_slots_default [8];
3900 guint32 *method_slots = NULL;
3901 int (*compare_func) (const char *s1, const char *s2) = NULL;
3903 array = g_ptr_array_new ();
3908 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3910 /* An optimization for calls made from Delegate:CreateDelegate () */
3911 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3912 method = mono_get_delegate_invoke (klass);
3915 g_ptr_array_add (array, method);
3919 mono_class_setup_methods (klass);
3920 mono_class_setup_vtable (klass);
3921 if (mono_class_has_failure (klass))
3924 if (is_generic_parameter (&klass->byval_arg))
3925 nslots = mono_class_get_vtable_size (klass->parent);
3927 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3928 if (nslots >= sizeof (method_slots_default) * 8) {
3929 method_slots = g_new0 (guint32, nslots / 32 + 1);
3931 method_slots = method_slots_default;
3932 memset (method_slots, 0, sizeof (method_slots_default));
3935 mono_class_setup_methods (klass);
3936 mono_class_setup_vtable (klass);
3937 if (mono_class_has_failure (klass))
3941 while ((method = mono_class_get_methods (klass, &iter))) {
3943 if (method->slot != -1) {
3944 g_assert (method->slot < nslots);
3945 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3947 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3948 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3951 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3953 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3954 if (bflags & BFLAGS_Public)
3956 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3962 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3963 if (bflags & BFLAGS_Static)
3964 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3967 if (bflags & BFLAGS_Instance)
3975 if (compare_func (name, method->name))
3980 g_ptr_array_add (array, method);
3982 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3984 if (method_slots != method_slots_default)
3985 g_free (method_slots);
3990 if (method_slots != method_slots_default)
3991 g_free (method_slots);
3992 g_ptr_array_free (array, TRUE);
3994 if (mono_class_has_failure (klass)) {
3995 *ex = mono_class_get_exception_for_failure (klass);
3997 *ex = mono_get_exception_execution_engine ("Unknown error");
4002 ICALL_EXPORT MonoArray*
4003 ves_icall_RuntimeType_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4005 static MonoClass *MethodInfo_array;
4009 MonoVTable *array_vtable;
4010 MonoException *ex = NULL;
4011 const char *mname = NULL;
4012 GPtrArray *method_array;
4013 MonoClass *klass, *refklass;
4016 mono_error_init (&error);
4018 if (!MethodInfo_array) {
4019 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
4020 mono_memory_barrier ();
4021 MethodInfo_array = klass;
4024 klass = mono_class_from_mono_type (type->type);
4025 refklass = mono_class_from_mono_type (reftype->type);
4026 domain = ((MonoObject *)type)->vtable->domain;
4027 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
4028 if (!is_ok (&error)) {
4029 mono_error_set_pending_exception (&error);
4032 if (type->type->byref) {
4033 res = mono_array_new_specific_checked (array_vtable, 0, &error);
4034 mono_error_set_pending_exception (&error);
4040 mname = mono_string_to_utf8_checked (name, &error);
4041 if (mono_error_set_pending_exception (&error))
4045 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
4046 g_free ((char*)mname);
4048 mono_set_pending_exception (ex);
4052 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
4053 if (!mono_error_ok (&error)) {
4054 mono_error_set_pending_exception (&error);
4058 for (i = 0; i < method_array->len; ++i) {
4059 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
4060 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
4061 if (!mono_error_ok (&error))
4063 mono_array_setref (res, i, rm);
4067 g_ptr_array_free (method_array, TRUE);
4068 if (!mono_error_ok (&error))
4069 mono_set_pending_exception (mono_error_convert_to_exception (&error));
4073 ICALL_EXPORT MonoArray*
4074 ves_icall_RuntimeType_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4077 MonoClass *startklass, *klass, *refklass;
4078 MonoArray *res = NULL;
4082 gpointer iter = NULL;
4083 MonoPtrArray tmp_array;
4086 domain = ((MonoObject *)type)->vtable->domain;
4087 if (type->type->byref) {
4088 res = mono_array_new_cached (domain, mono_defaults.method_info_class, 0, &error);
4089 mono_error_set_pending_exception (&error);
4093 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
4096 klass = startklass = mono_class_from_mono_type (type->type);
4097 refklass = mono_class_from_mono_type (reftype->type);
4099 mono_class_setup_methods (klass);
4100 if (mono_class_has_failure (klass)) {
4101 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
4106 while ((method = mono_class_get_methods (klass, &iter))) {
4108 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
4110 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4111 if (bflags & BFLAGS_Public)
4114 if (bflags & BFLAGS_NonPublic)
4120 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4121 if (bflags & BFLAGS_Static)
4122 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4125 if (bflags & BFLAGS_Instance)
4131 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
4132 if (mono_error_set_pending_exception (&error))
4135 mono_ptr_array_append (tmp_array, member);
4138 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array), &error);
4139 if (mono_error_set_pending_exception (&error))
4142 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4143 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4146 mono_ptr_array_destroy (tmp_array);
4152 property_hash (gconstpointer data)
4154 MonoProperty *prop = (MonoProperty*)data;
4156 return g_str_hash (prop->name);
4160 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
4162 if (method1->slot != -1 && method2->slot != -1)
4163 return method1->slot == method2->slot;
4165 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
4166 if (method1->is_inflated)
4167 method1 = ((MonoMethodInflated*) method1)->declaring;
4168 if (method2->is_inflated)
4169 method2 = ((MonoMethodInflated*) method2)->declaring;
4172 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4176 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4178 // Properties are hide-by-name-and-signature
4179 if (!g_str_equal (prop1->name, prop2->name))
4182 /* If we see a property in a generic method, we want to
4183 compare the generic signatures, not the inflated signatures
4184 because we might conflate two properties that were
4188 public T this[T t] { getter { return t; } } // method 1
4189 public U this[U u] { getter { return u; } } // method 2
4192 If we see int Foo<int,int>::Item[int] we need to know if
4193 the indexer came from method 1 or from method 2, and we
4194 shouldn't conflate them. (Bugzilla 36283)
4196 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4199 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4206 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4211 return method_nonpublic (accessor, start_klass);
4214 ICALL_EXPORT MonoArray*
4215 ves_icall_RuntimeType_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4219 MonoClass *startklass, *klass;
4225 gchar *propname = NULL;
4226 int (*compare_func) (const char *s1, const char *s2) = NULL;
4228 GHashTable *properties = NULL;
4229 MonoPtrArray tmp_array;
4231 mono_error_init (&error);
4233 domain = ((MonoObject *)type)->vtable->domain;
4234 if (type->type->byref) {
4235 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), 0, &error);
4236 mono_error_set_pending_exception (&error);
4240 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4242 klass = startklass = mono_class_from_mono_type (type->type);
4245 propname = mono_string_to_utf8_checked (name, &error);
4246 if (mono_error_set_pending_exception (&error))
4248 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4251 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4253 mono_class_setup_methods (klass);
4254 mono_class_setup_vtable (klass);
4255 if (mono_class_has_failure (klass))
4259 while ((prop = mono_class_get_properties (klass, &iter))) {
4265 flags = method->flags;
4268 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4269 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4270 if (bflags & BFLAGS_Public)
4272 } else if (bflags & BFLAGS_NonPublic) {
4273 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4274 property_accessor_nonpublic(prop->set, startklass == klass)) {
4281 if (flags & METHOD_ATTRIBUTE_STATIC) {
4282 if (bflags & BFLAGS_Static)
4283 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4286 if (bflags & BFLAGS_Instance)
4295 if (compare_func (propname, prop->name))
4299 if (g_hash_table_lookup (properties, prop))
4302 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4305 mono_ptr_array_append (tmp_array, pr);
4307 g_hash_table_insert (properties, prop, prop);
4309 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4312 g_hash_table_destroy (properties);
4315 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array), &error);
4316 if (!is_ok (&error))
4318 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4319 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4321 mono_ptr_array_destroy (tmp_array);
4328 if (mono_class_has_failure (klass))
4329 mono_error_set_for_class_failure (&error, klass);
4333 g_hash_table_destroy (properties);
4336 mono_ptr_array_destroy (tmp_array);
4338 mono_error_set_pending_exception (&error);
4344 event_hash (gconstpointer data)
4346 MonoEvent *event = (MonoEvent*)data;
4348 return g_str_hash (event->name);
4352 event_equal (MonoEvent *event1, MonoEvent *event2)
4354 // Events are hide-by-name
4355 return g_str_equal (event1->name, event2->name);
4358 ICALL_EXPORT MonoArray*
4359 ves_icall_RuntimeType_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4363 MonoClass *startklass, *klass;
4369 char *utf8_name = NULL;
4370 int (*compare_func) (const char *s1, const char *s2) = NULL;
4371 GHashTable *events = NULL;
4372 MonoPtrArray tmp_array;
4374 mono_error_init (&error);
4376 domain = mono_object_domain (type);
4377 if (type->type->byref) {
4378 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), 0, &error);
4379 mono_error_set_pending_exception (&error);
4383 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4385 klass = startklass = mono_class_from_mono_type (type->type);
4387 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4389 mono_class_setup_methods (klass);
4390 mono_class_setup_vtable (klass);
4391 if (mono_class_has_failure (klass))
4395 while ((event = mono_class_get_events (klass, &iter))) {
4397 method = event->add;
4399 method = event->remove;
4401 method = event->raise;
4403 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4404 if (bflags & BFLAGS_Public)
4406 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4407 if (bflags & BFLAGS_NonPublic)
4412 if (bflags & BFLAGS_NonPublic)
4418 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4419 if (bflags & BFLAGS_Static)
4420 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4423 if (bflags & BFLAGS_Instance)
4428 if (bflags & BFLAGS_Instance)
4434 if (utf8_name == NULL) {
4435 utf8_name = mono_string_to_utf8_checked (name, &error);
4436 if (!is_ok (&error))
4438 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4441 if (compare_func (event->name, utf8_name))
4445 if (g_hash_table_lookup (events, event))
4448 MonoReflectionEvent *ev_obj;
4449 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4452 mono_ptr_array_append (tmp_array, ev_obj);
4454 g_hash_table_insert (events, event, event);
4456 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4459 g_hash_table_destroy (events);
4461 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array), &error);
4462 if (!is_ok (&error))
4465 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4466 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4468 mono_ptr_array_destroy (tmp_array);
4470 if (utf8_name != NULL)
4476 if (mono_class_has_failure (klass))
4477 mono_error_set_for_class_failure (&error, klass);
4482 g_hash_table_destroy (events);
4483 if (utf8_name != NULL)
4486 mono_ptr_array_destroy (tmp_array);
4488 mono_error_set_pending_exception (&error);
4492 ICALL_EXPORT MonoArray*
4493 ves_icall_RuntimeType_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4496 MonoReflectionType *rt;
4499 MonoArray *res = NULL;
4504 MonoPtrArray tmp_array;
4506 mono_error_init (&error);
4508 domain = ((MonoObject *)type)->vtable->domain;
4509 if (type->type->byref) {
4510 MonoArray *result = mono_array_new_cached (domain, mono_defaults.runtimetype_class, 0, &error);
4511 mono_error_set_pending_exception (&error);
4514 klass = mono_class_from_mono_type (type->type);
4517 * If a nested type is generic, return its generic type definition.
4518 * Note that this means that the return value is essentially the set
4519 * of nested types of the generic type definition of @klass.
4521 * A note in MSDN claims that a generic type definition can have
4522 * nested types that aren't generic. In any case, the container of that
4523 * nested type would be the generic type definition.
4525 if (klass->generic_class)
4526 klass = klass->generic_class->container_class;
4528 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4530 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4532 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4533 if (bflags & BFLAGS_Public)
4536 if (bflags & BFLAGS_NonPublic)
4544 str = mono_string_to_utf8_checked (name, &error);
4545 if (!is_ok (&error))
4547 mono_identifier_unescape_type_name_chars (str);
4550 if (strcmp (nested->name, str))
4554 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4555 if (!is_ok (&error))
4558 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4561 res = mono_array_new_cached (domain, mono_defaults.runtimetype_class, mono_ptr_array_size (tmp_array), &error);
4562 if (!is_ok (&error))
4565 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4566 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4569 mono_ptr_array_destroy (tmp_array);
4573 mono_error_set_pending_exception (&error);
4577 ICALL_EXPORT MonoReflectionType*
4578 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4581 MonoReflectionType *ret;
4583 MonoType *type = NULL;
4584 MonoTypeNameParse info;
4585 gboolean type_resolve;
4587 /* On MS.NET, this does not fire a TypeResolve event */
4588 type_resolve = TRUE;
4589 str = mono_string_to_utf8_checked (name, &error);
4590 if (mono_error_set_pending_exception (&error))
4592 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4593 if (!mono_reflection_parse_type (str, &info)) {
4595 mono_reflection_free_type_info (&info);
4597 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4600 /*g_print ("failed parse\n");*/
4604 if (info.assembly.name) {
4606 mono_reflection_free_type_info (&info);
4608 /* 1.0 and 2.0 throw different exceptions */
4609 if (mono_defaults.generic_ilist_class)
4610 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4612 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4618 if (module != NULL) {
4619 if (module->image) {
4620 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4621 if (!is_ok (&error)) {
4623 mono_reflection_free_type_info (&info);
4624 mono_error_set_pending_exception (&error);
4631 if (assembly_is_dynamic (assembly->assembly)) {
4632 /* Enumerate all modules */
4633 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4637 if (abuilder->modules) {
4638 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4639 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4640 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4641 if (!is_ok (&error)) {
4643 mono_reflection_free_type_info (&info);
4644 mono_error_set_pending_exception (&error);
4652 if (!type && abuilder->loaded_modules) {
4653 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4654 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4655 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4656 if (!is_ok (&error)) {
4658 mono_reflection_free_type_info (&info);
4659 mono_error_set_pending_exception (&error);
4668 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4669 if (!is_ok (&error)) {
4671 mono_reflection_free_type_info (&info);
4672 mono_error_set_pending_exception (&error);
4677 mono_reflection_free_type_info (&info);
4679 MonoException *e = NULL;
4682 e = mono_get_exception_type_load (name, NULL);
4685 mono_set_pending_exception (e);
4689 if (type->type == MONO_TYPE_CLASS) {
4690 MonoClass *klass = mono_type_get_class (type);
4692 /* need to report exceptions ? */
4693 if (throwOnError && mono_class_has_failure (klass)) {
4694 /* report SecurityException (or others) that occured when loading the assembly */
4695 MonoException *exc = mono_class_get_exception_for_failure (klass);
4696 mono_set_pending_exception (exc);
4701 /* g_print ("got it\n"); */
4702 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4703 mono_error_set_pending_exception (&error);
4709 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4712 gchar *shadow_ini_file;
4715 /* Check for shadow-copied assembly */
4716 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4717 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4719 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4720 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4726 g_free (shadow_ini_file);
4727 if (content != NULL) {
4730 *filename = content;
4737 ICALL_EXPORT MonoString *
4738 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4740 MonoDomain *domain = mono_object_domain (assembly);
4741 MonoAssembly *mass = assembly->assembly;
4742 MonoString *res = NULL;
4747 if (g_path_is_absolute (mass->image->name)) {
4748 absolute = g_strdup (mass->image->name);
4749 dirname = g_path_get_dirname (absolute);
4751 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4752 dirname = g_strdup (mass->basedir);
4755 replace_shadow_path (domain, dirname, &absolute);
4760 for (i = strlen (absolute) - 1; i >= 0; i--)
4761 if (absolute [i] == '\\')
4766 uri = g_filename_to_uri (absolute, NULL, NULL);
4768 const char *prepend = "file://";
4770 if (*absolute == '/' && *(absolute + 1) == '/') {
4773 prepend = "file:///";
4776 uri = g_strconcat (prepend, absolute, NULL);
4780 res = mono_string_new (domain, uri);
4787 ICALL_EXPORT MonoBoolean
4788 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4790 MonoAssembly *mass = assembly->assembly;
4792 return mass->in_gac;
4795 ICALL_EXPORT MonoReflectionAssembly*
4796 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4801 MonoImageOpenStatus status;
4802 MonoReflectionAssembly* result = NULL;
4804 name = mono_string_to_utf8_checked (mname, &error);
4805 if (mono_error_set_pending_exception (&error))
4807 res = mono_assembly_load_with_partial_name (name, &status);
4813 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4815 mono_error_set_pending_exception (&error);
4819 ICALL_EXPORT MonoString *
4820 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4822 MonoDomain *domain = mono_object_domain (assembly);
4825 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4830 ICALL_EXPORT MonoBoolean
4831 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4833 return assembly->assembly->ref_only;
4836 ICALL_EXPORT MonoString *
4837 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4839 MonoDomain *domain = mono_object_domain (assembly);
4841 return mono_string_new (domain, assembly->assembly->image->version);
4844 ICALL_EXPORT MonoReflectionMethod*
4845 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4848 MonoReflectionMethod *res = NULL;
4851 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4855 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4856 if (!mono_error_ok (&error))
4859 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4862 if (!mono_error_ok (&error))
4863 mono_error_set_pending_exception (&error);
4867 ICALL_EXPORT MonoReflectionModule*
4868 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4871 MonoReflectionModule *result = NULL;
4872 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4873 if (!mono_error_ok (&error))
4874 mono_error_set_pending_exception (&error);
4878 ICALL_EXPORT MonoArray*
4879 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4882 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4883 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4884 if (mono_error_set_pending_exception (&error))
4889 for (i = 0; i < table->rows; ++i) {
4890 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4891 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4897 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4899 static MonoMethod *create_version = NULL;
4903 mono_error_init (error);
4906 if (!create_version) {
4907 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4908 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4909 g_assert (create_version);
4910 mono_method_desc_free (desc);
4916 args [3] = &revision;
4917 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4918 return_val_if_nok (error, NULL);
4920 mono_runtime_invoke_checked (create_version, result, args, error);
4921 return_val_if_nok (error, NULL);
4926 ICALL_EXPORT MonoArray*
4927 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4931 MonoDomain *domain = mono_object_domain (assembly);
4933 static MonoMethod *create_culture = NULL;
4934 MonoImage *image = assembly->assembly->image;
4938 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4941 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4942 if (mono_error_set_pending_exception (&error))
4946 if (count > 0 && !create_culture) {
4947 MonoMethodDesc *desc = mono_method_desc_new (
4948 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4949 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4950 g_assert (create_culture);
4951 mono_method_desc_free (desc);
4954 for (i = 0; i < count; i++) {
4955 MonoObject *version;
4956 MonoReflectionAssemblyName *aname;
4957 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4959 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4961 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4962 domain, mono_class_get_assembly_name_class (), &error);
4963 if (mono_error_set_pending_exception (&error))
4966 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4968 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4969 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4970 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4971 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4972 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4973 aname->versioncompat = 1; /* SameMachine (default) */
4974 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4976 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4977 if (mono_error_set_pending_exception (&error))
4980 MONO_OBJECT_SETREF (aname, version, version);
4982 if (create_culture) {
4984 MonoBoolean assembly_ref = 1;
4985 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4986 args [1] = &assembly_ref;
4988 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4989 if (mono_error_set_pending_exception (&error))
4992 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4995 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4996 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4997 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4999 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
5000 /* public key token isn't copied - the class library will
5001 automatically generate it from the public key if required */
5002 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
5003 if (mono_error_set_pending_exception (&error))
5006 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5007 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
5009 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
5010 if (mono_error_set_pending_exception (&error))
5013 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5014 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
5017 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
5018 if (mono_error_set_pending_exception (&error))
5021 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5024 /* note: this function doesn't return the codebase on purpose (i.e. it can
5025 be used under partial trust as path information isn't present). */
5027 mono_array_setref (result, i, aname);
5032 /* move this in some file in mono/util/ */
5034 g_concat_dir_and_file (const char *dir, const char *file)
5036 g_return_val_if_fail (dir != NULL, NULL);
5037 g_return_val_if_fail (file != NULL, NULL);
5040 * If the directory name doesn't have a / on the end, we need
5041 * to add one so we get a proper path to the file
5043 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
5044 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
5046 return g_strconcat (dir, file, NULL);
5050 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
5053 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5055 guint32 cols [MONO_MANIFEST_SIZE];
5056 guint32 impl, file_idx;
5060 char *n = mono_string_to_utf8_checked (name, &error);
5061 if (mono_error_set_pending_exception (&error))
5064 for (i = 0; i < table->rows; ++i) {
5065 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5066 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5067 if (strcmp (val, n) == 0)
5071 if (i == table->rows)
5074 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
5077 * this code should only be called after obtaining the
5078 * ResourceInfo and handling the other cases.
5080 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
5081 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
5083 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
5088 module = assembly->assembly->image;
5091 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
5092 if (mono_error_set_pending_exception (&error))
5094 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
5096 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
5099 ICALL_EXPORT gboolean
5100 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
5103 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5105 guint32 cols [MONO_MANIFEST_SIZE];
5106 guint32 file_cols [MONO_FILE_SIZE];
5110 n = mono_string_to_utf8_checked (name, &error);
5111 if (mono_error_set_pending_exception (&error))
5113 for (i = 0; i < table->rows; ++i) {
5114 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5115 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5116 if (strcmp (val, n) == 0)
5120 if (i == table->rows)
5123 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
5124 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
5127 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
5128 case MONO_IMPLEMENTATION_FILE:
5129 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5130 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5131 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
5132 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
5133 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
5134 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
5137 info->location = RESOURCE_LOCATION_EMBEDDED;
5140 case MONO_IMPLEMENTATION_ASSEMBLYREF:
5141 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5142 mono_assembly_load_reference (assembly->assembly->image, i - 1);
5143 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
5144 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
5145 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
5147 mono_set_pending_exception (ex);
5150 MonoReflectionAssembly *assm_obj;
5151 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5153 mono_error_set_pending_exception (&error);
5156 MONO_OBJECT_SETREF (info, assembly, assm_obj);
5158 /* Obtain info recursively */
5159 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5160 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5163 case MONO_IMPLEMENTATION_EXP_TYPE:
5164 g_assert_not_reached ();
5172 ICALL_EXPORT MonoObject*
5173 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
5176 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5177 MonoArray *result = NULL;
5182 /* check hash if needed */
5184 n = mono_string_to_utf8_checked (name, &error);
5185 if (mono_error_set_pending_exception (&error))
5188 for (i = 0; i < table->rows; ++i) {
5189 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5190 if (strcmp (val, n) == 0) {
5193 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5194 fn = mono_string_new (mono_object_domain (assembly), n);
5196 return (MonoObject*)fn;
5204 for (i = 0; i < table->rows; ++i) {
5205 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5209 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
5210 if (mono_error_set_pending_exception (&error))
5215 for (i = 0; i < table->rows; ++i) {
5216 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5217 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5218 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5219 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5224 return (MonoObject*)result;
5227 ICALL_EXPORT MonoArray*
5228 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5231 MonoDomain *domain = mono_domain_get();
5234 int i, j, file_count = 0;
5235 MonoImage **modules;
5236 guint32 module_count, real_module_count;
5237 MonoTableInfo *table;
5238 guint32 cols [MONO_FILE_SIZE];
5239 MonoImage *image = assembly->assembly->image;
5241 g_assert (image != NULL);
5242 g_assert (!assembly_is_dynamic (assembly->assembly));
5244 table = &image->tables [MONO_TABLE_FILE];
5245 file_count = table->rows;
5247 modules = image->modules;
5248 module_count = image->module_count;
5250 real_module_count = 0;
5251 for (i = 0; i < module_count; ++i)
5253 real_module_count ++;
5255 klass = mono_class_get_module_class ();
5256 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5257 if (mono_error_set_pending_exception (&error))
5260 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5261 if (mono_error_set_pending_exception (&error))
5264 mono_array_setref (res, 0, image_obj);
5266 for (i = 0; i < module_count; ++i)
5268 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5269 if (mono_error_set_pending_exception (&error))
5271 mono_array_setref (res, j, rm);
5275 for (i = 0; i < file_count; ++i, ++j) {
5276 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5277 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5278 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5279 if (mono_error_set_pending_exception (&error))
5281 mono_array_setref (res, j, rm);
5284 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5286 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5287 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5290 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5291 if (mono_error_set_pending_exception (&error))
5293 mono_array_setref (res, j, rm);
5300 ICALL_EXPORT MonoReflectionMethod*
5301 ves_icall_GetCurrentMethod (void)
5303 MonoReflectionMethod *res = NULL;
5306 MonoMethod *m = mono_method_get_last_managed ();
5309 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5313 while (m->is_inflated)
5314 m = ((MonoMethodInflated*)m)->declaring;
5316 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5317 mono_error_set_pending_exception (&error);
5323 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5326 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5329 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5330 //method is inflated, we should inflate it on the other class
5331 MonoGenericContext ctx;
5332 ctx.method_inst = inflated->context.method_inst;
5333 ctx.class_inst = inflated->context.class_inst;
5334 if (klass->generic_class)
5335 ctx.class_inst = klass->generic_class->context.class_inst;
5336 else if (klass->generic_container)
5337 ctx.class_inst = klass->generic_container->context.class_inst;
5338 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5339 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5343 mono_class_setup_methods (method->klass);
5344 if (mono_class_has_failure (method->klass))
5346 for (i = 0; i < method->klass->method.count; ++i) {
5347 if (method->klass->methods [i] == method) {
5352 mono_class_setup_methods (klass);
5353 if (mono_class_has_failure (klass))
5355 g_assert (offset >= 0 && offset < klass->method.count);
5356 return klass->methods [offset];
5359 ICALL_EXPORT MonoReflectionMethod*
5360 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5362 MonoReflectionMethod *res = NULL;
5366 klass = mono_class_from_mono_type (type);
5367 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5369 if (method->klass != klass) {
5370 method = mono_method_get_equivalent_method (method, klass);
5375 klass = method->klass;
5376 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5377 mono_error_set_pending_exception (&error);
5381 ICALL_EXPORT MonoReflectionMethodBody*
5382 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5385 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5386 mono_error_set_pending_exception (&error);
5390 ICALL_EXPORT MonoReflectionAssembly*
5391 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5394 MonoReflectionAssembly *result;
5395 MonoMethod *dest = NULL;
5397 mono_stack_walk_no_il (get_executing, &dest);
5399 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5401 mono_error_set_pending_exception (&error);
5406 ICALL_EXPORT MonoReflectionAssembly*
5407 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5410 MonoReflectionAssembly *result;
5411 MonoDomain* domain = mono_domain_get ();
5413 if (!domain->entry_assembly)
5416 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5418 mono_error_set_pending_exception (&error);
5422 ICALL_EXPORT MonoReflectionAssembly*
5423 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5428 MonoReflectionAssembly *result;
5431 mono_stack_walk_no_il (get_executing, &dest);
5433 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5437 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5440 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5442 mono_error_set_pending_exception (&error);
5446 ICALL_EXPORT MonoString *
5447 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5448 gboolean assembly_qualified)
5450 MonoDomain *domain = mono_object_domain (object);
5451 MonoTypeNameFormat format;
5456 format = assembly_qualified ?
5457 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5458 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5460 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5462 name = mono_type_get_name_full (object->type, format);
5466 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5471 res = mono_string_new (domain, name);
5478 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5481 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5483 mono_class_init_checked (klass, &error);
5484 mono_error_set_pending_exception (&error);
5485 return mono_security_core_clr_class_level (klass);
5489 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5491 MonoClassField *field = rfield->field;
5492 return mono_security_core_clr_field_level (field, TRUE);
5496 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5498 MonoMethod *method = rfield->method;
5499 return mono_security_core_clr_method_level (method, TRUE);
5503 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)
5505 static MonoMethod *create_culture = NULL;
5509 const char *pkey_ptr;
5511 MonoBoolean assembly_ref = 0;
5513 mono_error_init (error);
5515 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5516 aname->major = name->major;
5517 aname->minor = name->minor;
5518 aname->build = name->build;
5519 aname->flags = name->flags;
5520 aname->revision = name->revision;
5521 aname->hashalg = name->hash_alg;
5522 aname->versioncompat = 1; /* SameMachine (default) */
5523 aname->processor_architecture = name->arch;
5525 if (by_default_version) {
5526 MonoObject *version;
5528 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5529 return_if_nok (error);
5531 MONO_OBJECT_SETREF (aname, version, version);
5535 if (absolute != NULL && *absolute != '\0') {
5536 const gchar *prepend = "file://";
5539 codebase = g_strdup (absolute);
5544 for (i = strlen (codebase) - 1; i >= 0; i--)
5545 if (codebase [i] == '\\')
5548 if (*codebase == '/' && *(codebase + 1) == '/') {
5551 prepend = "file:///";
5555 result = g_strconcat (prepend, codebase, NULL);
5561 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5565 if (!create_culture) {
5566 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5567 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5568 g_assert (create_culture);
5569 mono_method_desc_free (desc);
5572 if (name->culture) {
5573 args [0] = mono_string_new (domain, name->culture);
5574 args [1] = &assembly_ref;
5576 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5577 return_if_nok (error);
5579 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5582 if (name->public_key) {
5583 pkey_ptr = (char*)name->public_key;
5584 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5586 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5587 return_if_nok (error);
5588 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5589 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5590 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5591 } else if (default_publickey) {
5592 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5593 return_if_nok (error);
5594 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5595 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5598 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5599 if (name->public_key_token [0]) {
5603 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5604 return_if_nok (error);
5606 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5607 p = mono_array_addr (keyToken, char, 0);
5609 for (i = 0, j = 0; i < 8; i++) {
5610 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5611 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5614 } else if (default_token) {
5615 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5616 return_if_nok (error);
5617 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5621 ICALL_EXPORT MonoString *
5622 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5624 MonoDomain *domain = mono_object_domain (assembly);
5625 MonoAssembly *mass = assembly->assembly;
5629 name = mono_stringify_assembly_name (&mass->aname);
5630 res = mono_string_new (domain, name);
5637 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5640 gchar *absolute, *dirname;
5641 MonoAssembly *mass = assembly->assembly;
5643 /* XXX this is duplicated code to compute the codebase URI, unify it */
5644 if (g_path_is_absolute (mass->image->name)) {
5645 absolute = g_strdup (mass->image->name);
5646 dirname = g_path_get_dirname (absolute);
5648 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5649 dirname = g_strdup (mass->basedir);
5652 replace_shadow_path (mono_object_domain (assembly), dirname, &absolute);
5655 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5656 mono_error_set_pending_exception (&error);
5662 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5666 MonoImageOpenStatus status = MONO_IMAGE_OK;
5669 MonoAssemblyName name;
5672 filename = mono_string_to_utf8_checked (fname, &error);
5673 if (mono_error_set_pending_exception (&error))
5676 dirname = g_path_get_dirname (filename);
5677 replace_shadow_path (mono_domain_get (), dirname, &filename);
5680 image = mono_image_open (filename, &status);
5686 if (status == MONO_IMAGE_IMAGE_INVALID)
5687 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5689 exc = mono_get_exception_file_not_found2 (NULL, fname);
5690 mono_set_pending_exception (exc);
5694 res = mono_assembly_fill_assembly_name (image, &name);
5696 mono_image_close (image);
5698 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5702 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5703 mono_error_set_pending_exception (&error);
5705 mono_image_close (image);
5709 ICALL_EXPORT MonoBoolean
5710 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5711 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5713 MonoBoolean result = FALSE;
5714 MonoDeclSecurityEntry entry;
5716 /* SecurityAction.RequestMinimum */
5717 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5718 *minimum = entry.blob;
5719 *minLength = entry.size;
5722 /* SecurityAction.RequestOptional */
5723 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5724 *optional = entry.blob;
5725 *optLength = entry.size;
5728 /* SecurityAction.RequestRefuse */
5729 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5730 *refused = entry.blob;
5731 *refLength = entry.size;
5739 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5741 guint32 attrs, visibility;
5743 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5744 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5745 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5748 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5754 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5756 MonoReflectionType *rt;
5759 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5762 mono_error_init (error);
5764 /* we start the count from 1 because we skip the special type <Module> */
5767 for (i = 1; i < tdef->rows; ++i) {
5768 if (mono_module_type_is_visible (tdef, image, i + 1))
5772 count = tdef->rows - 1;
5774 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5775 return_val_if_nok (error, NULL);
5776 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5777 return_val_if_nok (error, NULL);
5779 for (i = 1; i < tdef->rows; ++i) {
5780 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5781 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5784 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5785 return_val_if_nok (error, NULL);
5787 mono_array_setref (res, count, rt);
5789 MonoException *ex = mono_error_convert_to_exception (error);
5790 mono_array_setref (*exceptions, count, ex);
5799 ICALL_EXPORT MonoArray*
5800 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5803 MonoArray *res = NULL;
5804 MonoArray *exceptions = NULL;
5805 MonoImage *image = NULL;
5806 MonoTableInfo *table = NULL;
5809 int i, len, ex_count;
5811 domain = mono_object_domain (assembly);
5813 g_assert (!assembly_is_dynamic (assembly->assembly));
5814 image = assembly->assembly->image;
5815 table = &image->tables [MONO_TABLE_FILE];
5816 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5817 if (mono_error_set_pending_exception (&error))
5820 /* Append data from all modules in the assembly */
5821 for (i = 0; i < table->rows; ++i) {
5822 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5823 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5828 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5829 if (mono_error_set_pending_exception (&error))
5833 /* Append the new types to the end of the array */
5834 if (mono_array_length (res2) > 0) {
5836 MonoArray *res3, *ex3;
5838 len1 = mono_array_length (res);
5839 len2 = mono_array_length (res2);
5841 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5842 if (mono_error_set_pending_exception (&error))
5844 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5845 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5848 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5849 if (mono_error_set_pending_exception (&error))
5851 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5852 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5859 /* the ReflectionTypeLoadException must have all the types (Types property),
5860 * NULL replacing types which throws an exception. The LoaderException must
5861 * contain all exceptions for NULL items.
5864 len = mono_array_length (res);
5867 for (i = 0; i < len; i++) {
5868 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5872 klass = mono_type_get_class (t->type);
5873 if ((klass != NULL) && mono_class_has_failure (klass)) {
5874 /* keep the class in the list */
5875 list = g_list_append (list, klass);
5876 /* and replace Type with NULL */
5877 mono_array_setref (res, i, NULL);
5884 if (list || ex_count) {
5886 MonoException *exc = NULL;
5887 MonoArray *exl = NULL;
5888 int j, length = g_list_length (list) + ex_count;
5890 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5891 if (mono_error_set_pending_exception (&error)) {
5895 /* Types for which mono_class_get_checked () succeeded */
5896 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5897 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5898 mono_array_setref (exl, i, exc);
5900 /* Types for which it don't */
5901 for (j = 0; j < mono_array_length (exceptions); ++j) {
5902 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5904 g_assert (i < length);
5905 mono_array_setref (exl, i, exc);
5912 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5913 if (!is_ok (&error)) {
5914 mono_error_set_pending_exception (&error);
5917 mono_set_pending_exception (exc);
5924 ICALL_EXPORT gboolean
5925 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5928 MonoAssemblyName aname;
5929 MonoDomain *domain = mono_object_domain (name);
5931 gboolean is_version_defined;
5932 gboolean is_token_defined;
5934 aname.public_key = NULL;
5935 val = mono_string_to_utf8_checked (assname, &error);
5936 if (mono_error_set_pending_exception (&error))
5939 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5940 g_free ((guint8*) aname.public_key);
5945 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5946 mono_error_set_pending_exception (&error);
5948 mono_assembly_name_free (&aname);
5949 g_free ((guint8*) aname.public_key);
5955 ICALL_EXPORT MonoReflectionType*
5956 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5959 MonoReflectionType *ret;
5960 MonoDomain *domain = mono_object_domain (module);
5963 g_assert (module->image);
5965 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5966 /* These images do not have a global type */
5969 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5970 if (!mono_error_ok (&error)) {
5971 mono_error_set_pending_exception (&error);
5975 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5976 if (!mono_error_ok (&error)) {
5977 mono_error_set_pending_exception (&error);
5985 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5987 /*if (module->image)
5988 mono_image_close (module->image);*/
5991 ICALL_EXPORT MonoString*
5992 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5994 MonoDomain *domain = mono_object_domain (module);
5996 g_assert (module->image);
5997 return mono_string_new (domain, module->image->guid);
6000 ICALL_EXPORT gpointer
6001 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
6004 if (module->image && module->image->is_module_handle)
6005 return module->image->raw_data;
6008 return (gpointer) (-1);
6012 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
6014 if (image_is_dynamic (image)) {
6015 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
6016 *pe_kind = dyn->pe_kind;
6017 *machine = dyn->machine;
6020 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
6021 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
6026 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
6028 return (image->md_version_major << 16) | (image->md_version_minor);
6031 ICALL_EXPORT MonoArray*
6032 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
6035 MonoArray *exceptions;
6038 if (!module->image) {
6039 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
6040 mono_error_set_pending_exception (&error);
6045 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
6046 if (mono_error_set_pending_exception (&error))
6049 for (i = 0; i < mono_array_length (exceptions); ++i) {
6050 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
6052 mono_set_pending_exception (ex);
6061 mono_memberref_is_method (MonoImage *image, guint32 token)
6063 if (!image_is_dynamic (image)) {
6064 guint32 cols [MONO_MEMBERREF_SIZE];
6066 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
6067 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
6068 mono_metadata_decode_blob_size (sig, &sig);
6069 return (*sig != 0x6);
6072 MonoClass *handle_class;
6074 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
6075 mono_error_cleanup (&error); /* just probing, ignore error */
6079 return mono_defaults.methodhandle_class == handle_class;
6084 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
6087 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
6088 mono_array_addr (type_args, MonoType*, 0));
6090 context->class_inst = NULL;
6092 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
6093 mono_array_addr (method_args, MonoType*, 0));
6095 context->method_inst = NULL;
6098 ICALL_EXPORT MonoType*
6099 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6102 int table = mono_metadata_token_table (token);
6103 int index = mono_metadata_token_index (token);
6104 MonoGenericContext context;
6107 *resolve_error = ResolveTokenError_Other;
6109 /* Validate token */
6110 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
6111 (table != MONO_TABLE_TYPESPEC)) {
6112 *resolve_error = ResolveTokenError_BadTable;
6116 if (image_is_dynamic (image)) {
6117 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
6118 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6119 mono_error_cleanup (&error);
6120 return klass ? &klass->byval_arg : NULL;
6123 init_generic_context_from_args (&context, type_args, method_args);
6124 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6125 mono_error_cleanup (&error);
6126 return klass ? &klass->byval_arg : NULL;
6129 if ((index <= 0) || (index > image->tables [table].rows)) {
6130 *resolve_error = ResolveTokenError_OutOfRange;
6134 init_generic_context_from_args (&context, type_args, method_args);
6135 klass = mono_class_get_checked (image, token, &error);
6137 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
6138 if (!mono_error_ok (&error)) {
6139 mono_error_set_pending_exception (&error);
6144 return &klass->byval_arg;
6149 ICALL_EXPORT MonoMethod*
6150 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6153 int table = mono_metadata_token_table (token);
6154 int index = mono_metadata_token_index (token);
6155 MonoGenericContext context;
6158 *resolve_error = ResolveTokenError_Other;
6160 /* Validate token */
6161 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
6162 (table != MONO_TABLE_MEMBERREF)) {
6163 *resolve_error = ResolveTokenError_BadTable;
6167 if (image_is_dynamic (image)) {
6168 if (table == MONO_TABLE_METHOD) {
6169 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6170 mono_error_cleanup (&error);
6174 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
6175 *resolve_error = ResolveTokenError_BadTable;
6179 init_generic_context_from_args (&context, type_args, method_args);
6180 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6181 mono_error_cleanup (&error);
6185 if ((index <= 0) || (index > image->tables [table].rows)) {
6186 *resolve_error = ResolveTokenError_OutOfRange;
6189 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6190 *resolve_error = ResolveTokenError_BadTable;
6194 init_generic_context_from_args (&context, type_args, method_args);
6195 method = mono_get_method_checked (image, token, NULL, &context, &error);
6196 mono_error_set_pending_exception (&error);
6201 ICALL_EXPORT MonoString*
6202 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6205 int index = mono_metadata_token_index (token);
6207 *resolve_error = ResolveTokenError_Other;
6209 /* Validate token */
6210 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6211 *resolve_error = ResolveTokenError_BadTable;
6215 if (image_is_dynamic (image)) {
6216 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6217 mono_error_cleanup (&error);
6221 if ((index <= 0) || (index >= image->heap_us.size)) {
6222 *resolve_error = ResolveTokenError_OutOfRange;
6226 /* FIXME: What to do if the index points into the middle of a string ? */
6228 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
6229 mono_error_set_pending_exception (&error);
6233 ICALL_EXPORT MonoClassField*
6234 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6238 int table = mono_metadata_token_table (token);
6239 int index = mono_metadata_token_index (token);
6240 MonoGenericContext context;
6241 MonoClassField *field;
6243 *resolve_error = ResolveTokenError_Other;
6245 /* Validate token */
6246 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6247 *resolve_error = ResolveTokenError_BadTable;
6251 if (image_is_dynamic (image)) {
6252 if (table == MONO_TABLE_FIELD) {
6253 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6254 mono_error_cleanup (&error);
6258 if (mono_memberref_is_method (image, token)) {
6259 *resolve_error = ResolveTokenError_BadTable;
6263 init_generic_context_from_args (&context, type_args, method_args);
6264 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6265 mono_error_cleanup (&error);
6269 if ((index <= 0) || (index > image->tables [table].rows)) {
6270 *resolve_error = ResolveTokenError_OutOfRange;
6273 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6274 *resolve_error = ResolveTokenError_BadTable;
6278 init_generic_context_from_args (&context, type_args, method_args);
6279 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6280 mono_error_set_pending_exception (&error);
6286 ICALL_EXPORT MonoObject*
6287 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6291 int table = mono_metadata_token_table (token);
6293 *error = ResolveTokenError_Other;
6296 case MONO_TABLE_TYPEDEF:
6297 case MONO_TABLE_TYPEREF:
6298 case MONO_TABLE_TYPESPEC: {
6299 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6301 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6302 mono_error_set_pending_exception (&merror);
6309 case MONO_TABLE_METHOD:
6310 case MONO_TABLE_METHODSPEC: {
6311 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6313 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6314 mono_error_set_pending_exception (&merror);
6320 case MONO_TABLE_FIELD: {
6321 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6323 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6324 mono_error_set_pending_exception (&merror);
6330 case MONO_TABLE_MEMBERREF:
6331 if (mono_memberref_is_method (image, token)) {
6332 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6334 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6335 mono_error_set_pending_exception (&merror);
6342 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6344 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6345 mono_error_set_pending_exception (&merror);
6354 *error = ResolveTokenError_BadTable;
6360 ICALL_EXPORT MonoArray*
6361 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6364 int table = mono_metadata_token_table (token);
6365 int idx = mono_metadata_token_index (token);
6366 MonoTableInfo *tables = image->tables;
6371 *resolve_error = ResolveTokenError_OutOfRange;
6373 /* FIXME: Support other tables ? */
6374 if (table != MONO_TABLE_STANDALONESIG)
6377 if (image_is_dynamic (image))
6380 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6383 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6385 ptr = mono_metadata_blob_heap (image, sig);
6386 len = mono_metadata_decode_blob_size (ptr, &ptr);
6388 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6389 if (mono_error_set_pending_exception (&error))
6391 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6395 ICALL_EXPORT MonoReflectionType*
6396 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6399 MonoReflectionType *ret;
6401 int isbyref = 0, rank;
6403 char *str = mono_string_to_utf8_checked (smodifiers, &error);
6404 if (mono_error_set_pending_exception (&error))
6407 klass = mono_class_from_mono_type (tb->type.type);
6409 /* logic taken from mono_reflection_parse_type(): keep in sync */
6413 if (isbyref) { /* only one level allowed by the spec */
6422 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6423 mono_error_set_pending_exception (&error);
6427 klass = mono_ptr_class_get (&klass->byval_arg);
6428 mono_class_init (klass);
6439 else if (*p != '*') { /* '*' means unknown lower bound */
6450 klass = mono_array_class_get (klass, rank);
6451 mono_class_init (klass);
6460 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6461 mono_error_set_pending_exception (&error);
6466 ICALL_EXPORT MonoBoolean
6467 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6473 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6479 check_for_invalid_type (MonoClass *klass, MonoError *error)
6484 mono_error_init (error);
6486 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6489 name = mono_type_get_full_name (klass);
6490 str = mono_string_new (mono_domain_get (), name);
6492 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6495 ICALL_EXPORT MonoReflectionType *
6496 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6499 MonoReflectionType *ret;
6500 MonoClass *klass, *aklass;
6502 klass = mono_class_from_mono_type (type->type);
6503 check_for_invalid_type (klass, &error);
6504 mono_error_set_pending_exception (&error);
6506 if (rank == 0) //single dimentional array
6507 aklass = mono_array_class_get (klass, 1);
6509 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6511 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6512 mono_error_set_pending_exception (&error);
6517 ICALL_EXPORT MonoReflectionType *
6518 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6521 MonoReflectionType *ret;
6524 klass = mono_class_from_mono_type (type->type);
6525 mono_class_init_checked (klass, &error);
6526 if (mono_error_set_pending_exception (&error))
6529 check_for_invalid_type (klass, &error);
6530 if (mono_error_set_pending_exception (&error))
6533 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6534 mono_error_set_pending_exception (&error);
6539 ICALL_EXPORT MonoReflectionType *
6540 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6543 MonoReflectionType *ret;
6544 MonoClass *klass, *pklass;
6546 klass = mono_class_from_mono_type (type->type);
6547 mono_class_init_checked (klass, &error);
6548 if (mono_error_set_pending_exception (&error))
6550 check_for_invalid_type (klass, &error);
6551 if (mono_error_set_pending_exception (&error))
6554 pklass = mono_ptr_class_get (type->type);
6556 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6557 mono_error_set_pending_exception (&error);
6562 ICALL_EXPORT MonoObject *
6563 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6564 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6567 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6568 MonoObject *delegate;
6570 MonoMethod *method = info->method;
6572 mono_class_init_checked (delegate_class, &error);
6573 if (mono_error_set_pending_exception (&error))
6576 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6577 /* FIXME improve this exception message */
6578 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6580 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6581 mono_error_set_pending_exception (&error);
6585 if (mono_security_core_clr_enabled ()) {
6586 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6587 if (throwOnBindFailure)
6588 mono_error_set_pending_exception (&error);
6590 mono_error_cleanup (&error);
6595 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6596 if (mono_error_set_pending_exception (&error))
6599 if (method_is_dynamic (method)) {
6600 /* Creating a trampoline would leak memory */
6601 func = mono_compile_method_checked (method, &error);
6602 if (mono_error_set_pending_exception (&error))
6605 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6606 method = mono_object_get_virtual_method (target, method);
6607 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6608 if (mono_error_set_pending_exception (&error))
6610 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6613 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6614 if (mono_error_set_pending_exception (&error))
6619 ICALL_EXPORT MonoMulticastDelegate *
6620 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6623 MonoMulticastDelegate *ret;
6625 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6627 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6628 if (mono_error_set_pending_exception (&error))
6631 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6636 ICALL_EXPORT MonoReflectionMethod*
6637 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6639 MonoReflectionMethod *ret = NULL;
6641 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6642 mono_error_set_pending_exception (&error);
6648 static inline gint32
6649 mono_array_get_byte_length (MonoArray *array)
6655 klass = array->obj.vtable->klass;
6657 if (array->bounds == NULL)
6658 length = array->max_length;
6661 for (i = 0; i < klass->rank; ++ i)
6662 length *= array->bounds [i].length;
6665 switch (klass->element_class->byval_arg.type) {
6668 case MONO_TYPE_BOOLEAN:
6672 case MONO_TYPE_CHAR:
6680 return length * sizeof (gpointer);
6691 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6693 return mono_array_get_byte_length (array);
6697 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6699 return mono_array_get (array, gint8, idx);
6703 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6705 mono_array_set (array, gint8, idx, value);
6708 ICALL_EXPORT MonoBoolean
6709 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6711 guint8 *src_buf, *dest_buf;
6714 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6718 g_assert (count >= 0);
6720 /* This is called directly from the class libraries without going through the managed wrapper */
6721 MONO_CHECK_ARG_NULL (src, FALSE);
6722 MONO_CHECK_ARG_NULL (dest, FALSE);
6724 /* watch out for integer overflow */
6725 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6728 src_buf = (guint8 *)src->vector + src_offset;
6729 dest_buf = (guint8 *)dest->vector + dest_offset;
6732 memcpy (dest_buf, src_buf, count);
6734 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6739 #ifndef DISABLE_REMOTING
6740 ICALL_EXPORT MonoObject *
6741 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6744 MonoDomain *domain = mono_object_domain (this_obj);
6746 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6747 MonoTransparentProxy *tp;
6751 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6752 if (mono_error_set_pending_exception (&error))
6755 tp = (MonoTransparentProxy*) res;
6757 MONO_OBJECT_SETREF (tp, rp, rp);
6758 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6759 klass = mono_class_from_mono_type (type);
6761 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6762 mono_class_setup_vtable (klass);
6763 if (mono_class_has_failure (klass)) {
6764 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6768 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6769 if (mono_error_set_pending_exception (&error))
6771 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6772 if (mono_error_set_pending_exception (&error))
6775 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6776 if (mono_error_set_pending_exception (&error))
6781 ICALL_EXPORT MonoReflectionType *
6782 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6785 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6786 mono_error_set_pending_exception (&error);
6792 /* System.Environment */
6795 ves_icall_System_Environment_get_UserName (void)
6797 /* using glib is more portable */
6798 return mono_string_new (mono_domain_get (), g_get_user_name ());
6802 ICALL_EXPORT MonoString *
6803 ves_icall_System_Environment_get_MachineName (void)
6805 #if defined (HOST_WIN32)
6810 len = MAX_COMPUTERNAME_LENGTH + 1;
6811 buf = g_new (gunichar2, len);
6814 if (GetComputerName (buf, (PDWORD) &len)) {
6816 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6817 mono_error_set_pending_exception (&error);
6822 #elif !defined(DISABLE_SOCKETS)
6826 #if defined _SC_HOST_NAME_MAX
6827 n = sysconf (_SC_HOST_NAME_MAX);
6831 buf = g_malloc (n+1);
6833 if (gethostname (buf, n) == 0){
6835 result = mono_string_new (mono_domain_get (), buf);
6842 return mono_string_new (mono_domain_get (), "mono");
6847 ves_icall_System_Environment_get_Platform (void)
6849 #if defined (TARGET_WIN32)
6852 #elif defined(__MACH__)
6855 // Notice that the value is hidden from user code, and only exposed
6856 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6857 // define and making assumptions based on Unix/128/4 values before there
6858 // was a MacOS define. Lots of code would assume that not-Unix meant
6859 // Windows, but in this case, it would be OSX.
6868 ICALL_EXPORT MonoString *
6869 ves_icall_System_Environment_get_NewLine (void)
6871 #if defined (HOST_WIN32)
6872 return mono_string_new (mono_domain_get (), "\r\n");
6874 return mono_string_new (mono_domain_get (), "\n");
6878 ICALL_EXPORT MonoBoolean
6879 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6881 #if SIZEOF_VOID_P == 8
6885 gboolean isWow64Process = FALSE;
6886 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6887 return (MonoBoolean)isWow64Process;
6889 #elif defined(HAVE_SYS_UTSNAME_H)
6890 struct utsname name;
6892 if (uname (&name) >= 0) {
6893 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6900 ICALL_EXPORT MonoString *
6901 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6910 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6911 if (mono_error_set_pending_exception (&error))
6913 value = g_getenv (utf8_name);
6920 return mono_string_new (mono_domain_get (), value);
6924 * There is no standard way to get at environ.
6927 #ifndef __MINGW32_VERSION
6928 #if defined(__APPLE__)
6929 #if defined (TARGET_OSX)
6930 /* Apple defines this in crt_externs.h but doesn't provide that header for
6931 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6932 * in fact exist on all implementations (so far)
6934 gchar ***_NSGetEnviron(void);
6935 #define environ (*_NSGetEnviron())
6937 static char *mono_environ[1] = { NULL };
6938 #define environ mono_environ
6939 #endif /* defined (TARGET_OSX) */
6947 ICALL_EXPORT MonoArray *
6948 ves_icall_System_Environment_GetCoomandLineArgs (void)
6951 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6952 mono_error_set_pending_exception (&error);
6956 ICALL_EXPORT MonoArray *
6957 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6969 env_strings = GetEnvironmentStrings();
6972 env_string = env_strings;
6973 while (*env_string != '\0') {
6974 /* weird case that MS seems to skip */
6975 if (*env_string != '=')
6977 while (*env_string != '\0')
6983 domain = mono_domain_get ();
6984 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6985 if (mono_error_set_pending_exception (&error))
6990 env_string = env_strings;
6991 while (*env_string != '\0') {
6992 /* weird case that MS seems to skip */
6993 if (*env_string != '=') {
6994 equal_str = wcschr(env_string, '=');
6995 g_assert(equal_str);
6997 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6998 if (mono_error_set_pending_exception (&error))
7001 mono_array_setref (names, n, str);
7004 while (*env_string != '\0')
7009 FreeEnvironmentStrings (env_strings);
7023 for (e = environ; *e != 0; ++ e)
7026 domain = mono_domain_get ();
7027 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
7028 if (mono_error_set_pending_exception (&error))
7032 for (e = environ; *e != 0; ++ e) {
7033 parts = g_strsplit (*e, "=", 2);
7035 str = mono_string_new (domain, *parts);
7036 mono_array_setref (names, n, str);
7049 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
7052 gunichar2 *utf16_name, *utf16_value;
7054 gchar *utf8_name, *utf8_value;
7059 utf16_name = mono_string_to_utf16 (name);
7060 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7061 SetEnvironmentVariable (utf16_name, NULL);
7062 g_free (utf16_name);
7066 utf16_value = mono_string_to_utf16 (value);
7068 SetEnvironmentVariable (utf16_name, utf16_value);
7070 g_free (utf16_name);
7071 g_free (utf16_value);
7073 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
7074 if (mono_error_set_pending_exception (&error))
7077 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7078 g_unsetenv (utf8_name);
7083 utf8_value = mono_string_to_utf8_checked (value, &error);
7084 if (!mono_error_ok (&error)) {
7086 mono_error_set_pending_exception (&error);
7089 g_setenv (utf8_name, utf8_value, TRUE);
7092 g_free (utf8_value);
7097 ves_icall_System_Environment_Exit (int result)
7099 mono_environment_exitcode_set (result);
7101 /* FIXME: There are some cleanup hangs that should be worked out, but
7102 * if the program is going to exit, everything will be cleaned up when
7103 * NaCl exits anyway.
7105 #ifndef __native_client__
7106 if (!mono_runtime_try_shutdown ())
7107 mono_thread_exit ();
7109 /* Suspend all managed threads since the runtime is going away */
7110 mono_thread_suspend_all_other_threads ();
7112 mono_runtime_quit ();
7115 /* we may need to do some cleanup here... */
7119 ICALL_EXPORT MonoString*
7120 ves_icall_System_Environment_GetGacPath (void)
7122 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
7125 ICALL_EXPORT MonoString*
7126 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
7128 #if defined (HOST_WIN32)
7129 #ifndef CSIDL_FLAG_CREATE
7130 #define CSIDL_FLAG_CREATE 0x8000
7133 WCHAR path [MAX_PATH];
7134 /* Create directory if no existing */
7135 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
7140 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
7141 mono_error_set_pending_exception (&error);
7145 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7147 return mono_string_new (mono_domain_get (), "");
7150 ICALL_EXPORT MonoArray *
7151 ves_icall_System_Environment_GetLogicalDrives (void)
7154 gunichar2 buf [256], *ptr, *dname;
7156 guint initial_size = 127, size = 128;
7159 MonoString *drivestr;
7160 MonoDomain *domain = mono_domain_get ();
7166 while (size > initial_size) {
7167 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
7168 if (size > initial_size) {
7171 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7172 initial_size = size;
7186 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7187 if (mono_error_set_pending_exception (&error))
7194 while (*u16) { u16++; len ++; }
7195 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7196 if (mono_error_set_pending_exception (&error))
7199 mono_array_setref (result, ndrives++, drivestr);
7210 ICALL_EXPORT MonoString *
7211 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7214 gunichar2 volume_name [MAX_PATH + 1];
7216 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7218 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
7219 mono_error_set_pending_exception (&error);
7223 ICALL_EXPORT MonoString *
7224 ves_icall_System_Environment_InternalGetHome (void)
7226 return mono_string_new (mono_domain_get (), g_get_home_dir ());
7229 static const char *encodings [] = {
7231 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7232 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7233 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7235 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7236 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7237 "x_unicode_2_0_utf_7",
7239 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7240 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7242 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7245 "unicodefffe", "utf_16be",
7252 * Returns the internal codepage, if the value of "int_code_page" is
7253 * 1 at entry, and we can not compute a suitable code page number,
7254 * returns the code page as a string
7256 ICALL_EXPORT MonoString*
7257 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
7262 char *codepage = NULL;
7264 int want_name = *int_code_page;
7267 *int_code_page = -1;
7269 g_get_charset (&cset);
7270 c = codepage = strdup (cset);
7271 for (c = codepage; *c; c++){
7272 if (isascii (*c) && isalpha (*c))
7277 /* g_print ("charset: %s\n", cset); */
7279 /* handle some common aliases */
7282 for (i = 0; p != 0; ){
7285 p = encodings [++i];
7288 if (strcmp (p, codepage) == 0){
7289 *int_code_page = code;
7292 p = encodings [++i];
7295 if (strstr (codepage, "utf_8") != NULL)
7296 *int_code_page |= 0x10000000;
7299 if (want_name && *int_code_page == -1)
7300 return mono_string_new (mono_domain_get (), cset);
7305 ICALL_EXPORT MonoBoolean
7306 ves_icall_System_Environment_get_HasShutdownStarted (void)
7308 if (mono_runtime_is_shutting_down ())
7311 if (mono_domain_is_unloading (mono_domain_get ()))
7318 ves_icall_System_Environment_BroadcastSettingChange (void)
7321 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7327 ves_icall_System_Environment_get_TickCount (void)
7329 /* this will overflow after ~24 days */
7330 return (gint32) (mono_msec_boottime () & 0xffffffff);
7334 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7339 #ifndef DISABLE_REMOTING
7340 ICALL_EXPORT MonoBoolean
7341 ves_icall_IsTransparentProxy (MonoObject *proxy)
7346 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7352 ICALL_EXPORT MonoReflectionMethod *
7353 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7354 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7356 MonoReflectionMethod *ret = NULL;
7361 MonoMethod **vtable;
7362 MonoMethod *res = NULL;
7364 MONO_CHECK_ARG_NULL (rtype, NULL);
7365 MONO_CHECK_ARG_NULL (rmethod, NULL);
7367 method = rmethod->method;
7368 klass = mono_class_from_mono_type (rtype->type);
7369 mono_class_init_checked (klass, &error);
7370 if (mono_error_set_pending_exception (&error))
7373 if (MONO_CLASS_IS_INTERFACE (klass))
7376 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7379 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7380 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7386 mono_class_setup_vtable (klass);
7387 vtable = klass->vtable;
7389 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7390 gboolean variance_used = FALSE;
7391 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7392 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7394 res = vtable [offs + method->slot];
7396 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7399 if (method->slot != -1)
7400 res = vtable [method->slot];
7406 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7407 mono_error_set_pending_exception (&error);
7412 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7418 klass = mono_class_from_mono_type (type->type);
7419 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7420 if (!is_ok (&error)) {
7421 mono_error_set_pending_exception (&error);
7425 mono_vtable_set_is_remote (vtable, enable);
7428 #else /* DISABLE_REMOTING */
7431 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7433 g_assert_not_reached ();
7438 ICALL_EXPORT MonoObject *
7439 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7446 domain = mono_object_domain (type);
7447 klass = mono_class_from_mono_type (type->type);
7448 mono_class_init_checked (klass, &error);
7449 if (mono_error_set_pending_exception (&error))
7452 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7453 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7457 if (klass->rank >= 1) {
7458 g_assert (klass->rank == 1);
7459 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7460 mono_error_set_pending_exception (&error);
7463 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7464 if (!is_ok (&error)) {
7465 mono_error_set_pending_exception (&error);
7468 /* Bypass remoting object creation check */
7469 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7470 mono_error_set_pending_exception (&error);
7476 ICALL_EXPORT MonoString *
7477 ves_icall_System_IO_get_temp_path (void)
7479 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7482 #ifndef PLATFORM_NO_DRIVEINFO
7483 ICALL_EXPORT MonoBoolean
7484 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7485 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7489 ULARGE_INTEGER wapi_free_bytes_avail;
7490 ULARGE_INTEGER wapi_total_number_of_bytes;
7491 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7493 *error = ERROR_SUCCESS;
7494 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7495 &wapi_total_number_of_free_bytes);
7498 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7499 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7500 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7502 *free_bytes_avail = 0;
7503 *total_number_of_bytes = 0;
7504 *total_number_of_free_bytes = 0;
7505 *error = GetLastError ();
7511 ICALL_EXPORT guint32
7512 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7514 return GetDriveType (mono_string_chars (root_path_name));
7518 ICALL_EXPORT gpointer
7519 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7522 gpointer result = mono_compile_method_checked (method, &error);
7523 mono_error_set_pending_exception (&error);
7527 ICALL_EXPORT MonoString *
7528 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7533 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7535 #if defined (HOST_WIN32)
7536 /* Avoid mixing '/' and '\\' */
7539 for (i = strlen (path) - 1; i >= 0; i--)
7540 if (path [i] == '/')
7544 mcpath = mono_string_new (mono_domain_get (), path);
7550 /* this is an icall */
7552 get_bundled_app_config (void)
7555 const gchar *app_config;
7558 gchar *config_file_name, *config_file_path;
7559 gsize len, config_file_path_length, config_ext_length;
7562 domain = mono_domain_get ();
7563 file = domain->setup->configuration_file;
7564 if (!file || file->length == 0)
7567 // Retrieve config file and remove the extension
7568 config_file_name = mono_string_to_utf8_checked (file, &error);
7569 if (mono_error_set_pending_exception (&error))
7571 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7572 if (!config_file_path)
7573 config_file_path = config_file_name;
7575 config_file_path_length = strlen (config_file_path);
7576 config_ext_length = strlen (".config");
7577 if (config_file_path_length <= config_ext_length)
7580 len = config_file_path_length - config_ext_length;
7581 module = (gchar *)g_malloc0 (len + 1);
7582 memcpy (module, config_file_path, len);
7583 // Get the config file from the module name
7584 app_config = mono_config_string_for_assembly_file (module);
7587 if (config_file_name != config_file_path)
7588 g_free (config_file_name);
7589 g_free (config_file_path);
7594 return mono_string_new (mono_domain_get (), app_config);
7598 get_bundled_machine_config (void)
7600 const gchar *machine_config;
7602 machine_config = mono_get_machine_config ();
7604 if (!machine_config)
7607 return mono_string_new (mono_domain_get (), machine_config);
7610 ICALL_EXPORT MonoString *
7611 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7616 path = g_path_get_dirname (mono_get_config_dir ());
7618 #if defined (HOST_WIN32)
7619 /* Avoid mixing '/' and '\\' */
7622 for (i = strlen (path) - 1; i >= 0; i--)
7623 if (path [i] == '/')
7627 ipath = mono_string_new (mono_domain_get (), path);
7633 ICALL_EXPORT gboolean
7634 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7636 MonoPEResourceDataEntry *entry;
7639 if (!assembly || !result || !size)
7644 image = assembly->assembly->image;
7645 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7649 *result = mono_image_rva_map (image, entry->rde_data_offset);
7654 *size = entry->rde_size;
7659 ICALL_EXPORT MonoBoolean
7660 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7662 return mono_is_debugger_attached ();
7665 ICALL_EXPORT MonoBoolean
7666 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7668 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7669 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7675 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7677 if (mono_get_runtime_callbacks ()->debug_log)
7678 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7682 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7684 #if defined (HOST_WIN32)
7685 OutputDebugString (mono_string_chars (message));
7687 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7691 /* Only used for value types */
7692 ICALL_EXPORT MonoObject *
7693 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7700 domain = mono_object_domain (type);
7701 klass = mono_class_from_mono_type (type->type);
7702 mono_class_init_checked (klass, &error);
7703 if (mono_error_set_pending_exception (&error))
7706 if (mono_class_is_nullable (klass))
7707 /* No arguments -> null */
7710 result = mono_object_new_checked (domain, klass, &error);
7711 mono_error_set_pending_exception (&error);
7715 ICALL_EXPORT MonoReflectionMethod *
7716 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7718 MonoReflectionMethod *ret = NULL;
7721 MonoClass *klass, *parent;
7722 MonoGenericContext *generic_inst = NULL;
7723 MonoMethod *method = m->method;
7724 MonoMethod *result = NULL;
7727 if (method->klass == NULL)
7730 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7731 MONO_CLASS_IS_INTERFACE (method->klass) ||
7732 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7735 slot = mono_method_get_vtable_slot (method);
7739 klass = method->klass;
7740 if (klass->generic_class) {
7741 generic_inst = mono_class_get_context (klass);
7742 klass = klass->generic_class->container_class;
7746 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7747 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7748 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7749 or klass is the generic container class and generic_inst is the instantiation.
7751 when we go to the parent, if the parent is an open constructed type, we need to
7752 replace the type parameters by the definitions from the generic_inst, and then take it
7753 apart again into the klass and the generic_inst.
7755 For cases like this:
7756 class C<T> : B<T, int> {
7757 public override void Foo () { ... }
7759 class B<U,V> : A<HashMap<U,V>> {
7760 public override void Foo () { ... }
7763 public virtual void Foo () { ... }
7766 if at each iteration the parent isn't open, we can skip inflating it. if at some
7767 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7770 MonoGenericContext *parent_inst = NULL;
7771 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7772 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7773 if (!mono_error_ok (&error)) {
7774 mono_error_set_pending_exception (&error);
7778 if (parent->generic_class) {
7779 parent_inst = mono_class_get_context (parent);
7780 parent = parent->generic_class->container_class;
7783 mono_class_setup_vtable (parent);
7784 if (parent->vtable_size <= slot)
7787 generic_inst = parent_inst;
7790 klass = klass->parent;
7793 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7794 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7795 if (!mono_error_ok (&error)) {
7796 mono_error_set_pending_exception (&error);
7800 generic_inst = NULL;
7802 if (klass->generic_class) {
7803 generic_inst = mono_class_get_context (klass);
7804 klass = klass->generic_class->container_class;
7810 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7811 if (!mono_error_ok (&error)) {
7812 mono_error_set_pending_exception (&error);
7817 if (klass == method->klass)
7820 /*This is possible if definition == FALSE.
7821 * Do it here to be really sure we don't read invalid memory.
7823 if (slot >= klass->vtable_size)
7826 mono_class_setup_vtable (klass);
7828 result = klass->vtable [slot];
7829 if (result == NULL) {
7830 /* It is an abstract method */
7831 gpointer iter = NULL;
7832 while ((result = mono_class_get_methods (klass, &iter)))
7833 if (result->slot == slot)
7840 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7841 mono_error_set_pending_exception (&error);
7845 ICALL_EXPORT MonoString*
7846 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7848 MonoMethod *method = m->method;
7850 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7855 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7857 iter->sig = *(MonoMethodSignature**)argsp;
7859 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7860 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7863 /* FIXME: it's not documented what start is exactly... */
7867 iter->args = argsp + sizeof (gpointer);
7869 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7871 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7874 ICALL_EXPORT MonoTypedRef
7875 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7877 guint32 i, arg_size;
7881 i = iter->sig->sentinelpos + iter->next_arg;
7883 g_assert (i < iter->sig->param_count);
7885 res.type = iter->sig->params [i];
7886 res.klass = mono_class_from_mono_type (res.type);
7887 arg_size = mono_type_stack_size (res.type, &align);
7888 #if defined(__arm__) || defined(__mips__)
7889 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7891 res.value = iter->args;
7892 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7893 /* Values are stored as 8 byte register sized objects, but 'value'
7894 * is dereferenced as a pointer in other routines.
7896 res.value = (char*)res.value + 4;
7898 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7899 if (arg_size <= sizeof (gpointer)) {
7901 int padding = arg_size - mono_type_size (res.type, &dummy);
7902 res.value = (guint8*)res.value + padding;
7905 iter->args = (char*)iter->args + arg_size;
7908 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7913 ICALL_EXPORT MonoTypedRef
7914 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7916 guint32 i, arg_size;
7920 i = iter->sig->sentinelpos + iter->next_arg;
7922 g_assert (i < iter->sig->param_count);
7924 while (i < iter->sig->param_count) {
7925 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7927 res.type = iter->sig->params [i];
7928 res.klass = mono_class_from_mono_type (res.type);
7929 /* FIXME: endianess issue... */
7930 arg_size = mono_type_stack_size (res.type, &align);
7931 #if defined(__arm__) || defined(__mips__)
7932 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7934 res.value = iter->args;
7935 iter->args = (char*)iter->args + arg_size;
7937 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7940 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7948 ICALL_EXPORT MonoType*
7949 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7953 i = iter->sig->sentinelpos + iter->next_arg;
7955 g_assert (i < iter->sig->param_count);
7957 return iter->sig->params [i];
7960 ICALL_EXPORT MonoObject*
7961 mono_TypedReference_ToObject (MonoTypedRef* tref)
7964 MonoObject *result = NULL;
7965 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7966 MonoObject** objp = (MonoObject **)tref->value;
7970 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7971 mono_error_set_pending_exception (&error);
7975 ICALL_EXPORT MonoTypedRef
7976 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7979 MonoReflectionField *f;
7981 MonoType *ftype = NULL;
7985 memset (&res, 0, sizeof (res));
7988 g_assert (mono_array_length (fields) > 0);
7990 klass = target->vtable->klass;
7992 for (i = 0; i < mono_array_length (fields); ++i) {
7993 f = mono_array_get (fields, MonoReflectionField*, i);
7995 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7998 if (f->field->parent != klass) {
7999 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
8003 p = (guint8*)target + f->field->offset;
8005 p += f->field->offset - sizeof (MonoObject);
8006 klass = mono_class_from_mono_type (f->field->type);
8007 ftype = f->field->type;
8011 res.klass = mono_class_from_mono_type (ftype);
8018 prelink_method (MonoMethod *method, MonoError *error)
8020 const char *exc_class, *exc_arg;
8022 mono_error_init (error);
8023 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
8025 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
8027 mono_error_set_exception_instance (error,
8028 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
8031 /* create the wrapper, too? */
8035 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
8039 prelink_method (method->method, &error);
8040 mono_error_set_pending_exception (&error);
8044 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
8047 MonoClass *klass = mono_class_from_mono_type (type->type);
8049 gpointer iter = NULL;
8051 mono_class_init_checked (klass, &error);
8052 if (mono_error_set_pending_exception (&error))
8055 while ((m = mono_class_get_methods (klass, &iter))) {
8056 prelink_method (m, &error);
8057 if (mono_error_set_pending_exception (&error))
8062 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
8064 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
8065 gint32 const **exponents,
8066 gunichar2 const **digitLowerTable,
8067 gunichar2 const **digitUpperTable,
8068 gint64 const **tenPowersList,
8069 gint32 const **decHexDigits)
8071 *mantissas = Formatter_MantissaBitsTable;
8072 *exponents = Formatter_TensExponentTable;
8073 *digitLowerTable = Formatter_DigitLowerTable;
8074 *digitUpperTable = Formatter_DigitUpperTable;
8075 *tenPowersList = Formatter_TenPowersList;
8076 *decHexDigits = Formatter_DecHexDigits;
8080 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
8081 * and avoid useless allocations.
8084 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
8086 MonoReflectionType *rt;
8090 mono_error_init (error);
8091 for (i = 0; i < type->num_mods; ++i) {
8092 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
8097 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
8098 return_val_if_nok (error, NULL);
8100 for (i = 0; i < type->num_mods; ++i) {
8101 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
8102 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
8103 return_val_if_nok (error, NULL);
8105 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8106 return_val_if_nok (error, NULL);
8108 mono_array_setref (res, count, rt);
8115 ICALL_EXPORT MonoArray*
8116 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
8119 MonoType *type = param->ClassImpl->type;
8120 MonoClass *member_class = mono_object_class (param->MemberImpl);
8121 MonoMethod *method = NULL;
8124 MonoMethodSignature *sig;
8127 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8128 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8129 method = rmethod->method;
8130 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
8131 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8132 if (!(method = prop->property->get))
8133 method = prop->property->set;
8136 char *type_name = mono_type_get_full_name (member_class);
8137 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
8138 MonoException *ex = mono_get_exception_not_supported (msg);
8141 mono_set_pending_exception (ex);
8145 image = method->klass->image;
8146 pos = param->PositionImpl;
8147 sig = mono_method_signature (method);
8151 type = sig->params [pos];
8153 res = type_array_from_modifiers (image, type, optional, &error);
8154 mono_error_set_pending_exception (&error);
8159 get_property_type (MonoProperty *prop)
8161 MonoMethodSignature *sig;
8163 sig = mono_method_signature (prop->get);
8165 } else if (prop->set) {
8166 sig = mono_method_signature (prop->set);
8167 return sig->params [sig->param_count - 1];
8172 ICALL_EXPORT MonoArray*
8173 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
8176 MonoType *type = get_property_type (property->property);
8177 MonoImage *image = property->klass->image;
8182 res = type_array_from_modifiers (image, type, optional, &error);
8183 mono_error_set_pending_exception (&error);
8188 *Construct a MonoType suited to be used to decode a constant blob object.
8190 * @type is the target type which will be constructed
8191 * @blob_type is the blob type, for example, that comes from the constant table
8192 * @real_type is the expected constructed type.
8195 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8197 type->type = blob_type;
8198 type->data.klass = NULL;
8199 if (blob_type == MONO_TYPE_CLASS)
8200 type->data.klass = mono_defaults.object_class;
8201 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8202 /* For enums, we need to use the base type */
8203 type->type = MONO_TYPE_VALUETYPE;
8204 type->data.klass = mono_class_from_mono_type (real_type);
8206 type->data.klass = mono_class_from_mono_type (real_type);
8209 ICALL_EXPORT MonoObject*
8210 property_info_get_default_value (MonoReflectionProperty *property)
8214 MonoProperty *prop = property->property;
8215 MonoType *type = get_property_type (prop);
8216 MonoDomain *domain = mono_object_domain (property);
8217 MonoTypeEnum def_type;
8218 const char *def_value;
8221 mono_class_init (prop->parent);
8223 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8224 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8228 def_value = mono_class_get_property_default_value (prop, &def_type);
8230 mono_type_from_blob_type (&blob_type, def_type, type);
8231 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8233 mono_error_set_pending_exception (&error);
8237 ICALL_EXPORT MonoBoolean
8238 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8241 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8242 MonoCustomAttrInfo *cinfo;
8245 mono_class_init_checked (attr_class, &error);
8246 if (mono_error_set_pending_exception (&error))
8249 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8250 if (!is_ok (&error)) {
8251 mono_error_set_pending_exception (&error);
8256 found = mono_custom_attrs_has_attr (cinfo, attr_class);
8258 mono_custom_attrs_free (cinfo);
8262 ICALL_EXPORT MonoArray*
8263 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8265 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8270 mono_class_init_checked (attr_class, &error);
8271 if (mono_error_set_pending_exception (&error))
8275 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8276 if (!mono_error_ok (&error)) {
8277 mono_error_set_pending_exception (&error);
8284 ICALL_EXPORT MonoArray*
8285 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8289 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8290 mono_error_set_pending_exception (&error);
8295 ICALL_EXPORT MonoString*
8296 ves_icall_Mono_Runtime_GetDisplayName (void)
8299 MonoString *display_name;
8301 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8302 display_name = mono_string_new (mono_domain_get (), info);
8304 return display_name;
8307 ICALL_EXPORT MonoString*
8308 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8311 MonoString *message;
8315 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8316 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8319 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8321 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8322 if (mono_error_set_pending_exception (&error))
8329 ICALL_EXPORT gpointer
8330 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8332 return GetCurrentProcess ();
8335 ICALL_EXPORT MonoBoolean
8336 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8338 return GetExitCodeProcess (handle, (guint32*) exitcode);
8341 ICALL_EXPORT MonoBoolean
8342 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8344 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8345 return CloseHandle (handle);
8347 return CloseProcess (handle);
8351 ICALL_EXPORT MonoBoolean
8352 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8354 return TerminateProcess (handle, exitcode);
8358 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8360 return WaitForInputIdle (handle, milliseconds);
8363 ICALL_EXPORT MonoBoolean
8364 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8366 return GetProcessWorkingSetSize (handle, min, max);
8369 ICALL_EXPORT MonoBoolean
8370 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8372 return SetProcessWorkingSetSize (handle, min, max);
8375 ICALL_EXPORT MonoBoolean
8376 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8378 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8382 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8384 return mono_process_current_pid ();
8388 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8390 return GetPriorityClass (handle);
8393 ICALL_EXPORT MonoBoolean
8394 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8396 return SetPriorityClass (handle, priorityClass);
8399 #ifndef DISABLE_ICALL_TABLES
8401 #define ICALL_TYPE(id,name,first)
8402 #define ICALL(id,name,func) Icall_ ## id,
8405 #include "metadata/icall-def.h"
8411 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8412 #define ICALL(id,name,func)
8414 #include "metadata/icall-def.h"
8420 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8421 #define ICALL(id,name,func)
8423 guint16 first_icall;
8426 static const IcallTypeDesc
8427 icall_type_descs [] = {
8428 #include "metadata/icall-def.h"
8432 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8435 #define ICALL_TYPE(id,name,first)
8438 #ifdef HAVE_ARRAY_ELEM_INIT
8439 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8440 #define MSGSTRFIELD1(line) str##line
8442 static const struct msgstrtn_t {
8443 #define ICALL(id,name,func)
8445 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8446 #include "metadata/icall-def.h"
8448 } icall_type_names_str = {
8449 #define ICALL_TYPE(id,name,first) (name),
8450 #include "metadata/icall-def.h"
8453 static const guint16 icall_type_names_idx [] = {
8454 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8455 #include "metadata/icall-def.h"
8458 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8460 static const struct msgstr_t {
8462 #define ICALL_TYPE(id,name,first)
8463 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8464 #include "metadata/icall-def.h"
8466 } icall_names_str = {
8467 #define ICALL(id,name,func) (name),
8468 #include "metadata/icall-def.h"
8471 static const guint16 icall_names_idx [] = {
8472 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8473 #include "metadata/icall-def.h"
8476 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8482 #define ICALL_TYPE(id,name,first) name,
8483 #define ICALL(id,name,func)
8484 static const char* const
8485 icall_type_names [] = {
8486 #include "metadata/icall-def.h"
8490 #define icall_type_name_get(id) (icall_type_names [(id)])
8494 #define ICALL_TYPE(id,name,first)
8495 #define ICALL(id,name,func) name,
8496 static const char* const
8498 #include "metadata/icall-def.h"
8501 #define icall_name_get(id) icall_names [(id)]
8503 #endif /* !HAVE_ARRAY_ELEM_INIT */
8507 #define ICALL_TYPE(id,name,first)
8508 #define ICALL(id,name,func) func,
8509 static const gconstpointer
8510 icall_functions [] = {
8511 #include "metadata/icall-def.h"
8515 #ifdef ENABLE_ICALL_SYMBOL_MAP
8518 #define ICALL_TYPE(id,name,first)
8519 #define ICALL(id,name,func) #func,
8520 static const gconstpointer
8521 icall_symbols [] = {
8522 #include "metadata/icall-def.h"
8527 #endif /* DISABLE_ICALL_TABLES */
8529 static mono_mutex_t icall_mutex;
8530 static GHashTable *icall_hash = NULL;
8531 static GHashTable *jit_icall_hash_name = NULL;
8532 static GHashTable *jit_icall_hash_addr = NULL;
8535 mono_icall_init (void)
8537 #ifndef DISABLE_ICALL_TABLES
8540 /* check that tables are sorted: disable in release */
8543 const char *prev_class = NULL;
8544 const char *prev_method;
8546 for (i = 0; i < Icall_type_num; ++i) {
8547 const IcallTypeDesc *desc;
8550 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8551 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8552 prev_class = icall_type_name_get (i);
8553 desc = &icall_type_descs [i];
8554 num_icalls = icall_desc_num_icalls (desc);
8555 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8556 for (j = 0; j < num_icalls; ++j) {
8557 const char *methodn = icall_name_get (desc->first_icall + j);
8558 if (prev_method && strcmp (prev_method, methodn) >= 0)
8559 g_print ("method %s should come before method %s\n", methodn, prev_method);
8560 prev_method = methodn;
8566 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8567 mono_os_mutex_init (&icall_mutex);
8571 mono_icall_lock (void)
8573 mono_locks_os_acquire (&icall_mutex, IcallLock);
8577 mono_icall_unlock (void)
8579 mono_locks_os_release (&icall_mutex, IcallLock);
8583 mono_icall_cleanup (void)
8585 g_hash_table_destroy (icall_hash);
8586 g_hash_table_destroy (jit_icall_hash_name);
8587 g_hash_table_destroy (jit_icall_hash_addr);
8588 mono_os_mutex_destroy (&icall_mutex);
8592 * mono_add_internal_call:
8593 * @name: method specification to surface to the managed world
8594 * @method: pointer to a C method to invoke when the method is called
8596 * This method surfaces the C function pointed by @method as a method
8597 * that has been surfaced in managed code with the method specified in
8598 * @name as an internal call.
8600 * Internal calls are surfaced to all app domains loaded and they are
8601 * accessibly by a type with the specified name.
8603 * You must provide a fully qualified type name, that is namespaces
8604 * and type name, followed by a colon and the method name, with an
8605 * optional signature to bind.
8607 * For example, the following are all valid declarations:
8609 * "MyApp.Services.ScriptService:Accelerate"
8610 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8612 * You use method parameters in cases where there might be more than
8613 * one surface method to managed code. That way you can register different
8614 * internal calls for different method overloads.
8616 * The internal calls are invoked with no marshalling. This means that .NET
8617 * types like System.String are exposed as `MonoString *` parameters. This is
8618 * different than the way that strings are surfaced in P/Invoke.
8620 * For more information on how the parameters are marshalled, see the
8621 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8624 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8625 * reference for more information on the format of method descriptions.
8628 mono_add_internal_call (const char *name, gconstpointer method)
8632 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8634 mono_icall_unlock ();
8637 #ifndef DISABLE_ICALL_TABLES
8639 #ifdef HAVE_ARRAY_ELEM_INIT
8641 compare_method_imap (const void *key, const void *elem)
8643 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8644 return strcmp (key, method_name);
8648 find_method_icall (const IcallTypeDesc *imap, const char *name)
8650 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);
8653 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8657 compare_class_imap (const void *key, const void *elem)
8659 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8660 return strcmp (key, class_name);
8663 static const IcallTypeDesc*
8664 find_class_icalls (const char *name)
8666 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);
8669 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8672 #else /* HAVE_ARRAY_ELEM_INIT */
8675 compare_method_imap (const void *key, const void *elem)
8677 const char** method_name = (const char**)elem;
8678 return strcmp (key, *method_name);
8682 find_method_icall (const IcallTypeDesc *imap, const char *name)
8684 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8687 return (gpointer)icall_functions [(nameslot - icall_names)];
8691 compare_class_imap (const void *key, const void *elem)
8693 const char** class_name = (const char**)elem;
8694 return strcmp (key, *class_name);
8697 static const IcallTypeDesc*
8698 find_class_icalls (const char *name)
8700 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8703 return &icall_type_descs [nameslot - icall_type_names];
8706 #endif /* HAVE_ARRAY_ELEM_INIT */
8708 #endif /* DISABLE_ICALL_TABLES */
8711 * we should probably export this as an helper (handle nested types).
8712 * Returns the number of chars written in buf.
8715 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8717 int nspacelen, cnamelen;
8718 nspacelen = strlen (klass->name_space);
8719 cnamelen = strlen (klass->name);
8720 if (nspacelen + cnamelen + 2 > bufsize)
8723 memcpy (buf, klass->name_space, nspacelen);
8724 buf [nspacelen ++] = '.';
8726 memcpy (buf + nspacelen, klass->name, cnamelen);
8727 buf [nspacelen + cnamelen] = 0;
8728 return nspacelen + cnamelen;
8731 #ifdef DISABLE_ICALL_TABLES
8733 no_icall_table (void)
8735 g_assert_not_reached ();
8740 mono_lookup_internal_call (MonoMethod *method)
8745 int typelen = 0, mlen, siglen;
8747 #ifndef DISABLE_ICALL_TABLES
8748 const IcallTypeDesc *imap = NULL;
8751 g_assert (method != NULL);
8753 if (method->is_inflated)
8754 method = ((MonoMethodInflated *) method)->declaring;
8756 if (method->klass->nested_in) {
8757 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8761 mname [pos++] = '/';
8764 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8770 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8775 #ifndef DISABLE_ICALL_TABLES
8776 imap = find_class_icalls (mname);
8779 mname [typelen] = ':';
8780 mname [typelen + 1] = ':';
8782 mlen = strlen (method->name);
8783 memcpy (mname + typelen + 2, method->name, mlen);
8784 sigstart = mname + typelen + 2 + mlen;
8787 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8788 siglen = strlen (tmpsig);
8789 if (typelen + mlen + siglen + 6 > sizeof (mname))
8792 memcpy (sigstart + 1, tmpsig, siglen);
8793 sigstart [siglen + 1] = ')';
8794 sigstart [siglen + 2] = 0;
8799 res = g_hash_table_lookup (icall_hash, mname);
8801 mono_icall_unlock ();;
8804 /* try without signature */
8806 res = g_hash_table_lookup (icall_hash, mname);
8808 mono_icall_unlock ();
8812 #ifdef DISABLE_ICALL_TABLES
8813 mono_icall_unlock ();
8814 /* Fail only when the result is actually used */
8815 /* mono_marshal_get_native_wrapper () depends on this */
8816 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8817 return ves_icall_System_String_ctor_RedirectToCreateString;
8819 return no_icall_table;
8821 /* it wasn't found in the static call tables */
8823 mono_icall_unlock ();
8826 res = find_method_icall (imap, sigstart - mlen);
8828 mono_icall_unlock ();
8831 /* try _with_ signature */
8833 res = find_method_icall (imap, sigstart - mlen);
8835 mono_icall_unlock ();
8839 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8840 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8841 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8842 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8843 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");
8844 g_print ("If you see other errors or faults after this message they are probably related\n");
8845 g_print ("and you need to fix your mono install first.\n");
8847 mono_icall_unlock ();
8853 #ifdef ENABLE_ICALL_SYMBOL_MAP
8855 func_cmp (gconstpointer key, gconstpointer p)
8857 return (gsize)key - (gsize)*(gsize*)p;
8862 * mono_lookup_icall_symbol:
8864 * Given the icall METHOD, returns its C symbol.
8867 mono_lookup_icall_symbol (MonoMethod *m)
8869 #ifdef DISABLE_ICALL_TABLES
8870 g_assert_not_reached ();
8873 #ifdef ENABLE_ICALL_SYMBOL_MAP
8877 static gconstpointer *functions_sorted;
8878 static const char**symbols_sorted;
8879 static gboolean inited;
8884 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8885 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8886 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8887 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8888 /* Bubble sort the two arrays */
8892 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8893 if (functions_sorted [i] > functions_sorted [i + 1]) {
8896 tmp = functions_sorted [i];
8897 functions_sorted [i] = functions_sorted [i + 1];
8898 functions_sorted [i + 1] = tmp;
8899 tmp = symbols_sorted [i];
8900 symbols_sorted [i] = symbols_sorted [i + 1];
8901 symbols_sorted [i + 1] = tmp;
8908 func = mono_lookup_internal_call (m);
8911 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8915 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8917 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8918 g_assert_not_reached ();
8925 type_from_typename (char *type_name)
8927 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8929 if (!strcmp (type_name, "int"))
8930 klass = mono_defaults.int_class;
8931 else if (!strcmp (type_name, "ptr"))
8932 klass = mono_defaults.int_class;
8933 else if (!strcmp (type_name, "void"))
8934 klass = mono_defaults.void_class;
8935 else if (!strcmp (type_name, "int32"))
8936 klass = mono_defaults.int32_class;
8937 else if (!strcmp (type_name, "uint32"))
8938 klass = mono_defaults.uint32_class;
8939 else if (!strcmp (type_name, "int8"))
8940 klass = mono_defaults.sbyte_class;
8941 else if (!strcmp (type_name, "uint8"))
8942 klass = mono_defaults.byte_class;
8943 else if (!strcmp (type_name, "int16"))
8944 klass = mono_defaults.int16_class;
8945 else if (!strcmp (type_name, "uint16"))
8946 klass = mono_defaults.uint16_class;
8947 else if (!strcmp (type_name, "long"))
8948 klass = mono_defaults.int64_class;
8949 else if (!strcmp (type_name, "ulong"))
8950 klass = mono_defaults.uint64_class;
8951 else if (!strcmp (type_name, "float"))
8952 klass = mono_defaults.single_class;
8953 else if (!strcmp (type_name, "double"))
8954 klass = mono_defaults.double_class;
8955 else if (!strcmp (type_name, "object"))
8956 klass = mono_defaults.object_class;
8957 else if (!strcmp (type_name, "obj"))
8958 klass = mono_defaults.object_class;
8959 else if (!strcmp (type_name, "string"))
8960 klass = mono_defaults.string_class;
8961 else if (!strcmp (type_name, "bool"))
8962 klass = mono_defaults.boolean_class;
8963 else if (!strcmp (type_name, "boolean"))
8964 klass = mono_defaults.boolean_class;
8966 g_error ("%s", type_name);
8967 g_assert_not_reached ();
8969 return &klass->byval_arg;
8973 * LOCKING: Take the corlib image lock.
8975 MonoMethodSignature*
8976 mono_create_icall_signature (const char *sigstr)
8981 MonoMethodSignature *res, *res2;
8982 MonoImage *corlib = mono_defaults.corlib;
8984 mono_image_lock (corlib);
8985 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8986 mono_image_unlock (corlib);
8991 parts = g_strsplit (sigstr, " ", 256);
9000 res = mono_metadata_signature_alloc (corlib, len - 1);
9005 * Under windows, the default pinvoke calling convention is STDCALL but
9008 res->call_convention = MONO_CALL_C;
9011 res->ret = type_from_typename (parts [0]);
9012 for (i = 1; i < len; ++i) {
9013 res->params [i - 1] = type_from_typename (parts [i]);
9018 mono_image_lock (corlib);
9019 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
9021 res = res2; /*Value is allocated in the image pool*/
9023 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
9024 mono_image_unlock (corlib);
9030 mono_find_jit_icall_by_name (const char *name)
9032 MonoJitICallInfo *info;
9033 g_assert (jit_icall_hash_name);
9036 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9037 mono_icall_unlock ();
9042 mono_find_jit_icall_by_addr (gconstpointer addr)
9044 MonoJitICallInfo *info;
9045 g_assert (jit_icall_hash_addr);
9048 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
9049 mono_icall_unlock ();
9055 * mono_get_jit_icall_info:
9057 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
9058 * caller should access it while holding the icall lock.
9061 mono_get_jit_icall_info (void)
9063 return jit_icall_hash_name;
9067 * mono_lookup_jit_icall_symbol:
9069 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
9072 mono_lookup_jit_icall_symbol (const char *name)
9074 MonoJitICallInfo *info;
9075 const char *res = NULL;
9078 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9080 res = info->c_symbol;
9081 mono_icall_unlock ();
9086 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
9089 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
9090 mono_icall_unlock ();
9094 * 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
9095 * icalls without wrappers in some cases.
9098 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
9100 MonoJitICallInfo *info;
9107 if (!jit_icall_hash_name) {
9108 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
9109 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
9112 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
9113 g_warning ("jit icall already defined \"%s\"\n", name);
9114 g_assert_not_reached ();
9117 info = g_new0 (MonoJitICallInfo, 1);
9122 info->c_symbol = c_symbol;
9123 info->no_raise = no_raise;
9126 info->wrapper = func;
9128 info->wrapper = NULL;
9131 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
9132 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
9134 mono_icall_unlock ();
9139 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
9141 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);