5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
9 * Aleksey Kliger (aleksey@xamarin.com)
11 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
12 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
14 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
25 #ifdef HAVE_SYS_TIME_H
31 #if defined (HOST_WIN32)
34 #if defined (HAVE_WCHAR_H)
38 #include "mono/utils/mono-membar.h"
39 #include <mono/metadata/object.h>
40 #include <mono/metadata/threads.h>
41 #include <mono/metadata/threads-types.h>
42 #include <mono/metadata/threadpool-ms.h>
43 #include <mono/metadata/threadpool-ms-io.h>
44 #include <mono/metadata/monitor.h>
45 #include <mono/metadata/reflection.h>
46 #include <mono/metadata/assembly.h>
47 #include <mono/metadata/tabledefs.h>
48 #include <mono/metadata/exception.h>
49 #include <mono/metadata/exception-internals.h>
50 #include <mono/metadata/file-io.h>
51 #include <mono/metadata/console-io.h>
52 #include <mono/metadata/mono-route.h>
53 #include <mono/metadata/socket-io.h>
54 #include <mono/metadata/mono-endian.h>
55 #include <mono/metadata/tokentype.h>
56 #include <mono/metadata/domain-internals.h>
57 #include <mono/metadata/metadata-internals.h>
58 #include <mono/metadata/class-internals.h>
59 #include <mono/metadata/reflection-internals.h>
60 #include <mono/metadata/marshal.h>
61 #include <mono/metadata/gc-internals.h>
62 #include <mono/metadata/mono-gc.h>
63 #include <mono/metadata/rand.h>
64 #include <mono/metadata/sysmath.h>
65 #include <mono/metadata/string-icalls.h>
66 #include <mono/metadata/debug-helpers.h>
67 #include <mono/metadata/process.h>
68 #include <mono/metadata/environment.h>
69 #include <mono/metadata/profiler-private.h>
70 #include <mono/metadata/locales.h>
71 #include <mono/metadata/filewatcher.h>
72 #include <mono/metadata/security.h>
73 #include <mono/metadata/mono-config.h>
74 #include <mono/metadata/cil-coff.h>
75 #include <mono/metadata/number-formatter.h>
76 #include <mono/metadata/security-manager.h>
77 #include <mono/metadata/security-core-clr.h>
78 #include <mono/metadata/mono-perfcounters.h>
79 #include <mono/metadata/mono-debug.h>
80 #include <mono/metadata/mono-ptr-array.h>
81 #include <mono/metadata/verify-internals.h>
82 #include <mono/metadata/runtime.h>
83 #include <mono/metadata/file-mmap.h>
84 #include <mono/metadata/seq-points-data.h>
85 #include <mono/io-layer/io-layer.h>
86 #include <mono/utils/monobitset.h>
87 #include <mono/utils/mono-time.h>
88 #include <mono/utils/mono-proclib.h>
89 #include <mono/utils/mono-string.h>
90 #include <mono/utils/mono-error-internals.h>
91 #include <mono/utils/mono-mmap.h>
92 #include <mono/utils/mono-io-portability.h>
93 #include <mono/utils/mono-digest.h>
94 #include <mono/utils/bsearch.h>
95 #include <mono/utils/mono-os-mutex.h>
96 #include <mono/utils/mono-threads.h>
98 #if defined (HOST_WIN32)
102 #include "decimal-ms.h"
103 #include "number-ms.h"
105 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
106 #include <sys/utsname.h>
109 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
111 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
113 /* Lazy class loading functions */
114 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
115 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
116 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
119 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
122 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
124 static inline MonoBoolean
125 is_generic_parameter (MonoType *type)
127 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
131 mono_class_init_checked (MonoClass *klass, MonoError *error)
133 mono_error_init (error);
135 if (!mono_class_init (klass))
136 mono_error_set_for_class_failure (error, klass);
139 ICALL_EXPORT MonoObject *
140 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
146 MonoObject *result = NULL;
148 ac = (MonoClass *)arr->obj.vtable->klass;
150 esize = mono_array_element_size (ac);
151 ea = (gpointer*)((char*)arr->vector + (pos * esize));
153 if (ac->element_class->valuetype) {
154 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
155 mono_error_set_pending_exception (&error);
157 result = (MonoObject *)*ea;
161 ICALL_EXPORT MonoObject *
162 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
168 MONO_CHECK_ARG_NULL (idxs, NULL);
171 ic = (MonoClass *)io->obj.vtable->klass;
173 ac = (MonoClass *)arr->obj.vtable->klass;
175 g_assert (ic->rank == 1);
176 if (io->bounds != NULL || io->max_length != ac->rank) {
177 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
181 ind = (gint32 *)io->vector;
183 if (arr->bounds == NULL) {
184 if (*ind < 0 || *ind >= arr->max_length) {
185 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
189 return ves_icall_System_Array_GetValueImpl (arr, *ind);
192 for (i = 0; i < ac->rank; i++) {
193 if ((ind [i] < arr->bounds [i].lower_bound) ||
194 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
195 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
200 pos = ind [0] - arr->bounds [0].lower_bound;
201 for (i = 1; i < ac->rank; i++)
202 pos = pos * arr->bounds [i].length + ind [i] -
203 arr->bounds [i].lower_bound;
205 return ves_icall_System_Array_GetValueImpl (arr, pos);
209 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
212 MonoClass *ac, *vc, *ec;
221 mono_error_init (&error);
224 vc = value->vtable->klass;
228 ac = arr->obj.vtable->klass;
229 ec = ac->element_class;
231 esize = mono_array_element_size (ac);
232 ea = (gpointer*)((char*)arr->vector + (pos * esize));
233 va = (gpointer*)((char*)value + sizeof (MonoObject));
235 if (mono_class_is_nullable (ec)) {
236 mono_nullable_init ((guint8*)ea, value, ec);
241 mono_gc_bzero_atomic (ea, esize);
245 #define NO_WIDENING_CONVERSION G_STMT_START{\
246 mono_set_pending_exception (mono_get_exception_argument ( \
247 "value", "not a widening conversion")); \
251 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
252 if (esize < vsize + (extra)) { \
253 mono_set_pending_exception (mono_get_exception_argument ( \
254 "value", "not a widening conversion")); \
259 #define INVALID_CAST G_STMT_START{ \
260 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
261 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
265 /* Check element (destination) type. */
266 switch (ec->byval_arg.type) {
267 case MONO_TYPE_STRING:
268 switch (vc->byval_arg.type) {
269 case MONO_TYPE_STRING:
275 case MONO_TYPE_BOOLEAN:
276 switch (vc->byval_arg.type) {
277 case MONO_TYPE_BOOLEAN:
290 NO_WIDENING_CONVERSION;
299 if (!ec->valuetype) {
300 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
301 if (mono_error_set_pending_exception (&error))
305 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
309 if (mono_object_isinst_checked (value, ec, &error)) {
310 if (ec->has_references)
311 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
313 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
316 if (mono_error_set_pending_exception (&error))
322 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
324 et = ec->byval_arg.type;
325 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
326 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
328 vt = vc->byval_arg.type;
329 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
330 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
332 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
338 case MONO_TYPE_CHAR: \
339 CHECK_WIDENING_CONVERSION(0); \
340 *(etype *) ea = (etype) u64; \
342 /* You can't assign a signed value to an unsigned array. */ \
347 /* You can't assign a floating point number to an integer array. */ \
350 NO_WIDENING_CONVERSION; \
354 #define ASSIGN_SIGNED(etype) G_STMT_START{\
360 CHECK_WIDENING_CONVERSION(0); \
361 *(etype *) ea = (etype) i64; \
363 /* You can assign an unsigned value to a signed array if the array's */ \
364 /* element size is larger than the value size. */ \
369 case MONO_TYPE_CHAR: \
370 CHECK_WIDENING_CONVERSION(1); \
371 *(etype *) ea = (etype) u64; \
373 /* You can't assign a floating point number to an integer array. */ \
376 NO_WIDENING_CONVERSION; \
380 #define ASSIGN_REAL(etype) G_STMT_START{\
384 CHECK_WIDENING_CONVERSION(0); \
385 *(etype *) ea = (etype) r64; \
387 /* All integer values fit into a floating point array, so we don't */ \
388 /* need to CHECK_WIDENING_CONVERSION here. */ \
393 *(etype *) ea = (etype) i64; \
399 case MONO_TYPE_CHAR: \
400 *(etype *) ea = (etype) u64; \
407 u64 = *(guint8 *) va;
410 u64 = *(guint16 *) va;
413 u64 = *(guint32 *) va;
416 u64 = *(guint64 *) va;
422 i64 = *(gint16 *) va;
425 i64 = *(gint32 *) va;
428 i64 = *(gint64 *) va;
431 r64 = *(gfloat *) va;
434 r64 = *(gdouble *) va;
437 u64 = *(guint16 *) va;
439 case MONO_TYPE_BOOLEAN:
440 /* Boolean is only compatible with itself. */
453 NO_WIDENING_CONVERSION;
460 /* If we can't do a direct copy, let's try a widening conversion. */
463 ASSIGN_UNSIGNED (guint16);
465 ASSIGN_UNSIGNED (guint8);
467 ASSIGN_UNSIGNED (guint16);
469 ASSIGN_UNSIGNED (guint32);
471 ASSIGN_UNSIGNED (guint64);
473 ASSIGN_SIGNED (gint8);
475 ASSIGN_SIGNED (gint16);
477 ASSIGN_SIGNED (gint32);
479 ASSIGN_SIGNED (gint64);
481 ASSIGN_REAL (gfloat);
483 ASSIGN_REAL (gdouble);
487 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
491 #undef NO_WIDENING_CONVERSION
492 #undef CHECK_WIDENING_CONVERSION
493 #undef ASSIGN_UNSIGNED
499 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
505 MONO_CHECK_ARG_NULL (idxs,);
507 ic = idxs->obj.vtable->klass;
508 ac = arr->obj.vtable->klass;
510 g_assert (ic->rank == 1);
511 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
512 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
516 ind = (gint32 *)idxs->vector;
518 if (arr->bounds == NULL) {
519 if (*ind < 0 || *ind >= arr->max_length) {
520 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
524 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
528 for (i = 0; i < ac->rank; i++)
529 if ((ind [i] < arr->bounds [i].lower_bound) ||
530 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
531 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
535 pos = ind [0] - arr->bounds [0].lower_bound;
536 for (i = 1; i < ac->rank; i++)
537 pos = pos * arr->bounds [i].length + ind [i] -
538 arr->bounds [i].lower_bound;
540 ves_icall_System_Array_SetValueImpl (arr, value, pos);
543 ICALL_EXPORT MonoArray *
544 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
547 MonoClass *aklass, *klass;
550 gboolean bounded = FALSE;
552 MONO_CHECK_ARG_NULL (type, NULL);
553 MONO_CHECK_ARG_NULL (lengths, NULL);
555 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
557 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
559 for (i = 0; i < mono_array_length (lengths); i++) {
560 if (mono_array_get (lengths, gint32, i) < 0) {
561 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
566 klass = mono_class_from_mono_type (type->type);
567 mono_class_init_checked (klass, &error);
568 if (mono_error_set_pending_exception (&error))
571 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
572 /* vectors are not the same as one dimensional arrays with no-zero bounds */
577 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
579 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
580 for (i = 0; i < aklass->rank; ++i) {
581 sizes [i] = mono_array_get (lengths, guint32, i);
583 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
585 sizes [i + aklass->rank] = 0;
588 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
589 mono_error_set_pending_exception (&error);
594 ICALL_EXPORT MonoArray *
595 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
598 MonoClass *aklass, *klass;
601 gboolean bounded = FALSE;
603 MONO_CHECK_ARG_NULL (type, NULL);
604 MONO_CHECK_ARG_NULL (lengths, NULL);
606 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
608 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
610 for (i = 0; i < mono_array_length (lengths); i++) {
611 if ((mono_array_get (lengths, gint64, i) < 0) ||
612 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
613 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
618 klass = mono_class_from_mono_type (type->type);
619 mono_class_init_checked (klass, &error);
620 if (mono_error_set_pending_exception (&error))
623 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
624 /* vectors are not the same as one dimensional arrays with no-zero bounds */
629 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
631 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
632 for (i = 0; i < aklass->rank; ++i) {
633 sizes [i] = mono_array_get (lengths, guint64, i);
635 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
637 sizes [i + aklass->rank] = 0;
640 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
641 mono_error_set_pending_exception (&error);
647 ves_icall_System_Array_GetRank (MonoObject *arr)
649 return arr->vtable->klass->rank;
653 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
655 gint32 rank = arr->obj.vtable->klass->rank;
658 if ((dimension < 0) || (dimension >= rank)) {
659 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
663 if (arr->bounds == NULL)
664 length = arr->max_length;
666 length = arr->bounds [dimension].length;
668 #ifdef MONO_BIG_ARRAYS
669 if (length > G_MAXINT32) {
670 mono_set_pending_exception (mono_get_exception_overflow ());
678 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
680 gint32 rank = arr->obj.vtable->klass->rank;
682 if ((dimension < 0) || (dimension >= rank)) {
683 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
687 if (arr->bounds == NULL)
688 return arr->max_length;
690 return arr->bounds [dimension].length;
694 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
696 gint32 rank = arr->obj.vtable->klass->rank;
698 if ((dimension < 0) || (dimension >= rank)) {
699 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
703 if (arr->bounds == NULL)
706 return arr->bounds [dimension].lower_bound;
710 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
712 int sz = mono_array_element_size (mono_object_class (arr));
713 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
716 ICALL_EXPORT MonoArray*
717 ves_icall_System_Array_Clone (MonoArray *arr)
720 MonoArray *result = mono_array_clone_checked (arr, &error);
721 mono_error_set_pending_exception (&error);
725 ICALL_EXPORT gboolean
726 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
731 MonoVTable *src_vtable;
732 MonoVTable *dest_vtable;
733 MonoClass *src_class;
734 MonoClass *dest_class;
736 src_vtable = source->obj.vtable;
737 dest_vtable = dest->obj.vtable;
739 if (src_vtable->rank != dest_vtable->rank)
742 if (source->bounds || dest->bounds)
745 /* there's no integer overflow since mono_array_length returns an unsigned integer */
746 if ((dest_idx + length > mono_array_length_fast (dest)) ||
747 (source_idx + length > mono_array_length_fast (source)))
750 src_class = src_vtable->klass->element_class;
751 dest_class = dest_vtable->klass->element_class;
754 * Handle common cases.
757 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
758 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
760 if (src_class == mono_defaults.object_class && dest_class->valuetype)
763 /* Check if we're copying a char[] <==> (u)short[] */
764 if (src_class != dest_class) {
765 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
768 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
769 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
773 if (dest_class->valuetype) {
774 element_size = mono_array_element_size (source->obj.vtable->klass);
775 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
776 if (dest_class->has_references) {
777 mono_value_copy_array (dest, dest_idx, source_addr, length);
779 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
780 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
783 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
790 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
796 ac = (MonoClass *)arr->obj.vtable->klass;
798 esize = mono_array_element_size (ac);
799 ea = (gpointer*)((char*)arr->vector + (pos * esize));
801 mono_gc_memmove_atomic (value, ea, esize);
805 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
811 ac = (MonoClass *)arr->obj.vtable->klass;
812 ec = ac->element_class;
814 esize = mono_array_element_size (ac);
815 ea = (gpointer*)((char*)arr->vector + (pos * esize));
817 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
818 g_assert (esize == sizeof (gpointer));
819 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
821 g_assert (ec->inited);
822 g_assert (esize == mono_class_value_size (ec, NULL));
823 if (ec->has_references)
824 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
826 mono_gc_memmove_atomic (ea, value, esize);
831 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
833 MonoClass *klass = array->obj.vtable->klass;
834 guint32 size = mono_array_element_size (klass);
835 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
837 const char *field_data;
839 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
840 MonoException *exc = mono_get_exception_argument("array",
841 "Cannot initialize array of non-primitive type.");
842 mono_set_pending_exception (exc);
846 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
847 MonoException *exc = mono_get_exception_argument("field_handle",
848 "Field doesn't have an RVA");
849 mono_set_pending_exception (exc);
853 size *= array->max_length;
854 field_data = mono_field_get_data (field_handle);
856 if (size > mono_type_size (field_handle->type, &align)) {
857 MonoException *exc = mono_get_exception_argument("field_handle",
858 "Field not large enough to fill array");
859 mono_set_pending_exception (exc);
863 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
865 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
866 guint ## n *src = (guint ## n *) field_data; \
868 nEnt = (size / sizeof(guint ## n)); \
870 for (i = 0; i < nEnt; i++) { \
871 data[i] = read ## n (&src[i]); \
875 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
877 switch (type->type) {
894 memcpy (mono_array_addr (array, char, 0), field_data, size);
898 memcpy (mono_array_addr (array, char, 0), field_data, size);
903 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
905 return offsetof (MonoString, chars);
908 ICALL_EXPORT MonoObject *
909 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
911 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
915 MonoObject *ret = mono_object_clone_checked (obj, &error);
916 mono_error_set_pending_exception (&error);
923 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
929 MONO_CHECK_ARG_NULL (handle,);
931 klass = mono_class_from_mono_type (handle);
932 MONO_CHECK_ARG (handle, klass,);
934 if (klass->generic_container)
937 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
938 if (!is_ok (&error)) {
939 mono_error_set_pending_exception (&error);
943 /* This will call the type constructor */
944 if (!mono_runtime_class_init_full (vtable, &error))
945 mono_error_set_pending_exception (&error);
949 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
953 mono_image_check_for_module_cctor (image);
954 if (image->has_module_cctor) {
955 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
956 if (!mono_error_ok (&error)) {
957 mono_error_set_pending_exception (&error);
960 /*It's fine to raise the exception here*/
961 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
962 if (!is_ok (&error)) {
963 mono_error_set_pending_exception (&error);
966 if (!mono_runtime_class_init_full (vtable, &error))
967 mono_error_set_pending_exception (&error);
971 ICALL_EXPORT MonoBoolean
972 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
977 /* later make this configurable and per-arch */
978 int min_size = 4096 * 4 * sizeof (void*);
979 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
980 /* if we have no info we are optimistic and assume there is enough room */
984 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
988 current = (guint8 *)&stack_addr;
989 if (current > stack_addr) {
990 if ((current - stack_addr) < min_size)
993 if (current - (stack_addr - stack_size) < min_size)
999 ICALL_EXPORT MonoObject *
1000 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
1003 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
1004 mono_error_set_pending_exception (&error);
1010 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1014 MonoObject **values = NULL;
1017 gint32 result = (int)(gsize)mono_defaults.int32_class;
1018 MonoClassField* field;
1021 klass = mono_object_class (this_obj);
1023 if (mono_class_num_fields (klass) == 0)
1027 * Compute the starting value of the hashcode for fields of primitive
1028 * types, and return the remaining fields in an array to the managed side.
1029 * This way, we can avoid costly reflection operations in managed code.
1032 while ((field = mono_class_get_fields (klass, &iter))) {
1033 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1035 if (mono_field_is_deleted (field))
1037 /* FIXME: Add more types */
1038 switch (field->type->type) {
1040 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1042 case MONO_TYPE_STRING: {
1044 s = *(MonoString**)((guint8*)this_obj + field->offset);
1046 result ^= mono_string_hash (s);
1051 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1052 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1053 if (!is_ok (&error)) {
1054 mono_error_set_pending_exception (&error);
1057 values [count++] = o;
1063 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1064 if (mono_error_set_pending_exception (&error))
1066 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1067 for (i = 0; i < count; ++i)
1068 mono_array_setref (*fields, i, values [i]);
1075 ICALL_EXPORT MonoBoolean
1076 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1080 MonoObject **values = NULL;
1082 MonoClassField* field;
1086 MONO_CHECK_ARG_NULL (that, FALSE);
1088 if (this_obj->vtable != that->vtable)
1091 klass = mono_object_class (this_obj);
1093 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1094 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1097 * Do the comparison for fields of primitive type and return a result if
1098 * possible. Otherwise, return the remaining fields in an array to the
1099 * managed side. This way, we can avoid costly reflection operations in
1104 while ((field = mono_class_get_fields (klass, &iter))) {
1105 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1107 if (mono_field_is_deleted (field))
1109 /* FIXME: Add more types */
1110 switch (field->type->type) {
1113 case MONO_TYPE_BOOLEAN:
1114 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1119 case MONO_TYPE_CHAR:
1120 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1125 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1130 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1134 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1138 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1143 case MONO_TYPE_STRING: {
1144 MonoString *s1, *s2;
1145 guint32 s1len, s2len;
1146 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1147 s2 = *(MonoString**)((guint8*)that + field->offset);
1150 if ((s1 == NULL) || (s2 == NULL))
1152 s1len = mono_string_length (s1);
1153 s2len = mono_string_length (s2);
1157 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1163 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1164 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1165 if (!is_ok (&error)) {
1166 mono_error_set_pending_exception (&error);
1169 values [count++] = o;
1170 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1171 if (!is_ok (&error)) {
1172 mono_error_set_pending_exception (&error);
1175 values [count++] = o;
1178 if (klass->enumtype)
1179 /* enums only have one non-static field */
1185 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1186 if (mono_error_set_pending_exception (&error))
1188 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1189 for (i = 0; i < count; ++i)
1190 mono_array_setref_fast (*fields, i, values [i]);
1197 ICALL_EXPORT MonoReflectionType *
1198 ves_icall_System_Object_GetType (MonoObject *obj)
1201 MonoReflectionType *ret;
1202 #ifndef DISABLE_REMOTING
1203 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1204 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1207 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1209 mono_error_set_pending_exception (&error);
1214 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1216 MONO_CHECK_ARG_NULL (obj, 0);
1219 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1220 mono_error_set_pending_exception (&error);
1225 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1226 MonoReflectionMethod *method,
1227 MonoArray *opt_param_types)
1229 MONO_CHECK_ARG_NULL (method, 0);
1232 gint32 result = mono_image_create_method_token (
1233 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1234 mono_error_set_pending_exception (&error);
1239 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1242 mono_image_create_pefile (mb, file, &error);
1243 mono_error_set_pending_exception (&error);
1247 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1250 mono_image_build_metadata (mb, &error);
1251 mono_error_set_pending_exception (&error);
1255 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1257 mono_image_register_token (mb->dynamic_image, token, obj);
1260 ICALL_EXPORT MonoObject*
1261 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1265 mono_loader_lock ();
1266 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1267 mono_loader_unlock ();
1272 ICALL_EXPORT MonoReflectionModule*
1273 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1276 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1277 mono_error_set_pending_exception (&error);
1282 * ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class:
1283 * @tb: a TypeBuilder object
1286 * Creates the generic class after all generic parameters have been added.
1289 ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class (MonoReflectionTypeBuilder *tb)
1292 (void) mono_reflection_create_generic_class (tb, &error);
1293 mono_error_set_pending_exception (&error);
1296 #ifndef DISABLE_REFLECTION_EMIT
1297 ICALL_EXPORT MonoArray*
1298 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
1301 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
1302 mono_error_set_pending_exception (&error);
1308 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1310 MonoMethod **dest = (MonoMethod **)data;
1312 /* skip unmanaged frames */
1317 if (!strcmp (m->klass->name_space, "System.Reflection"))
1326 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1328 MonoMethod **dest = (MonoMethod **)data;
1330 /* skip unmanaged frames */
1334 if (m->wrapper_type != MONO_WRAPPER_NONE)
1342 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1353 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1355 MonoMethod **dest = (MonoMethod **)data;
1357 /* skip unmanaged frames */
1361 if (m->wrapper_type != MONO_WRAPPER_NONE)
1369 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1370 || (!strcmp (m->klass->name_space, "System"))))
1380 static MonoReflectionType *
1381 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1383 MonoMethod *m, *dest;
1385 MonoType *type = NULL;
1386 MonoAssembly *assembly = NULL;
1387 gboolean type_resolve = FALSE;
1388 MonoImage *rootimage = NULL;
1390 mono_error_init (error);
1393 * We must compute the calling assembly as type loading must happen under a metadata context.
1394 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1395 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1397 m = mono_method_get_last_managed ();
1399 if (m && m->klass->image != mono_defaults.corlib) {
1400 /* Happens with inlining */
1402 /* Ugly hack: type_from_parsed_name is called from
1403 * System.Type.internal_from_name, which is called most
1404 * directly from System.Type.GetType(string,bool,bool) but
1405 * also indirectly from places such as
1406 * System.Type.GetType(string,func,func) (via
1407 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1408 * so we need to skip over all of those to find the true caller.
1410 * It would be nice if we had stack marks.
1412 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1418 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1419 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1420 * to crash. This only seems to happen in some strange remoting
1421 * scenarios and I was unable to figure out what's happening there.
1422 * Dec 10, 2005 - Martin.
1426 assembly = dest->klass->image->assembly;
1427 type_resolve = TRUE;
1428 rootimage = assembly->image;
1430 g_warning (G_STRLOC);
1433 if (info->assembly.name)
1434 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1437 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1438 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1439 return_val_if_nok (error, NULL);
1443 // Say we're looking for System.Generic.Dict<int, Local>
1444 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1445 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1446 // is messed up when we go to construct the Local as the type arg...
1448 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1449 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1450 if (!info->assembly.name && !type) {
1452 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1453 return_val_if_nok (error, NULL);
1455 if (assembly && !type && type_resolve) {
1456 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1457 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1458 return_val_if_nok (error, NULL);
1464 return mono_type_get_object_checked (mono_domain_get (), type, error);
1467 ICALL_EXPORT MonoReflectionType*
1468 ves_icall_System_Type_internal_from_name (MonoString *name,
1469 MonoBoolean throwOnError,
1470 MonoBoolean ignoreCase)
1473 MonoTypeNameParse info;
1474 MonoReflectionType *type = NULL;
1477 char *str = mono_string_to_utf8_checked (name, &error);
1478 if (!is_ok (&error))
1481 parsedOk = mono_reflection_parse_type (str, &info);
1483 /* mono_reflection_parse_type() mangles the string */
1485 mono_reflection_free_type_info (&info);
1487 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1491 type = type_from_parsed_name (&info, ignoreCase, &error);
1493 mono_reflection_free_type_info (&info);
1495 if (!is_ok (&error))
1500 mono_error_set_type_load_name (&error, g_strdup (str), NULL, "");
1507 if (!is_ok (&error)) {
1509 mono_error_set_pending_exception (&error);
1511 mono_error_cleanup (&error);
1519 ICALL_EXPORT MonoReflectionType*
1520 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1523 MonoReflectionType *ret;
1524 MonoDomain *domain = mono_domain_get ();
1526 ret = mono_type_get_object_checked (domain, handle, &error);
1527 mono_error_set_pending_exception (&error);
1532 ICALL_EXPORT MonoType*
1533 ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass)
1535 return mono_class_get_type (klass);
1538 /* System.TypeCode */
1557 TYPECODE_STRING = 18
1560 ICALL_EXPORT guint32
1561 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1563 int t = type->type->type;
1565 if (type->type->byref)
1566 return TYPECODE_OBJECT;
1570 case MONO_TYPE_VOID:
1571 return TYPECODE_OBJECT;
1572 case MONO_TYPE_BOOLEAN:
1573 return TYPECODE_BOOLEAN;
1575 return TYPECODE_BYTE;
1577 return TYPECODE_SBYTE;
1579 return TYPECODE_UINT16;
1581 return TYPECODE_INT16;
1582 case MONO_TYPE_CHAR:
1583 return TYPECODE_CHAR;
1587 return TYPECODE_OBJECT;
1589 return TYPECODE_UINT32;
1591 return TYPECODE_INT32;
1593 return TYPECODE_UINT64;
1595 return TYPECODE_INT64;
1597 return TYPECODE_SINGLE;
1599 return TYPECODE_DOUBLE;
1600 case MONO_TYPE_VALUETYPE: {
1601 MonoClass *klass = type->type->data.klass;
1603 if (klass->enumtype) {
1604 t = mono_class_enum_basetype (klass)->type;
1606 } else if (mono_is_corlib_image (klass->image)) {
1607 if (strcmp (klass->name_space, "System") == 0) {
1608 if (strcmp (klass->name, "Decimal") == 0)
1609 return TYPECODE_DECIMAL;
1610 else if (strcmp (klass->name, "DateTime") == 0)
1611 return TYPECODE_DATETIME;
1614 return TYPECODE_OBJECT;
1616 case MONO_TYPE_STRING:
1617 return TYPECODE_STRING;
1618 case MONO_TYPE_SZARRAY:
1619 case MONO_TYPE_ARRAY:
1620 case MONO_TYPE_OBJECT:
1622 case MONO_TYPE_MVAR:
1623 case MONO_TYPE_TYPEDBYREF:
1624 return TYPECODE_OBJECT;
1625 case MONO_TYPE_CLASS:
1627 MonoClass *klass = type->type->data.klass;
1628 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1629 if (strcmp (klass->name, "DBNull") == 0)
1630 return TYPECODE_DBNULL;
1633 return TYPECODE_OBJECT;
1634 case MONO_TYPE_GENERICINST:
1635 return TYPECODE_OBJECT;
1637 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1643 mono_type_is_primitive (MonoType *type)
1645 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1646 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1650 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1652 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1653 return mono_class_enum_basetype (type->data.klass);
1654 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1655 return mono_class_enum_basetype (type->data.generic_class->container_class);
1659 ICALL_EXPORT guint32
1660 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1665 g_assert (type != NULL);
1667 klass = mono_class_from_mono_type (type->type);
1668 klassc = mono_class_from_mono_type (c->type);
1670 if (type->type->byref ^ c->type->byref)
1673 if (type->type->byref) {
1674 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1675 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1677 klass = mono_class_from_mono_type (t);
1678 klassc = mono_class_from_mono_type (ot);
1680 if (mono_type_is_primitive (t)) {
1681 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1682 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1683 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1684 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1685 return t->type == ot->type;
1687 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1690 if (klass->valuetype)
1691 return klass == klassc;
1692 return klass->valuetype == klassc->valuetype;
1695 return mono_class_is_assignable_from (klass, klassc);
1698 ICALL_EXPORT guint32
1699 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1702 MonoClass *klass = mono_class_from_mono_type (type->type);
1703 mono_class_init_checked (klass, &error);
1704 if (!is_ok (&error)) {
1705 mono_error_set_pending_exception (&error);
1708 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1709 mono_error_set_pending_exception (&error);
1713 ICALL_EXPORT guint32
1714 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1716 MonoClass *klass = mono_class_from_mono_type (type->type);
1717 return klass->flags;
1720 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1721 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1724 MonoClass *klass = field->field->parent;
1725 MonoMarshalType *info;
1729 if (klass->generic_container ||
1730 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1733 ftype = mono_field_get_type (field->field);
1734 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1737 info = mono_marshal_load_type_info (klass);
1739 for (i = 0; i < info->num_fields; ++i) {
1740 if (info->fields [i].field == field->field) {
1741 if (!info->fields [i].mspec)
1744 MonoReflectionMarshalAsAttribute* obj;
1745 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1746 if (!mono_error_ok (&error))
1747 mono_error_set_pending_exception (&error);
1756 ICALL_EXPORT MonoReflectionField*
1757 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1760 gboolean found = FALSE;
1767 klass = handle->parent;
1769 klass = mono_class_from_mono_type (type);
1771 /* Check that the field belongs to the class */
1772 for (k = klass; k; k = k->parent) {
1773 if (k == handle->parent) {
1780 /* The managed code will throw the exception */
1784 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1785 mono_error_set_pending_exception (&error);
1789 ICALL_EXPORT MonoArray*
1790 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1793 MonoType *type = mono_field_get_type_checked (field->field, &error);
1796 if (!mono_error_ok (&error)) {
1797 mono_error_set_pending_exception (&error);
1801 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1802 mono_error_set_pending_exception (&error);
1807 vell_icall_get_method_attributes (MonoMethod *method)
1809 return method->flags;
1813 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1816 MonoReflectionType *rt;
1817 MonoDomain *domain = mono_domain_get ();
1818 MonoMethodSignature* sig;
1820 sig = mono_method_signature_checked (method, &error);
1821 if (!mono_error_ok (&error)) {
1822 mono_error_set_pending_exception (&error);
1826 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1827 if (!mono_error_ok (&error)) {
1828 mono_error_set_pending_exception (&error);
1832 MONO_STRUCT_SETREF (info, parent, rt);
1834 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1835 if (!mono_error_ok (&error)) {
1836 mono_error_set_pending_exception (&error);
1840 MONO_STRUCT_SETREF (info, ret, rt);
1842 info->attrs = method->flags;
1843 info->implattrs = method->iflags;
1844 if (sig->call_convention == MONO_CALL_DEFAULT)
1845 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1847 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1852 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1855 ICALL_EXPORT MonoArray*
1856 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1859 MonoDomain *domain = mono_domain_get ();
1861 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1862 mono_error_set_pending_exception (&error);
1866 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1867 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1870 MonoDomain *domain = mono_domain_get ();
1871 MonoReflectionMarshalAsAttribute* res = NULL;
1872 MonoMarshalSpec **mspecs;
1875 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1876 mono_method_get_marshal_info (method, mspecs);
1879 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1880 if (!mono_error_ok (&error)) {
1881 mono_error_set_pending_exception (&error);
1886 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1888 mono_metadata_free_marshal_spec (mspecs [i]);
1895 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1897 MonoClass *parent = field->field->parent;
1898 if (!parent->size_inited)
1899 mono_class_init (parent);
1900 mono_class_setup_fields_locking (parent);
1902 return field->field->offset - sizeof (MonoObject);
1905 ICALL_EXPORT MonoReflectionType*
1906 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1909 MonoReflectionType *ret;
1912 parent = declaring? field->field->parent: field->klass;
1914 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1915 mono_error_set_pending_exception (&error);
1921 ICALL_EXPORT MonoObject *
1922 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1925 MonoClass *fklass = field->klass;
1926 MonoClassField *cf = field->field;
1927 MonoDomain *domain = mono_object_domain (field);
1929 if (fklass->image->assembly->ref_only) {
1930 mono_set_pending_exception (mono_get_exception_invalid_operation (
1931 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1935 if (mono_security_core_clr_enabled () &&
1936 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1937 mono_error_set_pending_exception (&error);
1941 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1942 mono_error_set_pending_exception (&error);
1947 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1950 MonoClassField *cf = field->field;
1954 if (field->klass->image->assembly->ref_only) {
1955 mono_set_pending_exception (mono_get_exception_invalid_operation (
1956 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1960 if (mono_security_core_clr_enabled () &&
1961 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1962 mono_error_set_pending_exception (&error);
1966 type = mono_field_get_type_checked (cf, &error);
1967 if (!mono_error_ok (&error)) {
1968 mono_error_set_pending_exception (&error);
1972 v = (gchar *) value;
1974 switch (type->type) {
1977 case MONO_TYPE_BOOLEAN:
1980 case MONO_TYPE_CHAR:
1989 case MONO_TYPE_VALUETYPE:
1992 v += sizeof (MonoObject);
1994 case MONO_TYPE_STRING:
1995 case MONO_TYPE_OBJECT:
1996 case MONO_TYPE_CLASS:
1997 case MONO_TYPE_ARRAY:
1998 case MONO_TYPE_SZARRAY:
2001 case MONO_TYPE_GENERICINST: {
2002 MonoGenericClass *gclass = type->data.generic_class;
2003 g_assert (!gclass->context.class_inst->is_open);
2005 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
2006 MonoClass *nklass = mono_class_from_mono_type (type);
2007 MonoObject *nullable;
2010 * Convert the boxed vtype into a Nullable structure.
2011 * This is complicated by the fact that Nullables have
2012 * a variable structure.
2014 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2015 if (!mono_error_ok (&error)) {
2016 mono_error_set_pending_exception (&error);
2020 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2022 v = (gchar *)mono_object_unbox (nullable);
2025 if (gclass->container_class->valuetype && (v != NULL))
2026 v += sizeof (MonoObject);
2030 g_error ("type 0x%x not handled in "
2031 "ves_icall_FieldInfo_SetValueInternal", type->type);
2036 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2037 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2038 if (!is_ok (&error)) {
2039 mono_error_set_pending_exception (&error);
2042 if (!vtable->initialized) {
2043 if (!mono_runtime_class_init_full (vtable, &error)) {
2044 mono_error_set_pending_exception (&error);
2048 mono_field_static_set_value (vtable, cf, v);
2050 mono_field_set_value (obj, cf, v);
2055 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2064 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2065 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2069 if (MONO_TYPE_IS_REFERENCE (f->type))
2070 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2072 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2075 ICALL_EXPORT MonoObject *
2076 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2078 MonoObject *o = NULL;
2079 MonoClassField *field = rfield->field;
2081 MonoDomain *domain = mono_object_domain (rfield);
2083 MonoTypeEnum def_type;
2084 const char *def_value;
2088 mono_class_init (field->parent);
2090 t = mono_field_get_type_checked (field, &error);
2091 if (!mono_error_ok (&error)) {
2092 mono_error_set_pending_exception (&error);
2096 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2097 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2101 if (image_is_dynamic (field->parent->image)) {
2102 MonoClass *klass = field->parent;
2103 int fidx = field - klass->fields;
2105 g_assert (fidx >= 0 && fidx < klass->field.count);
2106 g_assert (klass->ext);
2107 g_assert (klass->ext->field_def_values);
2108 def_type = klass->ext->field_def_values [fidx].def_type;
2109 def_value = klass->ext->field_def_values [fidx].data;
2110 if (def_type == MONO_TYPE_END) {
2111 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2115 def_value = mono_class_get_field_default_value (field, &def_type);
2116 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2118 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2123 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2127 case MONO_TYPE_BOOLEAN:
2130 case MONO_TYPE_CHAR:
2138 case MONO_TYPE_R8: {
2141 /* boxed value type */
2142 t = g_new0 (MonoType, 1);
2144 klass = mono_class_from_mono_type (t);
2146 o = mono_object_new_checked (domain, klass, &error);
2147 if (!mono_error_ok (&error)) {
2148 mono_error_set_pending_exception (&error);
2151 v = ((gchar *) o) + sizeof (MonoObject);
2152 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2153 if (mono_error_set_pending_exception (&error))
2157 case MONO_TYPE_STRING:
2158 case MONO_TYPE_CLASS:
2159 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2160 if (mono_error_set_pending_exception (&error))
2164 g_assert_not_reached ();
2170 ICALL_EXPORT MonoReflectionType*
2171 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2174 MonoReflectionType *ret;
2177 type = mono_field_get_type_checked (ref_field->field, &error);
2178 if (!mono_error_ok (&error)) {
2179 mono_error_set_pending_exception (&error);
2183 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2184 if (!mono_error_ok (&error)) {
2185 mono_error_set_pending_exception (&error);
2192 /* From MonoProperty.cs */
2194 PInfo_Attributes = 1,
2195 PInfo_GetMethod = 1 << 1,
2196 PInfo_SetMethod = 1 << 2,
2197 PInfo_ReflectedType = 1 << 3,
2198 PInfo_DeclaringType = 1 << 4,
2203 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2206 MonoReflectionType *rt;
2207 MonoReflectionMethod *rm;
2208 MonoDomain *domain = mono_object_domain (property);
2209 const MonoProperty *pproperty = property->property;
2211 if ((req_info & PInfo_ReflectedType) != 0) {
2212 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2213 if (mono_error_set_pending_exception (&error))
2216 MONO_STRUCT_SETREF (info, parent, rt);
2218 if ((req_info & PInfo_DeclaringType) != 0) {
2219 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2220 if (mono_error_set_pending_exception (&error))
2223 MONO_STRUCT_SETREF (info, declaring_type, rt);
2226 if ((req_info & PInfo_Name) != 0)
2227 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2229 if ((req_info & PInfo_Attributes) != 0)
2230 info->attrs = pproperty->attrs;
2232 if ((req_info & PInfo_GetMethod) != 0) {
2233 if (pproperty->get &&
2234 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2235 pproperty->get->klass == property->klass)) {
2236 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2237 if (mono_error_set_pending_exception (&error))
2243 MONO_STRUCT_SETREF (info, get, rm);
2245 if ((req_info & PInfo_SetMethod) != 0) {
2246 if (pproperty->set &&
2247 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2248 pproperty->set->klass == property->klass)) {
2249 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2250 if (mono_error_set_pending_exception (&error))
2256 MONO_STRUCT_SETREF (info, set, rm);
2259 * There may be other methods defined for properties, though, it seems they are not exposed
2260 * in the reflection API
2265 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2268 MonoReflectionType *rt;
2269 MonoReflectionMethod *rm;
2270 MonoDomain *domain = mono_object_domain (event);
2272 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2273 if (mono_error_set_pending_exception (&error))
2276 MONO_STRUCT_SETREF (info, reflected_type, rt);
2278 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2279 if (mono_error_set_pending_exception (&error))
2282 MONO_STRUCT_SETREF (info, declaring_type, rt);
2284 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2285 info->attrs = event->event->attrs;
2287 if (event->event->add) {
2288 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2289 if (mono_error_set_pending_exception (&error))
2295 MONO_STRUCT_SETREF (info, add_method, rm);
2297 if (event->event->remove) {
2298 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2299 if (mono_error_set_pending_exception (&error))
2305 MONO_STRUCT_SETREF (info, remove_method, rm);
2307 if (event->event->raise) {
2308 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2309 if (mono_error_set_pending_exception (&error))
2315 MONO_STRUCT_SETREF (info, raise_method, rm);
2317 #ifndef MONO_SMALL_CONFIG
2318 if (event->event->other) {
2320 while (event->event->other [n])
2322 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2323 if (mono_error_set_pending_exception (&error))
2325 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2327 for (i = 0; i < n; i++) {
2328 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2329 if (mono_error_set_pending_exception (&error))
2331 mono_array_setref (info->other_methods, i, rm);
2338 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2343 mono_class_setup_interfaces (klass, error);
2344 if (!mono_error_ok (error))
2347 for (i = 0; i < klass->interface_count; i++) {
2348 ic = klass->interfaces [i];
2349 g_hash_table_insert (ifaces, ic, ic);
2351 collect_interfaces (ic, ifaces, error);
2352 if (!mono_error_ok (error))
2358 MonoArray *iface_array;
2359 MonoGenericContext *context;
2363 } FillIfaceArrayData;
2366 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2368 MonoReflectionType *rt;
2369 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2370 MonoClass *ic = (MonoClass *)key;
2371 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2373 if (!mono_error_ok (data->error))
2376 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2377 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2378 if (!mono_error_ok (data->error))
2382 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2383 if (!mono_error_ok (data->error))
2386 mono_array_setref (data->iface_array, data->next_idx++, rt);
2389 mono_metadata_free_type (inflated);
2393 get_interfaces_hash (gconstpointer v1)
2395 MonoClass *k = (MonoClass*)v1;
2397 return k->type_token;
2400 ICALL_EXPORT MonoArray*
2401 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2404 MonoClass *klass = mono_class_from_mono_type (type->type);
2406 FillIfaceArrayData data = { 0 };
2409 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2411 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2412 data.context = mono_class_get_context (klass);
2413 klass = klass->generic_class->container_class;
2416 for (parent = klass; parent; parent = parent->parent) {
2417 mono_class_setup_interfaces (parent, &error);
2418 if (!mono_error_ok (&error))
2420 collect_interfaces (parent, iface_hash, &error);
2421 if (!mono_error_ok (&error))
2425 data.error = &error;
2426 data.domain = mono_object_domain (type);
2428 len = g_hash_table_size (iface_hash);
2430 g_hash_table_destroy (iface_hash);
2431 if (!data.domain->empty_types) {
2432 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2433 if (!is_ok (&error))
2436 return data.domain->empty_types;
2439 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2440 if (!is_ok (&error))
2442 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2443 if (!mono_error_ok (&error))
2446 g_hash_table_destroy (iface_hash);
2447 return data.iface_array;
2450 g_hash_table_destroy (iface_hash);
2451 mono_error_set_pending_exception (&error);
2456 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2458 gboolean variance_used;
2459 MonoClass *klass = mono_class_from_mono_type (type->type);
2460 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2461 MonoReflectionMethod *member;
2464 int i = 0, len, ioffset;
2468 mono_class_init_checked (klass, &error);
2469 if (mono_error_set_pending_exception (&error))
2471 mono_class_init_checked (iclass, &error);
2472 if (mono_error_set_pending_exception (&error))
2475 mono_class_setup_vtable (klass);
2477 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2481 len = mono_class_num_methods (iclass);
2482 domain = mono_object_domain (type);
2483 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2484 if (mono_error_set_pending_exception (&error))
2486 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2487 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2488 if (mono_error_set_pending_exception (&error))
2490 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2492 while ((method = mono_class_get_methods (iclass, &iter))) {
2493 member = mono_method_get_object_checked (domain, method, iclass, &error);
2494 if (mono_error_set_pending_exception (&error))
2496 mono_array_setref (*methods, i, member);
2497 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2498 if (mono_error_set_pending_exception (&error))
2500 mono_array_setref (*targets, i, member);
2507 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2510 MonoClass *klass = mono_class_from_mono_type (type->type);
2512 mono_class_init_checked (klass, &error);
2513 if (mono_error_set_pending_exception (&error))
2516 if (image_is_dynamic (klass->image)) {
2517 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2518 *packing = tb->packing_size;
2519 *size = tb->class_size;
2521 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2525 ICALL_EXPORT MonoReflectionType*
2526 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2529 MonoReflectionType *ret;
2532 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2533 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2534 mono_error_set_pending_exception (&error);
2538 klass = mono_class_from_mono_type (type->type);
2539 mono_class_init_checked (klass, &error);
2540 if (mono_error_set_pending_exception (&error))
2544 // GetElementType should only return a type for:
2545 // Array Pointer PassedByRef
2546 if (type->type->byref)
2547 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2548 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2549 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2550 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2551 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2555 mono_error_set_pending_exception (&error);
2560 ICALL_EXPORT MonoReflectionType*
2561 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2564 MonoReflectionType *ret;
2566 if (type->type->byref)
2569 MonoClass *klass = mono_class_from_mono_type (type->type);
2573 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2574 mono_error_set_pending_exception (&error);
2579 ICALL_EXPORT MonoBoolean
2580 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2582 return type->type->type == MONO_TYPE_PTR;
2585 ICALL_EXPORT MonoBoolean
2586 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2588 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)));
2591 ICALL_EXPORT MonoBoolean
2592 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2594 return type->type->byref;
2597 ICALL_EXPORT MonoBoolean
2598 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2601 MonoClass *klass = mono_class_from_mono_type (type->type);
2602 mono_class_init_checked (klass, &error);
2603 if (mono_error_set_pending_exception (&error))
2606 return mono_class_is_com_object (klass);
2609 ICALL_EXPORT guint32
2610 ves_icall_reflection_get_token (MonoObject* obj)
2613 guint32 result = mono_reflection_get_token_checked (obj, &error);
2614 mono_error_set_pending_exception (&error);
2618 ICALL_EXPORT MonoReflectionModule*
2619 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2622 MonoReflectionModule *result = NULL;
2623 MonoClass *klass = mono_class_from_mono_type (type->type);
2624 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2625 mono_error_set_pending_exception (&error);
2629 ICALL_EXPORT MonoReflectionAssembly*
2630 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2633 MonoDomain *domain = mono_domain_get ();
2634 MonoClass *klass = mono_class_from_mono_type (type->type);
2635 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2636 mono_error_set_pending_exception (&error);
2640 ICALL_EXPORT MonoReflectionType*
2641 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2644 MonoReflectionType *ret;
2645 MonoDomain *domain = mono_domain_get ();
2648 if (type->type->byref)
2650 if (type->type->type == MONO_TYPE_VAR) {
2651 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2652 klass = param ? param->owner.klass : NULL;
2653 } else if (type->type->type == MONO_TYPE_MVAR) {
2654 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2655 klass = param ? param->owner.method->klass : NULL;
2657 klass = mono_class_from_mono_type (type->type)->nested_in;
2663 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2664 mono_error_set_pending_exception (&error);
2669 ICALL_EXPORT MonoString*
2670 ves_icall_RuntimeType_get_Name (MonoReflectionType *type)
2672 MonoDomain *domain = mono_domain_get ();
2673 MonoClass *klass = mono_class_from_mono_type (type->type);
2675 if (type->type->byref) {
2676 char *n = g_strdup_printf ("%s&", klass->name);
2677 MonoString *res = mono_string_new (domain, n);
2683 return mono_string_new (domain, klass->name);
2687 ICALL_EXPORT MonoString*
2688 ves_icall_RuntimeType_get_Namespace (MonoReflectionType *type)
2690 MonoDomain *domain = mono_domain_get ();
2691 MonoClass *klass = mono_class_from_mono_type (type->type);
2693 while (klass->nested_in)
2694 klass = klass->nested_in;
2696 if (klass->name_space [0] == '\0')
2699 return mono_string_new (domain, klass->name_space);
2703 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2707 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2708 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2712 klass = mono_class_from_mono_type (type->type);
2718 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2720 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2723 ICALL_EXPORT MonoArray*
2724 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2727 MonoReflectionType *rt;
2729 MonoClass *klass, *pklass;
2730 MonoDomain *domain = mono_object_domain (type);
2733 klass = mono_class_from_mono_type (type->type);
2735 if (klass->generic_container) {
2736 MonoGenericContainer *container = klass->generic_container;
2737 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2738 if (mono_error_set_pending_exception (&error))
2740 for (i = 0; i < container->type_argc; ++i) {
2741 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2743 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2744 if (mono_error_set_pending_exception (&error))
2747 mono_array_setref (res, i, rt);
2749 } else if (klass->generic_class) {
2750 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2751 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2752 if (mono_error_set_pending_exception (&error))
2754 for (i = 0; i < inst->type_argc; ++i) {
2755 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2756 if (mono_error_set_pending_exception (&error))
2759 mono_array_setref (res, i, rt);
2767 ICALL_EXPORT gboolean
2768 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2772 if (!IS_MONOTYPE (type))
2775 if (type->type->byref)
2778 klass = mono_class_from_mono_type (type->type);
2779 return klass->generic_container != NULL;
2782 ICALL_EXPORT MonoReflectionType*
2783 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2786 MonoReflectionType *ret;
2789 if (type->type->byref)
2792 klass = mono_class_from_mono_type (type->type);
2794 if (klass->generic_container) {
2795 return type; /* check this one */
2797 if (klass->generic_class) {
2798 MonoClass *generic_class = klass->generic_class->container_class;
2801 tb = mono_class_get_ref_info (generic_class);
2803 if (generic_class->wastypebuilder && tb)
2804 return (MonoReflectionType *)tb;
2806 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2807 mono_error_set_pending_exception (&error);
2815 ICALL_EXPORT MonoReflectionType*
2816 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2819 MonoReflectionType *ret;
2821 MonoType *geninst, **types;
2824 g_assert (IS_MONOTYPE (type));
2825 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2826 if (mono_error_set_pending_exception (&error))
2829 count = mono_array_length (type_array);
2830 types = g_new0 (MonoType *, count);
2832 for (i = 0; i < count; i++) {
2833 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2834 types [i] = t->type;
2837 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2840 mono_error_set_pending_exception (&error);
2844 klass = mono_class_from_mono_type (geninst);
2846 /*we might inflate to the GTD*/
2847 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2848 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2852 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2853 mono_error_set_pending_exception (&error);
2858 ICALL_EXPORT gboolean
2859 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2863 if (!IS_MONOTYPE (type))
2866 if (type->type->byref)
2869 klass = mono_class_from_mono_type (type->type);
2870 return klass->generic_class != NULL || klass->generic_container != NULL;
2874 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2876 if (!IS_MONOTYPE (type))
2879 if (is_generic_parameter (type->type))
2880 return mono_type_get_generic_param_num (type->type);
2884 ICALL_EXPORT GenericParameterAttributes
2885 ves_icall_RuntimeType_GetGenericParameterAttributes (MonoReflectionType *type)
2887 g_assert (IS_MONOTYPE (type));
2888 g_assert (is_generic_parameter (type->type));
2889 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2892 ICALL_EXPORT MonoArray *
2893 ves_icall_RuntimeType_GetGenericParameterConstraints (MonoReflectionType *type)
2896 MonoReflectionType *rt;
2897 MonoGenericParamInfo *param_info;
2903 g_assert (IS_MONOTYPE (type));
2905 domain = mono_object_domain (type);
2906 param_info = mono_generic_param_info (type->type->data.generic_param);
2907 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2910 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, &error);
2911 if (mono_error_set_pending_exception (&error))
2913 for (i = 0; i < count; i++) {
2914 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2915 if (mono_error_set_pending_exception (&error))
2918 mono_array_setref (res, i, rt);
2925 ICALL_EXPORT MonoBoolean
2926 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2928 return is_generic_parameter (type->type);
2931 ICALL_EXPORT MonoBoolean
2932 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2934 return is_generic_parameter (tb->type.type);
2938 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2939 MonoReflectionType *t)
2941 enumtype->type = t->type;
2944 ICALL_EXPORT MonoReflectionMethod*
2945 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2946 MonoReflectionMethod* generic)
2953 MonoReflectionMethod *ret = NULL;
2955 domain = ((MonoObject *)type)->vtable->domain;
2957 klass = mono_class_from_mono_type (type->type);
2958 mono_class_init_checked (klass, &error);
2959 if (mono_error_set_pending_exception (&error))
2963 while ((method = mono_class_get_methods (klass, &iter))) {
2964 if (method->token == generic->method->token) {
2965 ret = mono_method_get_object_checked (domain, method, klass, &error);
2966 if (mono_error_set_pending_exception (&error))
2974 ICALL_EXPORT MonoReflectionMethod *
2975 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
2978 MonoType *type = ref_type->type;
2980 MonoReflectionMethod *ret = NULL;
2982 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2983 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2986 if (type->type == MONO_TYPE_VAR)
2989 method = mono_type_get_generic_param_owner (type)->owner.method;
2992 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2993 if (!mono_error_ok (&error))
2994 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2998 ICALL_EXPORT MonoBoolean
2999 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
3001 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3005 ICALL_EXPORT MonoBoolean
3006 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
3008 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3013 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
3015 MonoDomain *domain = mono_domain_get ();
3016 MonoImage *image = method->method->klass->image;
3017 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
3018 MonoTableInfo *tables = image->tables;
3019 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
3020 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
3021 guint32 im_cols [MONO_IMPLMAP_SIZE];
3022 guint32 scope_token;
3023 const char *import = NULL;
3024 const char *scope = NULL;
3026 if (image_is_dynamic (image)) {
3027 MonoReflectionMethodAux *method_aux =
3028 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
3030 import = method_aux->dllentry;
3031 scope = method_aux->dll;
3034 if (!import || !scope) {
3035 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
3040 if (piinfo->implmap_idx) {
3041 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
3043 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
3044 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
3045 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
3046 scope = mono_metadata_string_heap (image, scope_token);
3050 *flags = piinfo->piflags;
3051 *entry_point = mono_string_new (domain, import);
3052 *dll_name = mono_string_new (domain, scope);
3055 ICALL_EXPORT MonoReflectionMethod *
3056 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3058 MonoMethodInflated *imethod;
3060 MonoReflectionMethod *ret = NULL;
3063 if (method->method->is_generic)
3066 if (!method->method->is_inflated)
3069 imethod = (MonoMethodInflated *) method->method;
3071 result = imethod->declaring;
3072 /* Not a generic method. */
3073 if (!result->is_generic)
3076 if (image_is_dynamic (method->method->klass->image)) {
3077 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3078 MonoReflectionMethod *res;
3081 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3082 * the dynamic case as well ?
3084 mono_image_lock ((MonoImage*)image);
3085 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3086 mono_image_unlock ((MonoImage*)image);
3092 if (imethod->context.class_inst) {
3093 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3094 /*Generic methods gets the context of the GTD.*/
3095 if (mono_class_get_context (klass)) {
3096 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3097 if (!mono_error_ok (&error))
3102 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3104 if (!mono_error_ok (&error))
3105 mono_error_set_pending_exception (&error);
3109 ICALL_EXPORT gboolean
3110 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3112 return mono_method_signature (method->method)->generic_param_count != 0;
3115 ICALL_EXPORT gboolean
3116 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3118 return method->method->is_generic;
3121 ICALL_EXPORT MonoArray*
3122 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3125 MonoReflectionType *rt;
3130 domain = mono_object_domain (method);
3132 if (method->method->is_inflated) {
3133 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3136 count = inst->type_argc;
3137 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3138 if (mono_error_set_pending_exception (&error))
3141 for (i = 0; i < count; i++) {
3142 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3143 if (mono_error_set_pending_exception (&error))
3146 mono_array_setref (res, i, rt);
3153 count = mono_method_signature (method->method)->generic_param_count;
3154 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3155 if (mono_error_set_pending_exception (&error))
3158 for (i = 0; i < count; i++) {
3159 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3160 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3161 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3163 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3164 if (mono_error_set_pending_exception (&error))
3167 mono_array_setref (res, i, rt);
3173 ICALL_EXPORT MonoObject *
3174 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3178 * Invoke from reflection is supposed to always be a virtual call (the API
3179 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3180 * greater flexibility.
3182 MonoMethod *m = method->method;
3183 MonoMethodSignature *sig = mono_method_signature (m);
3186 void *obj = this_arg;
3190 if (mono_security_core_clr_enabled () &&
3191 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3192 mono_error_set_pending_exception (&error);
3196 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3197 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3198 mono_error_cleanup (&error); /* FIXME does this make sense? */
3199 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3204 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3205 if (!is_ok (&error)) {
3206 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3209 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3210 char *target_name = mono_type_get_full_name (m->klass);
3211 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3212 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3214 g_free (target_name);
3218 m = mono_object_get_virtual_method (this_arg, m);
3219 /* must pass the pointer to the value for valuetype methods */
3220 if (m->klass->valuetype)
3221 obj = mono_object_unbox (this_arg);
3222 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3223 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3228 if (sig->ret->byref) {
3229 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"));
3233 pcount = params? mono_array_length (params): 0;
3234 if (pcount != sig->param_count) {
3235 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3239 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3240 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."));
3244 image = m->klass->image;
3245 if (image->assembly->ref_only) {
3246 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."));
3250 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3251 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3255 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3259 intptr_t *lower_bounds;
3260 pcount = mono_array_length (params);
3261 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3262 /* Note: the synthetized array .ctors have int32 as argument type */
3263 for (i = 0; i < pcount; ++i)
3264 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3266 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3267 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3268 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3269 if (!mono_error_ok (&error)) {
3270 mono_error_set_pending_exception (&error);
3274 for (i = 0; i < mono_array_length (arr); ++i) {
3275 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3276 if (!mono_error_ok (&error)) {
3277 mono_error_set_pending_exception (&error);
3280 mono_array_setref_fast (arr, i, subarray);
3282 return (MonoObject*)arr;
3285 if (m->klass->rank == pcount) {
3286 /* Only lengths provided. */
3287 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3288 if (!mono_error_ok (&error)) {
3289 mono_error_set_pending_exception (&error);
3293 return (MonoObject*)arr;
3295 g_assert (pcount == (m->klass->rank * 2));
3296 /* The arguments are lower-bound-length pairs */
3297 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3299 for (i = 0; i < pcount / 2; ++i) {
3300 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3301 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3304 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3305 if (!mono_error_ok (&error)) {
3306 mono_error_set_pending_exception (&error);
3310 return (MonoObject*)arr;
3313 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3314 mono_error_set_pending_exception (&error);
3318 #ifndef DISABLE_REMOTING
3319 ICALL_EXPORT MonoObject *
3320 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3323 MonoDomain *domain = mono_object_domain (method);
3324 MonoMethod *m = method->method;
3325 MonoMethodSignature *sig = mono_method_signature (m);
3326 MonoArray *out_args;
3328 int i, j, outarg_count = 0;
3330 if (m->klass == mono_defaults.object_class) {
3331 if (!strcmp (m->name, "FieldGetter")) {
3332 MonoClass *k = this_arg->vtable->klass;
3336 /* If this is a proxy, then it must be a CBO */
3337 if (k == mono_defaults.transparent_proxy_class) {
3338 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3339 this_arg = tp->rp->unwrapped_server;
3340 g_assert (this_arg);
3341 k = this_arg->vtable->klass;
3344 name = mono_array_get (params, MonoString *, 1);
3345 str = mono_string_to_utf8_checked (name, &error);
3346 if (mono_error_set_pending_exception (&error))
3350 MonoClassField* field = mono_class_get_field_from_name (k, str);
3353 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3354 if (field_klass->valuetype) {
3355 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3356 if (mono_error_set_pending_exception (&error))
3359 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3361 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3362 if (mono_error_set_pending_exception (&error))
3364 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3365 mono_array_setref (out_args, 0, result);
3372 g_assert_not_reached ();
3374 } else if (!strcmp (m->name, "FieldSetter")) {
3375 MonoClass *k = this_arg->vtable->klass;
3381 /* If this is a proxy, then it must be a CBO */
3382 if (k == mono_defaults.transparent_proxy_class) {
3383 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3384 this_arg = tp->rp->unwrapped_server;
3385 g_assert (this_arg);
3386 k = this_arg->vtable->klass;
3389 name = mono_array_get (params, MonoString *, 1);
3390 str = mono_string_to_utf8_checked (name, &error);
3391 if (mono_error_set_pending_exception (&error))
3395 MonoClassField* field = mono_class_get_field_from_name (k, str);
3398 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3399 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3401 if (field_klass->valuetype) {
3402 size = mono_type_size (field->type, &align);
3403 g_assert (size == mono_class_value_size (field_klass, NULL));
3404 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3406 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3409 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3410 if (mono_error_set_pending_exception (&error))
3412 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3421 g_assert_not_reached ();
3426 for (i = 0; i < mono_array_length (params); i++) {
3427 if (sig->params [i]->byref)
3431 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3432 if (mono_error_set_pending_exception (&error))
3435 /* handle constructors only for objects already allocated */
3436 if (!strcmp (method->method->name, ".ctor"))
3437 g_assert (this_arg);
3439 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3440 g_assert (!method->method->klass->valuetype);
3441 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3442 if (mono_error_set_pending_exception (&error))
3445 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3446 if (sig->params [i]->byref) {
3448 arg = mono_array_get (params, gpointer, i);
3449 mono_array_setref (out_args, j, arg);
3454 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3461 read_enum_value (const char *mem, int type)
3464 case MONO_TYPE_BOOLEAN:
3466 return *(guint8*)mem;
3468 return *(gint8*)mem;
3469 case MONO_TYPE_CHAR:
3471 return read16 (mem);
3473 return (gint16) read16 (mem);
3475 return read32 (mem);
3477 return (gint32) read32 (mem);
3480 return read64 (mem);
3482 g_assert_not_reached ();
3488 write_enum_value (char *mem, int type, guint64 value)
3492 case MONO_TYPE_I1: {
3493 guint8 *p = (guint8*)mem;
3499 case MONO_TYPE_CHAR: {
3500 guint16 *p = (guint16 *)mem;
3505 case MONO_TYPE_I4: {
3506 guint32 *p = (guint32 *)mem;
3511 case MONO_TYPE_I8: {
3512 guint64 *p = (guint64 *)mem;
3517 g_assert_not_reached ();
3522 ICALL_EXPORT MonoObject *
3523 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3531 domain = mono_object_domain (enumType);
3532 enumc = mono_class_from_mono_type (enumType->type);
3534 mono_class_init_checked (enumc, &error);
3535 if (mono_error_set_pending_exception (&error))
3538 etype = mono_class_enum_basetype (enumc);
3540 res = mono_object_new_checked (domain, enumc, &error);
3541 if (mono_error_set_pending_exception (&error))
3543 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3548 ICALL_EXPORT MonoBoolean
3549 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3551 int size = mono_class_value_size (a->vtable->klass, NULL);
3552 guint64 a_val = 0, b_val = 0;
3554 memcpy (&a_val, mono_object_unbox (a), size);
3555 memcpy (&b_val, mono_object_unbox (b), size);
3557 return (a_val & b_val) == b_val;
3560 ICALL_EXPORT MonoObject *
3561 ves_icall_System_Enum_get_value (MonoObject *eobj)
3573 g_assert (eobj->vtable->klass->enumtype);
3575 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3576 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3577 if (mono_error_set_pending_exception (&error))
3579 dst = (char *)res + sizeof (MonoObject);
3580 src = (char *)eobj + sizeof (MonoObject);
3581 size = mono_class_value_size (enumc, NULL);
3583 memcpy (dst, src, size);
3588 ICALL_EXPORT MonoReflectionType *
3589 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3592 MonoReflectionType *ret;
3596 klass = mono_class_from_mono_type (type->type);
3597 mono_class_init_checked (klass, &error);
3598 if (mono_error_set_pending_exception (&error))
3601 etype = mono_class_enum_basetype (klass);
3603 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3607 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3608 mono_error_set_pending_exception (&error);
3614 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3616 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3617 gpointer odata = (char *)other + sizeof (MonoObject);
3618 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3619 g_assert (basetype);
3624 if (eobj->vtable->klass != other->vtable->klass)
3627 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3628 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3629 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3632 return me > other ? 1 : -1; \
3635 switch (basetype->type) {
3637 COMPARE_ENUM_VALUES (guint8);
3639 COMPARE_ENUM_VALUES (gint8);
3640 case MONO_TYPE_CHAR:
3642 COMPARE_ENUM_VALUES (guint16);
3644 COMPARE_ENUM_VALUES (gint16);
3646 COMPARE_ENUM_VALUES (guint32);
3648 COMPARE_ENUM_VALUES (gint32);
3650 COMPARE_ENUM_VALUES (guint64);
3652 COMPARE_ENUM_VALUES (gint64);
3656 #undef COMPARE_ENUM_VALUES
3657 /* indicates that the enum was of an unsupported unerlying type */
3662 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3664 gpointer data = (char *)eobj + sizeof (MonoObject);
3665 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3666 g_assert (basetype);
3668 switch (basetype->type) {
3669 case MONO_TYPE_I1: {
3670 gint8 value = *((gint8*)data);
3671 return ((int)value ^ (int)value << 8);
3674 return *((guint8*)data);
3675 case MONO_TYPE_CHAR:
3677 return *((guint16*)data);
3679 case MONO_TYPE_I2: {
3680 gint16 value = *((gint16*)data);
3681 return ((int)(guint16)value | (((int)value) << 16));
3684 return *((guint32*)data);
3686 return *((gint32*)data);
3688 case MONO_TYPE_I8: {
3689 gint64 value = *((gint64*)data);
3690 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3693 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3698 ICALL_EXPORT MonoBoolean
3699 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3702 MonoDomain *domain = mono_object_domain (type);
3703 MonoClass *enumc = mono_class_from_mono_type (type->type);
3704 guint j = 0, nvalues;
3706 MonoClassField *field;
3708 guint64 field_value, previous_value = 0;
3709 gboolean sorted = TRUE;
3711 mono_class_init_checked (enumc, &error);
3712 if (mono_error_set_pending_exception (&error))
3716 if (!enumc->enumtype) {
3717 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3721 base_type = mono_class_enum_basetype (enumc)->type;
3723 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3724 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3725 if (mono_error_set_pending_exception (&error))
3727 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3728 if (mono_error_set_pending_exception (&error))
3732 while ((field = mono_class_get_fields (enumc, &iter))) {
3734 MonoTypeEnum def_type;
3736 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3738 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3740 if (mono_field_is_deleted (field))
3742 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3744 p = mono_class_get_field_default_value (field, &def_type);
3745 /* len = */ mono_metadata_decode_blob_size (p, &p);
3747 field_value = read_enum_value (p, base_type);
3748 mono_array_set (*values, guint64, j, field_value);
3750 if (previous_value > field_value)
3753 previous_value = field_value;
3761 BFLAGS_IgnoreCase = 1,
3762 BFLAGS_DeclaredOnly = 2,
3763 BFLAGS_Instance = 4,
3765 BFLAGS_Public = 0x10,
3766 BFLAGS_NonPublic = 0x20,
3767 BFLAGS_FlattenHierarchy = 0x40,
3768 BFLAGS_InvokeMethod = 0x100,
3769 BFLAGS_CreateInstance = 0x200,
3770 BFLAGS_GetField = 0x400,
3771 BFLAGS_SetField = 0x800,
3772 BFLAGS_GetProperty = 0x1000,
3773 BFLAGS_SetProperty = 0x2000,
3774 BFLAGS_ExactBinding = 0x10000,
3775 BFLAGS_SuppressChangeType = 0x20000,
3776 BFLAGS_OptionalParamBinding = 0x40000
3779 ICALL_EXPORT MonoArray*
3780 ves_icall_RuntimeType_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3784 MonoClass *startklass, *klass, *refklass;
3789 char *utf8_name = NULL;
3790 int (*compare_func) (const char *s1, const char *s2) = NULL;
3791 MonoClassField *field;
3792 MonoPtrArray tmp_array;
3794 domain = ((MonoObject *)type)->vtable->domain;
3795 if (type->type->byref) {
3796 MonoArray *result = mono_array_new_checked (domain, mono_defaults.field_info_class, 0, &error);
3797 mono_error_set_pending_exception (&error);
3801 klass = startklass = mono_class_from_mono_type (type->type);
3802 refklass = mono_class_from_mono_type (reftype->type);
3804 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3807 if (mono_class_has_failure (klass)) {
3808 mono_ptr_array_destroy (tmp_array);
3809 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3814 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3815 guint32 flags = mono_field_get_flags (field);
3817 if (mono_field_is_deleted_with_flags (field, flags))
3819 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3820 if (bflags & BFLAGS_Public)
3822 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3823 if (bflags & BFLAGS_NonPublic) {
3830 if (flags & FIELD_ATTRIBUTE_STATIC) {
3831 if (bflags & BFLAGS_Static)
3832 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3835 if (bflags & BFLAGS_Instance)
3843 if (utf8_name == NULL) {
3844 utf8_name = mono_string_to_utf8_checked (name, &error);
3845 if (!is_ok (&error))
3847 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3850 if (compare_func (mono_field_get_name (field), utf8_name))
3854 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3855 if (!mono_error_ok (&error))
3857 mono_ptr_array_append (tmp_array, member);
3859 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3862 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array), &error);
3863 if (!is_ok (&error))
3866 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3867 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3869 mono_ptr_array_destroy (tmp_array);
3871 if (utf8_name != NULL)
3876 mono_ptr_array_destroy (tmp_array);
3877 mono_error_set_pending_exception (&error);
3882 method_nonpublic (MonoMethod* method, gboolean start_klass)
3884 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3885 case METHOD_ATTRIBUTE_ASSEM:
3886 return (start_klass || mono_defaults.generic_ilist_class);
3887 case METHOD_ATTRIBUTE_PRIVATE:
3889 case METHOD_ATTRIBUTE_PUBLIC:
3897 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3900 MonoClass *startklass;
3904 /*FIXME, use MonoBitSet*/
3905 guint32 method_slots_default [8];
3906 guint32 *method_slots = NULL;
3907 int (*compare_func) (const char *s1, const char *s2) = NULL;
3909 array = g_ptr_array_new ();
3914 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3916 /* An optimization for calls made from Delegate:CreateDelegate () */
3917 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3918 method = mono_get_delegate_invoke (klass);
3921 g_ptr_array_add (array, method);
3925 mono_class_setup_methods (klass);
3926 mono_class_setup_vtable (klass);
3927 if (mono_class_has_failure (klass))
3930 if (is_generic_parameter (&klass->byval_arg))
3931 nslots = mono_class_get_vtable_size (klass->parent);
3933 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3934 if (nslots >= sizeof (method_slots_default) * 8) {
3935 method_slots = g_new0 (guint32, nslots / 32 + 1);
3937 method_slots = method_slots_default;
3938 memset (method_slots, 0, sizeof (method_slots_default));
3941 mono_class_setup_methods (klass);
3942 mono_class_setup_vtable (klass);
3943 if (mono_class_has_failure (klass))
3947 while ((method = mono_class_get_methods (klass, &iter))) {
3949 if (method->slot != -1) {
3950 g_assert (method->slot < nslots);
3951 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3953 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3954 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3957 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3959 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3960 if (bflags & BFLAGS_Public)
3962 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3968 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3969 if (bflags & BFLAGS_Static)
3970 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3973 if (bflags & BFLAGS_Instance)
3981 if (compare_func (name, method->name))
3986 g_ptr_array_add (array, method);
3988 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3990 if (method_slots != method_slots_default)
3991 g_free (method_slots);
3996 if (method_slots != method_slots_default)
3997 g_free (method_slots);
3998 g_ptr_array_free (array, TRUE);
4000 if (mono_class_has_failure (klass)) {
4001 *ex = mono_class_get_exception_for_failure (klass);
4003 *ex = mono_get_exception_execution_engine ("Unknown error");
4008 ICALL_EXPORT MonoArray*
4009 ves_icall_RuntimeType_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4011 static MonoClass *MethodInfo_array;
4015 MonoVTable *array_vtable;
4016 MonoException *ex = NULL;
4017 const char *mname = NULL;
4018 GPtrArray *method_array;
4019 MonoClass *klass, *refklass;
4022 mono_error_init (&error);
4024 if (!MethodInfo_array) {
4025 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
4026 mono_memory_barrier ();
4027 MethodInfo_array = klass;
4030 klass = mono_class_from_mono_type (type->type);
4031 refklass = mono_class_from_mono_type (reftype->type);
4032 domain = ((MonoObject *)type)->vtable->domain;
4033 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
4034 if (!is_ok (&error)) {
4035 mono_error_set_pending_exception (&error);
4038 if (type->type->byref) {
4039 res = mono_array_new_specific_checked (array_vtable, 0, &error);
4040 mono_error_set_pending_exception (&error);
4046 mname = mono_string_to_utf8_checked (name, &error);
4047 if (mono_error_set_pending_exception (&error))
4051 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
4052 g_free ((char*)mname);
4054 mono_set_pending_exception (ex);
4058 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
4059 if (!mono_error_ok (&error)) {
4060 mono_error_set_pending_exception (&error);
4064 for (i = 0; i < method_array->len; ++i) {
4065 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
4066 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
4067 if (!mono_error_ok (&error))
4069 mono_array_setref (res, i, rm);
4073 g_ptr_array_free (method_array, TRUE);
4074 if (!mono_error_ok (&error))
4075 mono_set_pending_exception (mono_error_convert_to_exception (&error));
4079 ICALL_EXPORT MonoArray*
4080 ves_icall_RuntimeType_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4083 MonoClass *startklass, *klass, *refklass;
4084 MonoArray *res = NULL;
4088 gpointer iter = NULL;
4089 MonoPtrArray tmp_array;
4092 domain = ((MonoObject *)type)->vtable->domain;
4093 if (type->type->byref) {
4094 res = mono_array_new_cached (domain, mono_defaults.method_info_class, 0, &error);
4095 mono_error_set_pending_exception (&error);
4099 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
4102 klass = startklass = mono_class_from_mono_type (type->type);
4103 refklass = mono_class_from_mono_type (reftype->type);
4105 mono_class_setup_methods (klass);
4106 if (mono_class_has_failure (klass)) {
4107 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
4112 while ((method = mono_class_get_methods (klass, &iter))) {
4114 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
4116 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4117 if (bflags & BFLAGS_Public)
4120 if (bflags & BFLAGS_NonPublic)
4126 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4127 if (bflags & BFLAGS_Static)
4128 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4131 if (bflags & BFLAGS_Instance)
4137 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
4138 if (mono_error_set_pending_exception (&error))
4141 mono_ptr_array_append (tmp_array, member);
4144 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array), &error);
4145 if (mono_error_set_pending_exception (&error))
4148 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4149 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4152 mono_ptr_array_destroy (tmp_array);
4158 property_hash (gconstpointer data)
4160 MonoProperty *prop = (MonoProperty*)data;
4162 return g_str_hash (prop->name);
4166 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
4168 if (method1->slot != -1 && method1->slot == method2->slot)
4171 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
4172 if (method1->is_inflated)
4173 method1 = ((MonoMethodInflated*) method1)->declaring;
4174 if (method2->is_inflated)
4175 method2 = ((MonoMethodInflated*) method2)->declaring;
4178 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4182 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4184 // Properties are hide-by-name-and-signature
4185 if (!g_str_equal (prop1->name, prop2->name))
4188 /* If we see a property in a generic method, we want to
4189 compare the generic signatures, not the inflated signatures
4190 because we might conflate two properties that were
4194 public T this[T t] { getter { return t; } } // method 1
4195 public U this[U u] { getter { return u; } } // method 2
4198 If we see int Foo<int,int>::Item[int] we need to know if
4199 the indexer came from method 1 or from method 2, and we
4200 shouldn't conflate them. (Bugzilla 36283)
4202 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4205 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4212 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4217 return method_nonpublic (accessor, start_klass);
4220 ICALL_EXPORT MonoArray*
4221 ves_icall_RuntimeType_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4225 MonoClass *startklass, *klass;
4231 gchar *propname = NULL;
4232 int (*compare_func) (const char *s1, const char *s2) = NULL;
4234 GHashTable *properties = NULL;
4235 MonoPtrArray tmp_array;
4237 mono_error_init (&error);
4239 domain = ((MonoObject *)type)->vtable->domain;
4240 if (type->type->byref) {
4241 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), 0, &error);
4242 mono_error_set_pending_exception (&error);
4246 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4248 klass = startklass = mono_class_from_mono_type (type->type);
4251 propname = mono_string_to_utf8_checked (name, &error);
4252 if (mono_error_set_pending_exception (&error))
4254 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4257 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4259 mono_class_setup_methods (klass);
4260 mono_class_setup_vtable (klass);
4261 if (mono_class_has_failure (klass))
4265 while ((prop = mono_class_get_properties (klass, &iter))) {
4271 flags = method->flags;
4274 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4275 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4276 if (bflags & BFLAGS_Public)
4278 } else if (bflags & BFLAGS_NonPublic) {
4279 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4280 property_accessor_nonpublic(prop->set, startklass == klass)) {
4287 if (flags & METHOD_ATTRIBUTE_STATIC) {
4288 if (bflags & BFLAGS_Static)
4289 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4292 if (bflags & BFLAGS_Instance)
4301 if (compare_func (propname, prop->name))
4305 if (g_hash_table_lookup (properties, prop))
4308 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4311 mono_ptr_array_append (tmp_array, pr);
4313 g_hash_table_insert (properties, prop, prop);
4315 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4318 g_hash_table_destroy (properties);
4321 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array), &error);
4322 if (!is_ok (&error))
4324 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4325 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4327 mono_ptr_array_destroy (tmp_array);
4334 if (mono_class_has_failure (klass))
4335 mono_error_set_for_class_failure (&error, klass);
4339 g_hash_table_destroy (properties);
4342 mono_ptr_array_destroy (tmp_array);
4344 mono_error_set_pending_exception (&error);
4350 event_hash (gconstpointer data)
4352 MonoEvent *event = (MonoEvent*)data;
4354 return g_str_hash (event->name);
4358 event_equal (MonoEvent *event1, MonoEvent *event2)
4360 // Events are hide-by-name
4361 return g_str_equal (event1->name, event2->name);
4364 ICALL_EXPORT MonoArray*
4365 ves_icall_RuntimeType_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4369 MonoClass *startklass, *klass;
4375 char *utf8_name = NULL;
4376 int (*compare_func) (const char *s1, const char *s2) = NULL;
4377 GHashTable *events = NULL;
4378 MonoPtrArray tmp_array;
4380 mono_error_init (&error);
4382 domain = mono_object_domain (type);
4383 if (type->type->byref) {
4384 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), 0, &error);
4385 mono_error_set_pending_exception (&error);
4389 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4391 klass = startklass = mono_class_from_mono_type (type->type);
4393 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4395 mono_class_setup_methods (klass);
4396 mono_class_setup_vtable (klass);
4397 if (mono_class_has_failure (klass))
4401 while ((event = mono_class_get_events (klass, &iter))) {
4403 method = event->add;
4405 method = event->remove;
4407 method = event->raise;
4409 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4410 if (bflags & BFLAGS_Public)
4412 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4413 if (bflags & BFLAGS_NonPublic)
4418 if (bflags & BFLAGS_NonPublic)
4424 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4425 if (bflags & BFLAGS_Static)
4426 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4429 if (bflags & BFLAGS_Instance)
4434 if (bflags & BFLAGS_Instance)
4440 if (utf8_name == NULL) {
4441 utf8_name = mono_string_to_utf8_checked (name, &error);
4442 if (!is_ok (&error))
4444 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4447 if (compare_func (event->name, utf8_name))
4451 if (g_hash_table_lookup (events, event))
4454 MonoReflectionEvent *ev_obj;
4455 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4458 mono_ptr_array_append (tmp_array, ev_obj);
4460 g_hash_table_insert (events, event, event);
4462 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4465 g_hash_table_destroy (events);
4467 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array), &error);
4468 if (!is_ok (&error))
4471 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4472 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4474 mono_ptr_array_destroy (tmp_array);
4476 if (utf8_name != NULL)
4482 if (mono_class_has_failure (klass))
4483 mono_error_set_for_class_failure (&error, klass);
4488 g_hash_table_destroy (events);
4489 if (utf8_name != NULL)
4492 mono_ptr_array_destroy (tmp_array);
4494 mono_error_set_pending_exception (&error);
4498 ICALL_EXPORT MonoArray*
4499 ves_icall_RuntimeType_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4502 MonoReflectionType *rt;
4505 MonoArray *res = NULL;
4510 MonoPtrArray tmp_array;
4512 mono_error_init (&error);
4514 domain = ((MonoObject *)type)->vtable->domain;
4515 if (type->type->byref) {
4516 MonoArray *result = mono_array_new_cached (domain, mono_defaults.runtimetype_class, 0, &error);
4517 mono_error_set_pending_exception (&error);
4520 klass = mono_class_from_mono_type (type->type);
4523 * If a nested type is generic, return its generic type definition.
4524 * Note that this means that the return value is essentially the set
4525 * of nested types of the generic type definition of @klass.
4527 * A note in MSDN claims that a generic type definition can have
4528 * nested types that aren't generic. In any case, the container of that
4529 * nested type would be the generic type definition.
4531 if (klass->generic_class)
4532 klass = klass->generic_class->container_class;
4534 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4536 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4538 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4539 if (bflags & BFLAGS_Public)
4542 if (bflags & BFLAGS_NonPublic)
4550 str = mono_string_to_utf8_checked (name, &error);
4551 if (!is_ok (&error))
4553 mono_identifier_unescape_type_name_chars (str);
4556 if (strcmp (nested->name, str))
4560 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4561 if (!is_ok (&error))
4564 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4567 res = mono_array_new_cached (domain, mono_defaults.runtimetype_class, mono_ptr_array_size (tmp_array), &error);
4568 if (!is_ok (&error))
4571 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4572 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4575 mono_ptr_array_destroy (tmp_array);
4579 mono_error_set_pending_exception (&error);
4583 ICALL_EXPORT MonoReflectionType*
4584 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4587 MonoReflectionType *ret;
4589 MonoType *type = NULL;
4590 MonoTypeNameParse info;
4591 gboolean type_resolve;
4593 /* On MS.NET, this does not fire a TypeResolve event */
4594 type_resolve = TRUE;
4595 str = mono_string_to_utf8_checked (name, &error);
4596 if (mono_error_set_pending_exception (&error))
4598 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4599 if (!mono_reflection_parse_type (str, &info)) {
4601 mono_reflection_free_type_info (&info);
4603 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4606 /*g_print ("failed parse\n");*/
4610 if (info.assembly.name) {
4612 mono_reflection_free_type_info (&info);
4614 /* 1.0 and 2.0 throw different exceptions */
4615 if (mono_defaults.generic_ilist_class)
4616 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4618 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4624 if (module != NULL) {
4625 if (module->image) {
4626 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4627 if (!is_ok (&error)) {
4629 mono_reflection_free_type_info (&info);
4630 mono_error_set_pending_exception (&error);
4637 if (assembly_is_dynamic (assembly->assembly)) {
4638 /* Enumerate all modules */
4639 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4643 if (abuilder->modules) {
4644 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4645 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4646 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4647 if (!is_ok (&error)) {
4649 mono_reflection_free_type_info (&info);
4650 mono_error_set_pending_exception (&error);
4658 if (!type && abuilder->loaded_modules) {
4659 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4660 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4661 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4662 if (!is_ok (&error)) {
4664 mono_reflection_free_type_info (&info);
4665 mono_error_set_pending_exception (&error);
4674 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4675 if (!is_ok (&error)) {
4677 mono_reflection_free_type_info (&info);
4678 mono_error_set_pending_exception (&error);
4683 mono_reflection_free_type_info (&info);
4685 MonoException *e = NULL;
4688 e = mono_get_exception_type_load (name, NULL);
4691 mono_set_pending_exception (e);
4695 if (type->type == MONO_TYPE_CLASS) {
4696 MonoClass *klass = mono_type_get_class (type);
4698 /* need to report exceptions ? */
4699 if (throwOnError && mono_class_has_failure (klass)) {
4700 /* report SecurityException (or others) that occured when loading the assembly */
4701 MonoException *exc = mono_class_get_exception_for_failure (klass);
4702 mono_set_pending_exception (exc);
4707 /* g_print ("got it\n"); */
4708 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4709 mono_error_set_pending_exception (&error);
4715 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4718 gchar *shadow_ini_file;
4721 /* Check for shadow-copied assembly */
4722 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4723 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4725 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4726 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4732 g_free (shadow_ini_file);
4733 if (content != NULL) {
4736 *filename = content;
4743 ICALL_EXPORT MonoString *
4744 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4746 MonoDomain *domain = mono_object_domain (assembly);
4747 MonoAssembly *mass = assembly->assembly;
4748 MonoString *res = NULL;
4753 if (g_path_is_absolute (mass->image->name)) {
4754 absolute = g_strdup (mass->image->name);
4755 dirname = g_path_get_dirname (absolute);
4757 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4758 dirname = g_strdup (mass->basedir);
4761 replace_shadow_path (domain, dirname, &absolute);
4766 for (i = strlen (absolute) - 1; i >= 0; i--)
4767 if (absolute [i] == '\\')
4772 uri = g_filename_to_uri (absolute, NULL, NULL);
4774 const char *prepend = "file://";
4776 if (*absolute == '/' && *(absolute + 1) == '/') {
4779 prepend = "file:///";
4782 uri = g_strconcat (prepend, absolute, NULL);
4786 res = mono_string_new (domain, uri);
4793 ICALL_EXPORT MonoBoolean
4794 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4796 MonoAssembly *mass = assembly->assembly;
4798 return mass->in_gac;
4801 ICALL_EXPORT MonoReflectionAssembly*
4802 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4807 MonoImageOpenStatus status;
4808 MonoReflectionAssembly* result = NULL;
4810 name = mono_string_to_utf8_checked (mname, &error);
4811 if (mono_error_set_pending_exception (&error))
4813 res = mono_assembly_load_with_partial_name (name, &status);
4819 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4821 mono_error_set_pending_exception (&error);
4825 ICALL_EXPORT MonoString *
4826 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4828 MonoDomain *domain = mono_object_domain (assembly);
4831 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4836 ICALL_EXPORT MonoBoolean
4837 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4839 return assembly->assembly->ref_only;
4842 ICALL_EXPORT MonoString *
4843 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4845 MonoDomain *domain = mono_object_domain (assembly);
4847 return mono_string_new (domain, assembly->assembly->image->version);
4850 ICALL_EXPORT MonoReflectionMethod*
4851 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4854 MonoReflectionMethod *res = NULL;
4857 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4861 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4862 if (!mono_error_ok (&error))
4865 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4868 if (!mono_error_ok (&error))
4869 mono_error_set_pending_exception (&error);
4873 ICALL_EXPORT MonoReflectionModule*
4874 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4877 MonoReflectionModule *result = NULL;
4878 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4879 if (!mono_error_ok (&error))
4880 mono_error_set_pending_exception (&error);
4884 ICALL_EXPORT MonoArray*
4885 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4888 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4889 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4890 if (mono_error_set_pending_exception (&error))
4895 for (i = 0; i < table->rows; ++i) {
4896 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4897 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4903 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4905 static MonoMethod *create_version = NULL;
4909 mono_error_init (error);
4912 if (!create_version) {
4913 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4914 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4915 g_assert (create_version);
4916 mono_method_desc_free (desc);
4922 args [3] = &revision;
4923 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4924 return_val_if_nok (error, NULL);
4926 mono_runtime_invoke_checked (create_version, result, args, error);
4927 return_val_if_nok (error, NULL);
4932 ICALL_EXPORT MonoArray*
4933 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4937 MonoDomain *domain = mono_object_domain (assembly);
4939 static MonoMethod *create_culture = NULL;
4940 MonoImage *image = assembly->assembly->image;
4944 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4947 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4948 if (mono_error_set_pending_exception (&error))
4952 if (count > 0 && !create_culture) {
4953 MonoMethodDesc *desc = mono_method_desc_new (
4954 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4955 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4956 g_assert (create_culture);
4957 mono_method_desc_free (desc);
4960 for (i = 0; i < count; i++) {
4961 MonoObject *version;
4962 MonoReflectionAssemblyName *aname;
4963 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4965 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4967 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4968 domain, mono_class_get_assembly_name_class (), &error);
4969 if (mono_error_set_pending_exception (&error))
4972 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4974 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4975 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4976 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4977 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4978 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4979 aname->versioncompat = 1; /* SameMachine (default) */
4980 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4982 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4983 if (mono_error_set_pending_exception (&error))
4986 MONO_OBJECT_SETREF (aname, version, version);
4988 if (create_culture) {
4990 MonoBoolean assembly_ref = 1;
4991 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4992 args [1] = &assembly_ref;
4994 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4995 if (mono_error_set_pending_exception (&error))
4998 MONO_OBJECT_SETREF (aname, cultureInfo, o);
5001 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
5002 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
5003 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5005 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
5006 /* public key token isn't copied - the class library will
5007 automatically generate it from the public key if required */
5008 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
5009 if (mono_error_set_pending_exception (&error))
5012 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5013 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
5015 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
5016 if (mono_error_set_pending_exception (&error))
5019 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5020 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
5023 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
5024 if (mono_error_set_pending_exception (&error))
5027 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5030 /* note: this function doesn't return the codebase on purpose (i.e. it can
5031 be used under partial trust as path information isn't present). */
5033 mono_array_setref (result, i, aname);
5038 /* move this in some file in mono/util/ */
5040 g_concat_dir_and_file (const char *dir, const char *file)
5042 g_return_val_if_fail (dir != NULL, NULL);
5043 g_return_val_if_fail (file != NULL, NULL);
5046 * If the directory name doesn't have a / on the end, we need
5047 * to add one so we get a proper path to the file
5049 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
5050 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
5052 return g_strconcat (dir, file, NULL);
5056 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
5059 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5061 guint32 cols [MONO_MANIFEST_SIZE];
5062 guint32 impl, file_idx;
5066 char *n = mono_string_to_utf8_checked (name, &error);
5067 if (mono_error_set_pending_exception (&error))
5070 for (i = 0; i < table->rows; ++i) {
5071 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5072 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5073 if (strcmp (val, n) == 0)
5077 if (i == table->rows)
5080 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
5083 * this code should only be called after obtaining the
5084 * ResourceInfo and handling the other cases.
5086 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
5087 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
5089 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
5094 module = assembly->assembly->image;
5097 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
5098 if (mono_error_set_pending_exception (&error))
5100 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
5102 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
5105 ICALL_EXPORT gboolean
5106 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
5109 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5111 guint32 cols [MONO_MANIFEST_SIZE];
5112 guint32 file_cols [MONO_FILE_SIZE];
5116 n = mono_string_to_utf8_checked (name, &error);
5117 if (mono_error_set_pending_exception (&error))
5119 for (i = 0; i < table->rows; ++i) {
5120 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5121 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5122 if (strcmp (val, n) == 0)
5126 if (i == table->rows)
5129 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
5130 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
5133 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
5134 case MONO_IMPLEMENTATION_FILE:
5135 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5136 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5137 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
5138 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
5139 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
5140 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
5143 info->location = RESOURCE_LOCATION_EMBEDDED;
5146 case MONO_IMPLEMENTATION_ASSEMBLYREF:
5147 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5148 mono_assembly_load_reference (assembly->assembly->image, i - 1);
5149 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
5150 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
5151 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
5153 mono_set_pending_exception (ex);
5156 MonoReflectionAssembly *assm_obj;
5157 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5159 mono_error_set_pending_exception (&error);
5162 MONO_OBJECT_SETREF (info, assembly, assm_obj);
5164 /* Obtain info recursively */
5165 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5166 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5169 case MONO_IMPLEMENTATION_EXP_TYPE:
5170 g_assert_not_reached ();
5178 ICALL_EXPORT MonoObject*
5179 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
5182 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5183 MonoArray *result = NULL;
5188 /* check hash if needed */
5190 n = mono_string_to_utf8_checked (name, &error);
5191 if (mono_error_set_pending_exception (&error))
5194 for (i = 0; i < table->rows; ++i) {
5195 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5196 if (strcmp (val, n) == 0) {
5199 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5200 fn = mono_string_new (mono_object_domain (assembly), n);
5202 return (MonoObject*)fn;
5210 for (i = 0; i < table->rows; ++i) {
5211 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5215 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
5216 if (mono_error_set_pending_exception (&error))
5221 for (i = 0; i < table->rows; ++i) {
5222 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5223 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5224 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5225 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5230 return (MonoObject*)result;
5233 ICALL_EXPORT MonoArray*
5234 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5237 MonoDomain *domain = mono_domain_get();
5240 int i, j, file_count = 0;
5241 MonoImage **modules;
5242 guint32 module_count, real_module_count;
5243 MonoTableInfo *table;
5244 guint32 cols [MONO_FILE_SIZE];
5245 MonoImage *image = assembly->assembly->image;
5247 g_assert (image != NULL);
5248 g_assert (!assembly_is_dynamic (assembly->assembly));
5250 table = &image->tables [MONO_TABLE_FILE];
5251 file_count = table->rows;
5253 modules = image->modules;
5254 module_count = image->module_count;
5256 real_module_count = 0;
5257 for (i = 0; i < module_count; ++i)
5259 real_module_count ++;
5261 klass = mono_class_get_module_class ();
5262 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5263 if (mono_error_set_pending_exception (&error))
5266 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5267 if (mono_error_set_pending_exception (&error))
5270 mono_array_setref (res, 0, image_obj);
5272 for (i = 0; i < module_count; ++i)
5274 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5275 if (mono_error_set_pending_exception (&error))
5277 mono_array_setref (res, j, rm);
5281 for (i = 0; i < file_count; ++i, ++j) {
5282 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5283 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5284 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5285 if (mono_error_set_pending_exception (&error))
5287 mono_array_setref (res, j, rm);
5290 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5292 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5293 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5296 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5297 if (mono_error_set_pending_exception (&error))
5299 mono_array_setref (res, j, rm);
5306 ICALL_EXPORT MonoReflectionMethod*
5307 ves_icall_GetCurrentMethod (void)
5309 MonoReflectionMethod *res = NULL;
5312 MonoMethod *m = mono_method_get_last_managed ();
5315 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5319 while (m->is_inflated)
5320 m = ((MonoMethodInflated*)m)->declaring;
5322 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5323 mono_error_set_pending_exception (&error);
5329 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5332 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5335 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5336 //method is inflated, we should inflate it on the other class
5337 MonoGenericContext ctx;
5338 ctx.method_inst = inflated->context.method_inst;
5339 ctx.class_inst = inflated->context.class_inst;
5340 if (klass->generic_class)
5341 ctx.class_inst = klass->generic_class->context.class_inst;
5342 else if (klass->generic_container)
5343 ctx.class_inst = klass->generic_container->context.class_inst;
5344 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5345 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5349 mono_class_setup_methods (method->klass);
5350 if (mono_class_has_failure (method->klass))
5352 for (i = 0; i < method->klass->method.count; ++i) {
5353 if (method->klass->methods [i] == method) {
5358 mono_class_setup_methods (klass);
5359 if (mono_class_has_failure (klass))
5361 g_assert (offset >= 0 && offset < klass->method.count);
5362 return klass->methods [offset];
5365 ICALL_EXPORT MonoReflectionMethod*
5366 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5368 MonoReflectionMethod *res = NULL;
5372 klass = mono_class_from_mono_type (type);
5373 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5375 if (method->klass != klass) {
5376 method = mono_method_get_equivalent_method (method, klass);
5381 klass = method->klass;
5382 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5383 mono_error_set_pending_exception (&error);
5387 ICALL_EXPORT MonoReflectionMethodBody*
5388 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5391 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5392 mono_error_set_pending_exception (&error);
5396 ICALL_EXPORT MonoReflectionAssembly*
5397 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5400 MonoReflectionAssembly *result;
5401 MonoMethod *dest = NULL;
5403 mono_stack_walk_no_il (get_executing, &dest);
5405 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5407 mono_error_set_pending_exception (&error);
5412 ICALL_EXPORT MonoReflectionAssembly*
5413 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5416 MonoReflectionAssembly *result;
5417 MonoDomain* domain = mono_domain_get ();
5419 if (!domain->entry_assembly)
5422 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5424 mono_error_set_pending_exception (&error);
5428 ICALL_EXPORT MonoReflectionAssembly*
5429 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5434 MonoReflectionAssembly *result;
5437 mono_stack_walk_no_il (get_executing, &dest);
5439 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5443 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5446 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5448 mono_error_set_pending_exception (&error);
5452 ICALL_EXPORT MonoString *
5453 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5454 gboolean assembly_qualified)
5456 MonoDomain *domain = mono_object_domain (object);
5457 MonoTypeNameFormat format;
5462 format = assembly_qualified ?
5463 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5464 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5466 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5468 name = mono_type_get_name_full (object->type, format);
5472 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5477 res = mono_string_new (domain, name);
5484 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5487 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5489 mono_class_init_checked (klass, &error);
5490 mono_error_set_pending_exception (&error);
5491 return mono_security_core_clr_class_level (klass);
5495 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5497 MonoClassField *field = rfield->field;
5498 return mono_security_core_clr_field_level (field, TRUE);
5502 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5504 MonoMethod *method = rfield->method;
5505 return mono_security_core_clr_method_level (method, TRUE);
5509 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)
5511 static MonoMethod *create_culture = NULL;
5515 const char *pkey_ptr;
5517 MonoBoolean assembly_ref = 0;
5519 mono_error_init (error);
5521 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5522 aname->major = name->major;
5523 aname->minor = name->minor;
5524 aname->build = name->build;
5525 aname->flags = name->flags;
5526 aname->revision = name->revision;
5527 aname->hashalg = name->hash_alg;
5528 aname->versioncompat = 1; /* SameMachine (default) */
5529 aname->processor_architecture = name->arch;
5531 if (by_default_version) {
5532 MonoObject *version;
5534 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5535 return_if_nok (error);
5537 MONO_OBJECT_SETREF (aname, version, version);
5541 if (absolute != NULL && *absolute != '\0') {
5542 const gchar *prepend = "file://";
5545 codebase = g_strdup (absolute);
5550 for (i = strlen (codebase) - 1; i >= 0; i--)
5551 if (codebase [i] == '\\')
5554 if (*codebase == '/' && *(codebase + 1) == '/') {
5557 prepend = "file:///";
5561 result = g_strconcat (prepend, codebase, NULL);
5567 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5571 if (!create_culture) {
5572 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5573 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5574 g_assert (create_culture);
5575 mono_method_desc_free (desc);
5578 if (name->culture) {
5579 args [0] = mono_string_new (domain, name->culture);
5580 args [1] = &assembly_ref;
5582 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5583 return_if_nok (error);
5585 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5588 if (name->public_key) {
5589 pkey_ptr = (char*)name->public_key;
5590 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5592 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5593 return_if_nok (error);
5594 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5595 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5596 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5597 } else if (default_publickey) {
5598 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5599 return_if_nok (error);
5600 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5601 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5604 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5605 if (name->public_key_token [0]) {
5609 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5610 return_if_nok (error);
5612 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5613 p = mono_array_addr (keyToken, char, 0);
5615 for (i = 0, j = 0; i < 8; i++) {
5616 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5617 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5620 } else if (default_token) {
5621 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5622 return_if_nok (error);
5623 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5627 ICALL_EXPORT MonoString *
5628 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5630 MonoDomain *domain = mono_object_domain (assembly);
5631 MonoAssembly *mass = assembly->assembly;
5635 name = mono_stringify_assembly_name (&mass->aname);
5636 res = mono_string_new (domain, name);
5643 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5646 gchar *absolute, *dirname;
5647 MonoAssembly *mass = assembly->assembly;
5649 /* XXX this is duplicated code to compute the codebase URI, unify it */
5650 if (g_path_is_absolute (mass->image->name)) {
5651 absolute = g_strdup (mass->image->name);
5652 dirname = g_path_get_dirname (absolute);
5654 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5655 dirname = g_strdup (mass->basedir);
5658 replace_shadow_path (mono_object_domain (assembly), dirname, &absolute);
5661 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5662 mono_error_set_pending_exception (&error);
5668 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5672 MonoImageOpenStatus status = MONO_IMAGE_OK;
5675 MonoAssemblyName name;
5678 filename = mono_string_to_utf8_checked (fname, &error);
5679 if (mono_error_set_pending_exception (&error))
5682 dirname = g_path_get_dirname (filename);
5683 replace_shadow_path (mono_domain_get (), dirname, &filename);
5686 image = mono_image_open (filename, &status);
5692 if (status == MONO_IMAGE_IMAGE_INVALID)
5693 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5695 exc = mono_get_exception_file_not_found2 (NULL, fname);
5696 mono_set_pending_exception (exc);
5700 res = mono_assembly_fill_assembly_name (image, &name);
5702 mono_image_close (image);
5704 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5708 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5709 mono_error_set_pending_exception (&error);
5711 mono_image_close (image);
5715 ICALL_EXPORT MonoBoolean
5716 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5717 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5719 MonoBoolean result = FALSE;
5720 MonoDeclSecurityEntry entry;
5722 /* SecurityAction.RequestMinimum */
5723 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5724 *minimum = entry.blob;
5725 *minLength = entry.size;
5728 /* SecurityAction.RequestOptional */
5729 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5730 *optional = entry.blob;
5731 *optLength = entry.size;
5734 /* SecurityAction.RequestRefuse */
5735 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5736 *refused = entry.blob;
5737 *refLength = entry.size;
5745 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5747 guint32 attrs, visibility;
5749 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5750 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5751 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5754 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5760 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5762 MonoReflectionType *rt;
5765 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5768 mono_error_init (error);
5770 /* we start the count from 1 because we skip the special type <Module> */
5773 for (i = 1; i < tdef->rows; ++i) {
5774 if (mono_module_type_is_visible (tdef, image, i + 1))
5778 count = tdef->rows - 1;
5780 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5781 return_val_if_nok (error, NULL);
5782 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5783 return_val_if_nok (error, NULL);
5785 for (i = 1; i < tdef->rows; ++i) {
5786 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5787 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5790 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5791 return_val_if_nok (error, NULL);
5793 mono_array_setref (res, count, rt);
5795 MonoException *ex = mono_error_convert_to_exception (error);
5796 mono_array_setref (*exceptions, count, ex);
5805 ICALL_EXPORT MonoArray*
5806 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5809 MonoArray *res = NULL;
5810 MonoArray *exceptions = NULL;
5811 MonoImage *image = NULL;
5812 MonoTableInfo *table = NULL;
5815 int i, len, ex_count;
5817 domain = mono_object_domain (assembly);
5819 g_assert (!assembly_is_dynamic (assembly->assembly));
5820 image = assembly->assembly->image;
5821 table = &image->tables [MONO_TABLE_FILE];
5822 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5823 if (mono_error_set_pending_exception (&error))
5826 /* Append data from all modules in the assembly */
5827 for (i = 0; i < table->rows; ++i) {
5828 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5829 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5834 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5835 if (mono_error_set_pending_exception (&error))
5839 /* Append the new types to the end of the array */
5840 if (mono_array_length (res2) > 0) {
5842 MonoArray *res3, *ex3;
5844 len1 = mono_array_length (res);
5845 len2 = mono_array_length (res2);
5847 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5848 if (mono_error_set_pending_exception (&error))
5850 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5851 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5854 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5855 if (mono_error_set_pending_exception (&error))
5857 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5858 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5865 /* the ReflectionTypeLoadException must have all the types (Types property),
5866 * NULL replacing types which throws an exception. The LoaderException must
5867 * contain all exceptions for NULL items.
5870 len = mono_array_length (res);
5873 for (i = 0; i < len; i++) {
5874 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5878 klass = mono_type_get_class (t->type);
5879 if ((klass != NULL) && mono_class_has_failure (klass)) {
5880 /* keep the class in the list */
5881 list = g_list_append (list, klass);
5882 /* and replace Type with NULL */
5883 mono_array_setref (res, i, NULL);
5890 if (list || ex_count) {
5892 MonoException *exc = NULL;
5893 MonoArray *exl = NULL;
5894 int j, length = g_list_length (list) + ex_count;
5896 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5897 if (mono_error_set_pending_exception (&error)) {
5901 /* Types for which mono_class_get_checked () succeeded */
5902 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5903 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5904 mono_array_setref (exl, i, exc);
5906 /* Types for which it don't */
5907 for (j = 0; j < mono_array_length (exceptions); ++j) {
5908 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5910 g_assert (i < length);
5911 mono_array_setref (exl, i, exc);
5918 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5919 if (!is_ok (&error)) {
5920 mono_error_set_pending_exception (&error);
5923 mono_set_pending_exception (exc);
5930 ICALL_EXPORT gboolean
5931 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5934 MonoAssemblyName aname;
5935 MonoDomain *domain = mono_object_domain (name);
5937 gboolean is_version_defined;
5938 gboolean is_token_defined;
5940 aname.public_key = NULL;
5941 val = mono_string_to_utf8_checked (assname, &error);
5942 if (mono_error_set_pending_exception (&error))
5945 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5946 g_free ((guint8*) aname.public_key);
5951 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5952 mono_error_set_pending_exception (&error);
5954 mono_assembly_name_free (&aname);
5955 g_free ((guint8*) aname.public_key);
5961 ICALL_EXPORT MonoReflectionType*
5962 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5965 MonoReflectionType *ret;
5966 MonoDomain *domain = mono_object_domain (module);
5969 g_assert (module->image);
5971 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5972 /* These images do not have a global type */
5975 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5976 if (!mono_error_ok (&error)) {
5977 mono_error_set_pending_exception (&error);
5981 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5982 if (!mono_error_ok (&error)) {
5983 mono_error_set_pending_exception (&error);
5991 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5993 /*if (module->image)
5994 mono_image_close (module->image);*/
5997 ICALL_EXPORT MonoString*
5998 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
6000 MonoDomain *domain = mono_object_domain (module);
6002 g_assert (module->image);
6003 return mono_string_new (domain, module->image->guid);
6006 ICALL_EXPORT gpointer
6007 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
6010 if (module->image && module->image->is_module_handle)
6011 return module->image->raw_data;
6014 return (gpointer) (-1);
6018 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
6020 if (image_is_dynamic (image)) {
6021 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
6022 *pe_kind = dyn->pe_kind;
6023 *machine = dyn->machine;
6026 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
6027 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
6032 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
6034 return (image->md_version_major << 16) | (image->md_version_minor);
6037 ICALL_EXPORT MonoArray*
6038 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
6041 MonoArray *exceptions;
6044 if (!module->image) {
6045 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
6046 mono_error_set_pending_exception (&error);
6051 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
6052 if (mono_error_set_pending_exception (&error))
6055 for (i = 0; i < mono_array_length (exceptions); ++i) {
6056 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
6058 mono_set_pending_exception (ex);
6067 mono_memberref_is_method (MonoImage *image, guint32 token)
6069 if (!image_is_dynamic (image)) {
6070 guint32 cols [MONO_MEMBERREF_SIZE];
6072 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
6073 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
6074 mono_metadata_decode_blob_size (sig, &sig);
6075 return (*sig != 0x6);
6078 MonoClass *handle_class;
6080 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
6081 mono_error_cleanup (&error); /* just probing, ignore error */
6085 return mono_defaults.methodhandle_class == handle_class;
6090 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
6093 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
6094 mono_array_addr (type_args, MonoType*, 0));
6096 context->class_inst = NULL;
6098 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
6099 mono_array_addr (method_args, MonoType*, 0));
6101 context->method_inst = NULL;
6104 ICALL_EXPORT MonoType*
6105 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6108 int table = mono_metadata_token_table (token);
6109 int index = mono_metadata_token_index (token);
6110 MonoGenericContext context;
6113 *resolve_error = ResolveTokenError_Other;
6115 /* Validate token */
6116 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
6117 (table != MONO_TABLE_TYPESPEC)) {
6118 *resolve_error = ResolveTokenError_BadTable;
6122 if (image_is_dynamic (image)) {
6123 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
6124 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6125 mono_error_cleanup (&error);
6126 return klass ? &klass->byval_arg : NULL;
6129 init_generic_context_from_args (&context, type_args, method_args);
6130 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6131 mono_error_cleanup (&error);
6132 return klass ? &klass->byval_arg : NULL;
6135 if ((index <= 0) || (index > image->tables [table].rows)) {
6136 *resolve_error = ResolveTokenError_OutOfRange;
6140 init_generic_context_from_args (&context, type_args, method_args);
6141 klass = mono_class_get_checked (image, token, &error);
6143 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
6144 if (!mono_error_ok (&error)) {
6145 mono_error_set_pending_exception (&error);
6150 return &klass->byval_arg;
6155 ICALL_EXPORT MonoMethod*
6156 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6159 int table = mono_metadata_token_table (token);
6160 int index = mono_metadata_token_index (token);
6161 MonoGenericContext context;
6164 *resolve_error = ResolveTokenError_Other;
6166 /* Validate token */
6167 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
6168 (table != MONO_TABLE_MEMBERREF)) {
6169 *resolve_error = ResolveTokenError_BadTable;
6173 if (image_is_dynamic (image)) {
6174 if (table == MONO_TABLE_METHOD) {
6175 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6176 mono_error_cleanup (&error);
6180 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
6181 *resolve_error = ResolveTokenError_BadTable;
6185 init_generic_context_from_args (&context, type_args, method_args);
6186 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6187 mono_error_cleanup (&error);
6191 if ((index <= 0) || (index > image->tables [table].rows)) {
6192 *resolve_error = ResolveTokenError_OutOfRange;
6195 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6196 *resolve_error = ResolveTokenError_BadTable;
6200 init_generic_context_from_args (&context, type_args, method_args);
6201 method = mono_get_method_checked (image, token, NULL, &context, &error);
6202 mono_error_set_pending_exception (&error);
6207 ICALL_EXPORT MonoString*
6208 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6211 int index = mono_metadata_token_index (token);
6213 *resolve_error = ResolveTokenError_Other;
6215 /* Validate token */
6216 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6217 *resolve_error = ResolveTokenError_BadTable;
6221 if (image_is_dynamic (image)) {
6222 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6223 mono_error_cleanup (&error);
6227 if ((index <= 0) || (index >= image->heap_us.size)) {
6228 *resolve_error = ResolveTokenError_OutOfRange;
6232 /* FIXME: What to do if the index points into the middle of a string ? */
6234 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
6235 mono_error_set_pending_exception (&error);
6239 ICALL_EXPORT MonoClassField*
6240 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6244 int table = mono_metadata_token_table (token);
6245 int index = mono_metadata_token_index (token);
6246 MonoGenericContext context;
6247 MonoClassField *field;
6249 *resolve_error = ResolveTokenError_Other;
6251 /* Validate token */
6252 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6253 *resolve_error = ResolveTokenError_BadTable;
6257 if (image_is_dynamic (image)) {
6258 if (table == MONO_TABLE_FIELD) {
6259 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6260 mono_error_cleanup (&error);
6264 if (mono_memberref_is_method (image, token)) {
6265 *resolve_error = ResolveTokenError_BadTable;
6269 init_generic_context_from_args (&context, type_args, method_args);
6270 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6271 mono_error_cleanup (&error);
6275 if ((index <= 0) || (index > image->tables [table].rows)) {
6276 *resolve_error = ResolveTokenError_OutOfRange;
6279 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6280 *resolve_error = ResolveTokenError_BadTable;
6284 init_generic_context_from_args (&context, type_args, method_args);
6285 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6286 mono_error_set_pending_exception (&error);
6292 ICALL_EXPORT MonoObject*
6293 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6297 int table = mono_metadata_token_table (token);
6299 *error = ResolveTokenError_Other;
6302 case MONO_TABLE_TYPEDEF:
6303 case MONO_TABLE_TYPEREF:
6304 case MONO_TABLE_TYPESPEC: {
6305 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6307 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6308 mono_error_set_pending_exception (&merror);
6315 case MONO_TABLE_METHOD:
6316 case MONO_TABLE_METHODSPEC: {
6317 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6319 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6320 mono_error_set_pending_exception (&merror);
6326 case MONO_TABLE_FIELD: {
6327 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6329 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6330 mono_error_set_pending_exception (&merror);
6336 case MONO_TABLE_MEMBERREF:
6337 if (mono_memberref_is_method (image, token)) {
6338 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6340 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6341 mono_error_set_pending_exception (&merror);
6348 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6350 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6351 mono_error_set_pending_exception (&merror);
6360 *error = ResolveTokenError_BadTable;
6366 ICALL_EXPORT MonoArray*
6367 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6370 int table = mono_metadata_token_table (token);
6371 int idx = mono_metadata_token_index (token);
6372 MonoTableInfo *tables = image->tables;
6377 *resolve_error = ResolveTokenError_OutOfRange;
6379 /* FIXME: Support other tables ? */
6380 if (table != MONO_TABLE_STANDALONESIG)
6383 if (image_is_dynamic (image))
6386 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6389 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6391 ptr = mono_metadata_blob_heap (image, sig);
6392 len = mono_metadata_decode_blob_size (ptr, &ptr);
6394 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6395 if (mono_error_set_pending_exception (&error))
6397 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6401 ICALL_EXPORT MonoReflectionType*
6402 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6405 MonoReflectionType *ret;
6407 int isbyref = 0, rank;
6409 char *str = mono_string_to_utf8_checked (smodifiers, &error);
6410 if (mono_error_set_pending_exception (&error))
6413 klass = mono_class_from_mono_type (tb->type.type);
6415 /* logic taken from mono_reflection_parse_type(): keep in sync */
6419 if (isbyref) { /* only one level allowed by the spec */
6428 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6429 mono_error_set_pending_exception (&error);
6433 klass = mono_ptr_class_get (&klass->byval_arg);
6434 mono_class_init (klass);
6445 else if (*p != '*') { /* '*' means unknown lower bound */
6456 klass = mono_array_class_get (klass, rank);
6457 mono_class_init (klass);
6466 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6467 mono_error_set_pending_exception (&error);
6472 ICALL_EXPORT MonoBoolean
6473 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6479 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6485 check_for_invalid_type (MonoClass *klass, MonoError *error)
6490 mono_error_init (error);
6492 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6495 name = mono_type_get_full_name (klass);
6496 str = mono_string_new (mono_domain_get (), name);
6498 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6501 ICALL_EXPORT MonoReflectionType *
6502 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6505 MonoReflectionType *ret;
6506 MonoClass *klass, *aklass;
6508 klass = mono_class_from_mono_type (type->type);
6509 check_for_invalid_type (klass, &error);
6510 mono_error_set_pending_exception (&error);
6512 if (rank == 0) //single dimentional array
6513 aklass = mono_array_class_get (klass, 1);
6515 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6517 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6518 mono_error_set_pending_exception (&error);
6523 ICALL_EXPORT MonoReflectionType *
6524 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6527 MonoReflectionType *ret;
6530 klass = mono_class_from_mono_type (type->type);
6531 mono_class_init_checked (klass, &error);
6532 if (mono_error_set_pending_exception (&error))
6535 check_for_invalid_type (klass, &error);
6536 if (mono_error_set_pending_exception (&error))
6539 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6540 mono_error_set_pending_exception (&error);
6545 ICALL_EXPORT MonoReflectionType *
6546 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6549 MonoReflectionType *ret;
6550 MonoClass *klass, *pklass;
6552 klass = mono_class_from_mono_type (type->type);
6553 mono_class_init_checked (klass, &error);
6554 if (mono_error_set_pending_exception (&error))
6556 check_for_invalid_type (klass, &error);
6557 if (mono_error_set_pending_exception (&error))
6560 pklass = mono_ptr_class_get (type->type);
6562 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6563 mono_error_set_pending_exception (&error);
6568 ICALL_EXPORT MonoObject *
6569 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6570 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6573 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6574 MonoObject *delegate;
6576 MonoMethod *method = info->method;
6578 mono_class_init_checked (delegate_class, &error);
6579 if (mono_error_set_pending_exception (&error))
6582 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6583 /* FIXME improve this exception message */
6584 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6586 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6587 mono_error_set_pending_exception (&error);
6591 if (mono_security_core_clr_enabled ()) {
6592 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6593 if (throwOnBindFailure)
6594 mono_error_set_pending_exception (&error);
6596 mono_error_cleanup (&error);
6601 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6602 if (mono_error_set_pending_exception (&error))
6605 if (method_is_dynamic (method)) {
6606 /* Creating a trampoline would leak memory */
6607 func = mono_compile_method_checked (method, &error);
6608 if (mono_error_set_pending_exception (&error))
6611 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6612 method = mono_object_get_virtual_method (target, method);
6613 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6614 if (mono_error_set_pending_exception (&error))
6616 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6619 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6620 if (mono_error_set_pending_exception (&error))
6625 ICALL_EXPORT MonoMulticastDelegate *
6626 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6629 MonoMulticastDelegate *ret;
6631 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6633 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6634 if (mono_error_set_pending_exception (&error))
6637 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6642 ICALL_EXPORT MonoReflectionMethod*
6643 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6645 MonoReflectionMethod *ret = NULL;
6647 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6648 mono_error_set_pending_exception (&error);
6654 static inline gint32
6655 mono_array_get_byte_length (MonoArray *array)
6661 klass = array->obj.vtable->klass;
6663 if (array->bounds == NULL)
6664 length = array->max_length;
6667 for (i = 0; i < klass->rank; ++ i)
6668 length *= array->bounds [i].length;
6671 switch (klass->element_class->byval_arg.type) {
6674 case MONO_TYPE_BOOLEAN:
6678 case MONO_TYPE_CHAR:
6686 return length * sizeof (gpointer);
6697 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6699 return mono_array_get_byte_length (array);
6703 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6705 return mono_array_get (array, gint8, idx);
6709 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6711 mono_array_set (array, gint8, idx, value);
6714 ICALL_EXPORT MonoBoolean
6715 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6717 guint8 *src_buf, *dest_buf;
6720 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6724 g_assert (count >= 0);
6726 /* This is called directly from the class libraries without going through the managed wrapper */
6727 MONO_CHECK_ARG_NULL (src, FALSE);
6728 MONO_CHECK_ARG_NULL (dest, FALSE);
6730 /* watch out for integer overflow */
6731 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6734 src_buf = (guint8 *)src->vector + src_offset;
6735 dest_buf = (guint8 *)dest->vector + dest_offset;
6738 memcpy (dest_buf, src_buf, count);
6740 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6745 #ifndef DISABLE_REMOTING
6746 ICALL_EXPORT MonoObject *
6747 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6750 MonoDomain *domain = mono_object_domain (this_obj);
6752 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6753 MonoTransparentProxy *tp;
6757 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6758 if (mono_error_set_pending_exception (&error))
6761 tp = (MonoTransparentProxy*) res;
6763 MONO_OBJECT_SETREF (tp, rp, rp);
6764 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6765 klass = mono_class_from_mono_type (type);
6767 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6768 mono_class_setup_vtable (klass);
6769 if (mono_class_has_failure (klass)) {
6770 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6774 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6775 if (mono_error_set_pending_exception (&error))
6777 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6778 if (mono_error_set_pending_exception (&error))
6781 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6782 if (mono_error_set_pending_exception (&error))
6787 ICALL_EXPORT MonoReflectionType *
6788 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6791 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6792 mono_error_set_pending_exception (&error);
6798 /* System.Environment */
6801 ves_icall_System_Environment_get_UserName (void)
6803 /* using glib is more portable */
6804 return mono_string_new (mono_domain_get (), g_get_user_name ());
6808 ICALL_EXPORT MonoString *
6809 ves_icall_System_Environment_get_MachineName (void)
6811 #if defined (HOST_WIN32)
6816 len = MAX_COMPUTERNAME_LENGTH + 1;
6817 buf = g_new (gunichar2, len);
6820 if (GetComputerName (buf, (PDWORD) &len)) {
6822 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6823 mono_error_set_pending_exception (&error);
6828 #elif !defined(DISABLE_SOCKETS)
6832 #if defined _SC_HOST_NAME_MAX
6833 n = sysconf (_SC_HOST_NAME_MAX);
6837 buf = g_malloc (n+1);
6839 if (gethostname (buf, n) == 0){
6841 result = mono_string_new (mono_domain_get (), buf);
6848 return mono_string_new (mono_domain_get (), "mono");
6853 ves_icall_System_Environment_get_Platform (void)
6855 #if defined (TARGET_WIN32)
6858 #elif defined(__MACH__)
6861 // Notice that the value is hidden from user code, and only exposed
6862 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6863 // define and making assumptions based on Unix/128/4 values before there
6864 // was a MacOS define. Lots of code would assume that not-Unix meant
6865 // Windows, but in this case, it would be OSX.
6874 ICALL_EXPORT MonoString *
6875 ves_icall_System_Environment_get_NewLine (void)
6877 #if defined (HOST_WIN32)
6878 return mono_string_new (mono_domain_get (), "\r\n");
6880 return mono_string_new (mono_domain_get (), "\n");
6884 ICALL_EXPORT MonoBoolean
6885 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6887 #if SIZEOF_VOID_P == 8
6891 gboolean isWow64Process = FALSE;
6892 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6893 return (MonoBoolean)isWow64Process;
6895 #elif defined(HAVE_SYS_UTSNAME_H)
6896 struct utsname name;
6898 if (uname (&name) >= 0) {
6899 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6906 ICALL_EXPORT MonoString *
6907 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6916 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6917 if (mono_error_set_pending_exception (&error))
6919 value = g_getenv (utf8_name);
6926 return mono_string_new (mono_domain_get (), value);
6930 * There is no standard way to get at environ.
6933 #ifndef __MINGW32_VERSION
6934 #if defined(__APPLE__)
6935 #if defined (TARGET_OSX)
6936 /* Apple defines this in crt_externs.h but doesn't provide that header for
6937 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6938 * in fact exist on all implementations (so far)
6940 gchar ***_NSGetEnviron(void);
6941 #define environ (*_NSGetEnviron())
6943 static char *mono_environ[1] = { NULL };
6944 #define environ mono_environ
6945 #endif /* defined (TARGET_OSX) */
6953 ICALL_EXPORT MonoArray *
6954 ves_icall_System_Environment_GetCoomandLineArgs (void)
6957 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6958 mono_error_set_pending_exception (&error);
6962 ICALL_EXPORT MonoArray *
6963 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6975 env_strings = GetEnvironmentStrings();
6978 env_string = env_strings;
6979 while (*env_string != '\0') {
6980 /* weird case that MS seems to skip */
6981 if (*env_string != '=')
6983 while (*env_string != '\0')
6989 domain = mono_domain_get ();
6990 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6991 if (mono_error_set_pending_exception (&error))
6996 env_string = env_strings;
6997 while (*env_string != '\0') {
6998 /* weird case that MS seems to skip */
6999 if (*env_string != '=') {
7000 equal_str = wcschr(env_string, '=');
7001 g_assert(equal_str);
7003 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
7004 if (mono_error_set_pending_exception (&error))
7007 mono_array_setref (names, n, str);
7010 while (*env_string != '\0')
7015 FreeEnvironmentStrings (env_strings);
7029 for (e = environ; *e != 0; ++ e)
7032 domain = mono_domain_get ();
7033 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
7034 if (mono_error_set_pending_exception (&error))
7038 for (e = environ; *e != 0; ++ e) {
7039 parts = g_strsplit (*e, "=", 2);
7041 str = mono_string_new (domain, *parts);
7042 mono_array_setref (names, n, str);
7055 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
7058 gunichar2 *utf16_name, *utf16_value;
7060 gchar *utf8_name, *utf8_value;
7065 utf16_name = mono_string_to_utf16 (name);
7066 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7067 SetEnvironmentVariable (utf16_name, NULL);
7068 g_free (utf16_name);
7072 utf16_value = mono_string_to_utf16 (value);
7074 SetEnvironmentVariable (utf16_name, utf16_value);
7076 g_free (utf16_name);
7077 g_free (utf16_value);
7079 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
7080 if (mono_error_set_pending_exception (&error))
7083 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7084 g_unsetenv (utf8_name);
7089 utf8_value = mono_string_to_utf8_checked (value, &error);
7090 if (!mono_error_ok (&error)) {
7092 mono_error_set_pending_exception (&error);
7095 g_setenv (utf8_name, utf8_value, TRUE);
7098 g_free (utf8_value);
7103 ves_icall_System_Environment_Exit (int result)
7105 mono_environment_exitcode_set (result);
7107 /* FIXME: There are some cleanup hangs that should be worked out, but
7108 * if the program is going to exit, everything will be cleaned up when
7109 * NaCl exits anyway.
7111 #ifndef __native_client__
7112 if (!mono_runtime_try_shutdown ())
7113 mono_thread_exit ();
7115 /* Suspend all managed threads since the runtime is going away */
7116 mono_thread_suspend_all_other_threads ();
7118 mono_runtime_quit ();
7121 /* we may need to do some cleanup here... */
7125 ICALL_EXPORT MonoString*
7126 ves_icall_System_Environment_GetGacPath (void)
7128 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
7131 ICALL_EXPORT MonoString*
7132 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
7134 #if defined (HOST_WIN32)
7135 #ifndef CSIDL_FLAG_CREATE
7136 #define CSIDL_FLAG_CREATE 0x8000
7139 WCHAR path [MAX_PATH];
7140 /* Create directory if no existing */
7141 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
7146 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
7147 mono_error_set_pending_exception (&error);
7151 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7153 return mono_string_new (mono_domain_get (), "");
7156 ICALL_EXPORT MonoArray *
7157 ves_icall_System_Environment_GetLogicalDrives (void)
7160 gunichar2 buf [256], *ptr, *dname;
7162 guint initial_size = 127, size = 128;
7165 MonoString *drivestr;
7166 MonoDomain *domain = mono_domain_get ();
7172 while (size > initial_size) {
7173 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
7174 if (size > initial_size) {
7177 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7178 initial_size = size;
7192 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7193 if (mono_error_set_pending_exception (&error))
7200 while (*u16) { u16++; len ++; }
7201 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7202 if (mono_error_set_pending_exception (&error))
7205 mono_array_setref (result, ndrives++, drivestr);
7216 ICALL_EXPORT MonoString *
7217 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7220 gunichar2 volume_name [MAX_PATH + 1];
7222 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7224 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
7225 mono_error_set_pending_exception (&error);
7229 ICALL_EXPORT MonoString *
7230 ves_icall_System_Environment_InternalGetHome (void)
7232 return mono_string_new (mono_domain_get (), g_get_home_dir ());
7235 static const char *encodings [] = {
7237 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7238 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7239 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7241 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7242 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7243 "x_unicode_2_0_utf_7",
7245 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7246 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7248 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7251 "unicodefffe", "utf_16be",
7258 * Returns the internal codepage, if the value of "int_code_page" is
7259 * 1 at entry, and we can not compute a suitable code page number,
7260 * returns the code page as a string
7262 ICALL_EXPORT MonoString*
7263 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
7268 char *codepage = NULL;
7270 int want_name = *int_code_page;
7273 *int_code_page = -1;
7275 g_get_charset (&cset);
7276 c = codepage = strdup (cset);
7277 for (c = codepage; *c; c++){
7278 if (isascii (*c) && isalpha (*c))
7283 /* g_print ("charset: %s\n", cset); */
7285 /* handle some common aliases */
7288 for (i = 0; p != 0; ){
7291 p = encodings [++i];
7294 if (strcmp (p, codepage) == 0){
7295 *int_code_page = code;
7298 p = encodings [++i];
7301 if (strstr (codepage, "utf_8") != NULL)
7302 *int_code_page |= 0x10000000;
7305 if (want_name && *int_code_page == -1)
7306 return mono_string_new (mono_domain_get (), cset);
7311 ICALL_EXPORT MonoBoolean
7312 ves_icall_System_Environment_get_HasShutdownStarted (void)
7314 if (mono_runtime_is_shutting_down ())
7317 if (mono_domain_is_unloading (mono_domain_get ()))
7324 ves_icall_System_Environment_BroadcastSettingChange (void)
7327 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7333 ves_icall_System_Environment_get_TickCount (void)
7335 /* this will overflow after ~24 days */
7336 return (gint32) (mono_msec_boottime () & 0xffffffff);
7340 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7345 #ifndef DISABLE_REMOTING
7346 ICALL_EXPORT MonoBoolean
7347 ves_icall_IsTransparentProxy (MonoObject *proxy)
7352 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7358 ICALL_EXPORT MonoReflectionMethod *
7359 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7360 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7362 MonoReflectionMethod *ret = NULL;
7367 MonoMethod **vtable;
7368 MonoMethod *res = NULL;
7370 MONO_CHECK_ARG_NULL (rtype, NULL);
7371 MONO_CHECK_ARG_NULL (rmethod, NULL);
7373 method = rmethod->method;
7374 klass = mono_class_from_mono_type (rtype->type);
7375 mono_class_init_checked (klass, &error);
7376 if (mono_error_set_pending_exception (&error))
7379 if (MONO_CLASS_IS_INTERFACE (klass))
7382 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7385 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7386 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7392 mono_class_setup_vtable (klass);
7393 vtable = klass->vtable;
7395 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7396 gboolean variance_used = FALSE;
7397 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7398 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7400 res = vtable [offs + method->slot];
7402 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7405 if (method->slot != -1)
7406 res = vtable [method->slot];
7412 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7413 mono_error_set_pending_exception (&error);
7418 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7424 klass = mono_class_from_mono_type (type->type);
7425 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7426 if (!is_ok (&error)) {
7427 mono_error_set_pending_exception (&error);
7431 mono_vtable_set_is_remote (vtable, enable);
7434 #else /* DISABLE_REMOTING */
7437 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7439 g_assert_not_reached ();
7444 ICALL_EXPORT MonoObject *
7445 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7452 domain = mono_object_domain (type);
7453 klass = mono_class_from_mono_type (type->type);
7454 mono_class_init_checked (klass, &error);
7455 if (mono_error_set_pending_exception (&error))
7458 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7459 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7463 if (klass->rank >= 1) {
7464 g_assert (klass->rank == 1);
7465 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7466 mono_error_set_pending_exception (&error);
7469 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7470 if (!is_ok (&error)) {
7471 mono_error_set_pending_exception (&error);
7474 /* Bypass remoting object creation check */
7475 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7476 mono_error_set_pending_exception (&error);
7482 ICALL_EXPORT MonoString *
7483 ves_icall_System_IO_get_temp_path (void)
7485 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7488 #ifndef PLATFORM_NO_DRIVEINFO
7489 ICALL_EXPORT MonoBoolean
7490 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7491 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7495 ULARGE_INTEGER wapi_free_bytes_avail;
7496 ULARGE_INTEGER wapi_total_number_of_bytes;
7497 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7499 *error = ERROR_SUCCESS;
7500 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7501 &wapi_total_number_of_free_bytes);
7504 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7505 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7506 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7508 *free_bytes_avail = 0;
7509 *total_number_of_bytes = 0;
7510 *total_number_of_free_bytes = 0;
7511 *error = GetLastError ();
7517 ICALL_EXPORT guint32
7518 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7520 return GetDriveType (mono_string_chars (root_path_name));
7524 ICALL_EXPORT gpointer
7525 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7528 gpointer result = mono_compile_method_checked (method, &error);
7529 mono_error_set_pending_exception (&error);
7533 ICALL_EXPORT MonoString *
7534 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7539 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7541 #if defined (HOST_WIN32)
7542 /* Avoid mixing '/' and '\\' */
7545 for (i = strlen (path) - 1; i >= 0; i--)
7546 if (path [i] == '/')
7550 mcpath = mono_string_new (mono_domain_get (), path);
7556 /* this is an icall */
7558 get_bundled_app_config (void)
7561 const gchar *app_config;
7564 gchar *config_file_name, *config_file_path;
7565 gsize len, config_file_path_length, config_ext_length;
7568 domain = mono_domain_get ();
7569 file = domain->setup->configuration_file;
7570 if (!file || file->length == 0)
7573 // Retrieve config file and remove the extension
7574 config_file_name = mono_string_to_utf8_checked (file, &error);
7575 if (mono_error_set_pending_exception (&error))
7577 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7578 if (!config_file_path)
7579 config_file_path = config_file_name;
7581 config_file_path_length = strlen (config_file_path);
7582 config_ext_length = strlen (".config");
7583 if (config_file_path_length <= config_ext_length)
7586 len = config_file_path_length - config_ext_length;
7587 module = (gchar *)g_malloc0 (len + 1);
7588 memcpy (module, config_file_path, len);
7589 // Get the config file from the module name
7590 app_config = mono_config_string_for_assembly_file (module);
7593 if (config_file_name != config_file_path)
7594 g_free (config_file_name);
7595 g_free (config_file_path);
7600 return mono_string_new (mono_domain_get (), app_config);
7604 get_bundled_machine_config (void)
7606 const gchar *machine_config;
7608 machine_config = mono_get_machine_config ();
7610 if (!machine_config)
7613 return mono_string_new (mono_domain_get (), machine_config);
7616 ICALL_EXPORT MonoString *
7617 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7622 path = g_path_get_dirname (mono_get_config_dir ());
7624 #if defined (HOST_WIN32)
7625 /* Avoid mixing '/' and '\\' */
7628 for (i = strlen (path) - 1; i >= 0; i--)
7629 if (path [i] == '/')
7633 ipath = mono_string_new (mono_domain_get (), path);
7639 ICALL_EXPORT gboolean
7640 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7642 MonoPEResourceDataEntry *entry;
7645 if (!assembly || !result || !size)
7650 image = assembly->assembly->image;
7651 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7655 *result = mono_image_rva_map (image, entry->rde_data_offset);
7660 *size = entry->rde_size;
7665 ICALL_EXPORT MonoBoolean
7666 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7668 return mono_is_debugger_attached ();
7671 ICALL_EXPORT MonoBoolean
7672 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7674 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7675 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7681 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7683 if (mono_get_runtime_callbacks ()->debug_log)
7684 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7688 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7690 #if defined (HOST_WIN32)
7691 OutputDebugString (mono_string_chars (message));
7693 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7697 /* Only used for value types */
7698 ICALL_EXPORT MonoObject *
7699 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7706 domain = mono_object_domain (type);
7707 klass = mono_class_from_mono_type (type->type);
7708 mono_class_init_checked (klass, &error);
7709 if (mono_error_set_pending_exception (&error))
7712 if (mono_class_is_nullable (klass))
7713 /* No arguments -> null */
7716 result = mono_object_new_checked (domain, klass, &error);
7717 mono_error_set_pending_exception (&error);
7721 ICALL_EXPORT MonoReflectionMethod *
7722 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7724 MonoReflectionMethod *ret = NULL;
7727 MonoClass *klass, *parent;
7728 MonoGenericContext *generic_inst = NULL;
7729 MonoMethod *method = m->method;
7730 MonoMethod *result = NULL;
7733 if (method->klass == NULL)
7736 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7737 MONO_CLASS_IS_INTERFACE (method->klass) ||
7738 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7741 slot = mono_method_get_vtable_slot (method);
7745 klass = method->klass;
7746 if (klass->generic_class) {
7747 generic_inst = mono_class_get_context (klass);
7748 klass = klass->generic_class->container_class;
7752 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7753 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7754 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7755 or klass is the generic container class and generic_inst is the instantiation.
7757 when we go to the parent, if the parent is an open constructed type, we need to
7758 replace the type parameters by the definitions from the generic_inst, and then take it
7759 apart again into the klass and the generic_inst.
7761 For cases like this:
7762 class C<T> : B<T, int> {
7763 public override void Foo () { ... }
7765 class B<U,V> : A<HashMap<U,V>> {
7766 public override void Foo () { ... }
7769 public virtual void Foo () { ... }
7772 if at each iteration the parent isn't open, we can skip inflating it. if at some
7773 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7776 MonoGenericContext *parent_inst = NULL;
7777 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7778 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7779 if (!mono_error_ok (&error)) {
7780 mono_error_set_pending_exception (&error);
7784 if (parent->generic_class) {
7785 parent_inst = mono_class_get_context (parent);
7786 parent = parent->generic_class->container_class;
7789 mono_class_setup_vtable (parent);
7790 if (parent->vtable_size <= slot)
7793 generic_inst = parent_inst;
7796 klass = klass->parent;
7799 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7800 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7801 if (!mono_error_ok (&error)) {
7802 mono_error_set_pending_exception (&error);
7806 generic_inst = NULL;
7808 if (klass->generic_class) {
7809 generic_inst = mono_class_get_context (klass);
7810 klass = klass->generic_class->container_class;
7816 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7817 if (!mono_error_ok (&error)) {
7818 mono_error_set_pending_exception (&error);
7823 if (klass == method->klass)
7826 /*This is possible if definition == FALSE.
7827 * Do it here to be really sure we don't read invalid memory.
7829 if (slot >= klass->vtable_size)
7832 mono_class_setup_vtable (klass);
7834 result = klass->vtable [slot];
7835 if (result == NULL) {
7836 /* It is an abstract method */
7837 gpointer iter = NULL;
7838 while ((result = mono_class_get_methods (klass, &iter)))
7839 if (result->slot == slot)
7846 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7847 mono_error_set_pending_exception (&error);
7851 ICALL_EXPORT MonoString*
7852 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7854 MonoMethod *method = m->method;
7856 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7861 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7863 iter->sig = *(MonoMethodSignature**)argsp;
7865 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7866 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7869 /* FIXME: it's not documented what start is exactly... */
7873 iter->args = argsp + sizeof (gpointer);
7875 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7877 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7880 ICALL_EXPORT MonoTypedRef
7881 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7883 guint32 i, arg_size;
7887 i = iter->sig->sentinelpos + iter->next_arg;
7889 g_assert (i < iter->sig->param_count);
7891 res.type = iter->sig->params [i];
7892 res.klass = mono_class_from_mono_type (res.type);
7893 arg_size = mono_type_stack_size (res.type, &align);
7894 #if defined(__arm__) || defined(__mips__)
7895 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7897 res.value = iter->args;
7898 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7899 /* Values are stored as 8 byte register sized objects, but 'value'
7900 * is dereferenced as a pointer in other routines.
7902 res.value = (char*)res.value + 4;
7904 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7905 if (arg_size <= sizeof (gpointer)) {
7907 int padding = arg_size - mono_type_size (res.type, &dummy);
7908 res.value = (guint8*)res.value + padding;
7911 iter->args = (char*)iter->args + arg_size;
7914 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7919 ICALL_EXPORT MonoTypedRef
7920 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7922 guint32 i, arg_size;
7926 i = iter->sig->sentinelpos + iter->next_arg;
7928 g_assert (i < iter->sig->param_count);
7930 while (i < iter->sig->param_count) {
7931 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7933 res.type = iter->sig->params [i];
7934 res.klass = mono_class_from_mono_type (res.type);
7935 /* FIXME: endianess issue... */
7936 arg_size = mono_type_stack_size (res.type, &align);
7937 #if defined(__arm__) || defined(__mips__)
7938 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7940 res.value = iter->args;
7941 iter->args = (char*)iter->args + arg_size;
7943 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7946 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7954 ICALL_EXPORT MonoType*
7955 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7959 i = iter->sig->sentinelpos + iter->next_arg;
7961 g_assert (i < iter->sig->param_count);
7963 return iter->sig->params [i];
7966 ICALL_EXPORT MonoObject*
7967 mono_TypedReference_ToObject (MonoTypedRef* tref)
7970 MonoObject *result = NULL;
7971 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7972 MonoObject** objp = (MonoObject **)tref->value;
7976 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7977 mono_error_set_pending_exception (&error);
7981 ICALL_EXPORT MonoTypedRef
7982 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7985 MonoReflectionField *f;
7987 MonoType *ftype = NULL;
7991 memset (&res, 0, sizeof (res));
7994 g_assert (mono_array_length (fields) > 0);
7996 klass = target->vtable->klass;
7998 for (i = 0; i < mono_array_length (fields); ++i) {
7999 f = mono_array_get (fields, MonoReflectionField*, i);
8001 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
8004 if (f->field->parent != klass) {
8005 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
8009 p = (guint8*)target + f->field->offset;
8011 p += f->field->offset - sizeof (MonoObject);
8012 klass = mono_class_from_mono_type (f->field->type);
8013 ftype = f->field->type;
8017 res.klass = mono_class_from_mono_type (ftype);
8024 prelink_method (MonoMethod *method, MonoError *error)
8026 const char *exc_class, *exc_arg;
8028 mono_error_init (error);
8029 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
8031 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
8033 mono_error_set_exception_instance (error,
8034 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
8037 /* create the wrapper, too? */
8041 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
8045 prelink_method (method->method, &error);
8046 mono_error_set_pending_exception (&error);
8050 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
8053 MonoClass *klass = mono_class_from_mono_type (type->type);
8055 gpointer iter = NULL;
8057 mono_class_init_checked (klass, &error);
8058 if (mono_error_set_pending_exception (&error))
8061 while ((m = mono_class_get_methods (klass, &iter))) {
8062 prelink_method (m, &error);
8063 if (mono_error_set_pending_exception (&error))
8068 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
8070 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
8071 gint32 const **exponents,
8072 gunichar2 const **digitLowerTable,
8073 gunichar2 const **digitUpperTable,
8074 gint64 const **tenPowersList,
8075 gint32 const **decHexDigits)
8077 *mantissas = Formatter_MantissaBitsTable;
8078 *exponents = Formatter_TensExponentTable;
8079 *digitLowerTable = Formatter_DigitLowerTable;
8080 *digitUpperTable = Formatter_DigitUpperTable;
8081 *tenPowersList = Formatter_TenPowersList;
8082 *decHexDigits = Formatter_DecHexDigits;
8086 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
8087 * and avoid useless allocations.
8090 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
8092 MonoReflectionType *rt;
8096 mono_error_init (error);
8097 for (i = 0; i < type->num_mods; ++i) {
8098 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
8103 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
8104 return_val_if_nok (error, NULL);
8106 for (i = 0; i < type->num_mods; ++i) {
8107 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
8108 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
8109 return_val_if_nok (error, NULL);
8111 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8112 return_val_if_nok (error, NULL);
8114 mono_array_setref (res, count, rt);
8121 ICALL_EXPORT MonoArray*
8122 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
8125 MonoType *type = param->ClassImpl->type;
8126 MonoClass *member_class = mono_object_class (param->MemberImpl);
8127 MonoMethod *method = NULL;
8130 MonoMethodSignature *sig;
8133 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8134 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8135 method = rmethod->method;
8136 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
8137 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8138 if (!(method = prop->property->get))
8139 method = prop->property->set;
8142 char *type_name = mono_type_get_full_name (member_class);
8143 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
8144 MonoException *ex = mono_get_exception_not_supported (msg);
8147 mono_set_pending_exception (ex);
8151 image = method->klass->image;
8152 pos = param->PositionImpl;
8153 sig = mono_method_signature (method);
8157 type = sig->params [pos];
8159 res = type_array_from_modifiers (image, type, optional, &error);
8160 mono_error_set_pending_exception (&error);
8165 get_property_type (MonoProperty *prop)
8167 MonoMethodSignature *sig;
8169 sig = mono_method_signature (prop->get);
8171 } else if (prop->set) {
8172 sig = mono_method_signature (prop->set);
8173 return sig->params [sig->param_count - 1];
8178 ICALL_EXPORT MonoArray*
8179 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
8182 MonoType *type = get_property_type (property->property);
8183 MonoImage *image = property->klass->image;
8188 res = type_array_from_modifiers (image, type, optional, &error);
8189 mono_error_set_pending_exception (&error);
8194 *Construct a MonoType suited to be used to decode a constant blob object.
8196 * @type is the target type which will be constructed
8197 * @blob_type is the blob type, for example, that comes from the constant table
8198 * @real_type is the expected constructed type.
8201 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8203 type->type = blob_type;
8204 type->data.klass = NULL;
8205 if (blob_type == MONO_TYPE_CLASS)
8206 type->data.klass = mono_defaults.object_class;
8207 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8208 /* For enums, we need to use the base type */
8209 type->type = MONO_TYPE_VALUETYPE;
8210 type->data.klass = mono_class_from_mono_type (real_type);
8212 type->data.klass = mono_class_from_mono_type (real_type);
8215 ICALL_EXPORT MonoObject*
8216 property_info_get_default_value (MonoReflectionProperty *property)
8220 MonoProperty *prop = property->property;
8221 MonoType *type = get_property_type (prop);
8222 MonoDomain *domain = mono_object_domain (property);
8223 MonoTypeEnum def_type;
8224 const char *def_value;
8227 mono_class_init (prop->parent);
8229 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8230 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8234 def_value = mono_class_get_property_default_value (prop, &def_type);
8236 mono_type_from_blob_type (&blob_type, def_type, type);
8237 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8239 mono_error_set_pending_exception (&error);
8243 ICALL_EXPORT MonoBoolean
8244 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8247 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8248 MonoCustomAttrInfo *cinfo;
8251 mono_class_init_checked (attr_class, &error);
8252 if (mono_error_set_pending_exception (&error))
8255 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8256 if (!is_ok (&error)) {
8257 mono_error_set_pending_exception (&error);
8262 found = mono_custom_attrs_has_attr (cinfo, attr_class);
8264 mono_custom_attrs_free (cinfo);
8268 ICALL_EXPORT MonoArray*
8269 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8271 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8276 mono_class_init_checked (attr_class, &error);
8277 if (mono_error_set_pending_exception (&error))
8281 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8282 if (!mono_error_ok (&error)) {
8283 mono_error_set_pending_exception (&error);
8290 ICALL_EXPORT MonoArray*
8291 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8295 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8296 mono_error_set_pending_exception (&error);
8301 ICALL_EXPORT MonoString*
8302 ves_icall_Mono_Runtime_GetDisplayName (void)
8305 MonoString *display_name;
8307 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8308 display_name = mono_string_new (mono_domain_get (), info);
8310 return display_name;
8313 ICALL_EXPORT MonoString*
8314 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8317 MonoString *message;
8321 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8322 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8325 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8327 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8328 if (mono_error_set_pending_exception (&error))
8335 ICALL_EXPORT gpointer
8336 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8338 return GetCurrentProcess ();
8341 ICALL_EXPORT MonoBoolean
8342 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8344 return GetExitCodeProcess (handle, (guint32*) exitcode);
8347 ICALL_EXPORT MonoBoolean
8348 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8350 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8351 return CloseHandle (handle);
8353 return CloseProcess (handle);
8357 ICALL_EXPORT MonoBoolean
8358 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8360 return TerminateProcess (handle, exitcode);
8364 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8366 return WaitForInputIdle (handle, milliseconds);
8369 ICALL_EXPORT MonoBoolean
8370 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8372 return GetProcessWorkingSetSize (handle, min, max);
8375 ICALL_EXPORT MonoBoolean
8376 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8378 return SetProcessWorkingSetSize (handle, min, max);
8381 ICALL_EXPORT MonoBoolean
8382 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8384 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8388 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8390 return mono_process_current_pid ();
8394 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8396 return GetPriorityClass (handle);
8399 ICALL_EXPORT MonoBoolean
8400 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8402 return SetPriorityClass (handle, priorityClass);
8405 #ifndef DISABLE_ICALL_TABLES
8407 #define ICALL_TYPE(id,name,first)
8408 #define ICALL(id,name,func) Icall_ ## id,
8411 #include "metadata/icall-def.h"
8417 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8418 #define ICALL(id,name,func)
8420 #include "metadata/icall-def.h"
8426 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8427 #define ICALL(id,name,func)
8429 guint16 first_icall;
8432 static const IcallTypeDesc
8433 icall_type_descs [] = {
8434 #include "metadata/icall-def.h"
8438 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8441 #define ICALL_TYPE(id,name,first)
8444 #ifdef HAVE_ARRAY_ELEM_INIT
8445 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8446 #define MSGSTRFIELD1(line) str##line
8448 static const struct msgstrtn_t {
8449 #define ICALL(id,name,func)
8451 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8452 #include "metadata/icall-def.h"
8454 } icall_type_names_str = {
8455 #define ICALL_TYPE(id,name,first) (name),
8456 #include "metadata/icall-def.h"
8459 static const guint16 icall_type_names_idx [] = {
8460 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8461 #include "metadata/icall-def.h"
8464 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8466 static const struct msgstr_t {
8468 #define ICALL_TYPE(id,name,first)
8469 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8470 #include "metadata/icall-def.h"
8472 } icall_names_str = {
8473 #define ICALL(id,name,func) (name),
8474 #include "metadata/icall-def.h"
8477 static const guint16 icall_names_idx [] = {
8478 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8479 #include "metadata/icall-def.h"
8482 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8488 #define ICALL_TYPE(id,name,first) name,
8489 #define ICALL(id,name,func)
8490 static const char* const
8491 icall_type_names [] = {
8492 #include "metadata/icall-def.h"
8496 #define icall_type_name_get(id) (icall_type_names [(id)])
8500 #define ICALL_TYPE(id,name,first)
8501 #define ICALL(id,name,func) name,
8502 static const char* const
8504 #include "metadata/icall-def.h"
8507 #define icall_name_get(id) icall_names [(id)]
8509 #endif /* !HAVE_ARRAY_ELEM_INIT */
8513 #define ICALL_TYPE(id,name,first)
8514 #define ICALL(id,name,func) func,
8515 static const gconstpointer
8516 icall_functions [] = {
8517 #include "metadata/icall-def.h"
8521 #ifdef ENABLE_ICALL_SYMBOL_MAP
8524 #define ICALL_TYPE(id,name,first)
8525 #define ICALL(id,name,func) #func,
8526 static const gconstpointer
8527 icall_symbols [] = {
8528 #include "metadata/icall-def.h"
8533 #endif /* DISABLE_ICALL_TABLES */
8535 static mono_mutex_t icall_mutex;
8536 static GHashTable *icall_hash = NULL;
8537 static GHashTable *jit_icall_hash_name = NULL;
8538 static GHashTable *jit_icall_hash_addr = NULL;
8541 mono_icall_init (void)
8543 #ifndef DISABLE_ICALL_TABLES
8546 /* check that tables are sorted: disable in release */
8549 const char *prev_class = NULL;
8550 const char *prev_method;
8552 for (i = 0; i < Icall_type_num; ++i) {
8553 const IcallTypeDesc *desc;
8556 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8557 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8558 prev_class = icall_type_name_get (i);
8559 desc = &icall_type_descs [i];
8560 num_icalls = icall_desc_num_icalls (desc);
8561 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8562 for (j = 0; j < num_icalls; ++j) {
8563 const char *methodn = icall_name_get (desc->first_icall + j);
8564 if (prev_method && strcmp (prev_method, methodn) >= 0)
8565 g_print ("method %s should come before method %s\n", methodn, prev_method);
8566 prev_method = methodn;
8572 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8573 mono_os_mutex_init (&icall_mutex);
8577 mono_icall_lock (void)
8579 mono_locks_os_acquire (&icall_mutex, IcallLock);
8583 mono_icall_unlock (void)
8585 mono_locks_os_release (&icall_mutex, IcallLock);
8589 mono_icall_cleanup (void)
8591 g_hash_table_destroy (icall_hash);
8592 g_hash_table_destroy (jit_icall_hash_name);
8593 g_hash_table_destroy (jit_icall_hash_addr);
8594 mono_os_mutex_destroy (&icall_mutex);
8598 * mono_add_internal_call:
8599 * @name: method specification to surface to the managed world
8600 * @method: pointer to a C method to invoke when the method is called
8602 * This method surfaces the C function pointed by @method as a method
8603 * that has been surfaced in managed code with the method specified in
8604 * @name as an internal call.
8606 * Internal calls are surfaced to all app domains loaded and they are
8607 * accessibly by a type with the specified name.
8609 * You must provide a fully qualified type name, that is namespaces
8610 * and type name, followed by a colon and the method name, with an
8611 * optional signature to bind.
8613 * For example, the following are all valid declarations:
8615 * "MyApp.Services.ScriptService:Accelerate"
8616 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8618 * You use method parameters in cases where there might be more than
8619 * one surface method to managed code. That way you can register different
8620 * internal calls for different method overloads.
8622 * The internal calls are invoked with no marshalling. This means that .NET
8623 * types like System.String are exposed as `MonoString *` parameters. This is
8624 * different than the way that strings are surfaced in P/Invoke.
8626 * For more information on how the parameters are marshalled, see the
8627 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8630 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8631 * reference for more information on the format of method descriptions.
8634 mono_add_internal_call (const char *name, gconstpointer method)
8638 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8640 mono_icall_unlock ();
8643 #ifndef DISABLE_ICALL_TABLES
8645 #ifdef HAVE_ARRAY_ELEM_INIT
8647 compare_method_imap (const void *key, const void *elem)
8649 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8650 return strcmp (key, method_name);
8654 find_method_icall (const IcallTypeDesc *imap, const char *name)
8656 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);
8659 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8663 compare_class_imap (const void *key, const void *elem)
8665 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8666 return strcmp (key, class_name);
8669 static const IcallTypeDesc*
8670 find_class_icalls (const char *name)
8672 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);
8675 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8678 #else /* HAVE_ARRAY_ELEM_INIT */
8681 compare_method_imap (const void *key, const void *elem)
8683 const char** method_name = (const char**)elem;
8684 return strcmp (key, *method_name);
8688 find_method_icall (const IcallTypeDesc *imap, const char *name)
8690 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8693 return (gpointer)icall_functions [(nameslot - icall_names)];
8697 compare_class_imap (const void *key, const void *elem)
8699 const char** class_name = (const char**)elem;
8700 return strcmp (key, *class_name);
8703 static const IcallTypeDesc*
8704 find_class_icalls (const char *name)
8706 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8709 return &icall_type_descs [nameslot - icall_type_names];
8712 #endif /* HAVE_ARRAY_ELEM_INIT */
8714 #endif /* DISABLE_ICALL_TABLES */
8717 * we should probably export this as an helper (handle nested types).
8718 * Returns the number of chars written in buf.
8721 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8723 int nspacelen, cnamelen;
8724 nspacelen = strlen (klass->name_space);
8725 cnamelen = strlen (klass->name);
8726 if (nspacelen + cnamelen + 2 > bufsize)
8729 memcpy (buf, klass->name_space, nspacelen);
8730 buf [nspacelen ++] = '.';
8732 memcpy (buf + nspacelen, klass->name, cnamelen);
8733 buf [nspacelen + cnamelen] = 0;
8734 return nspacelen + cnamelen;
8737 #ifdef DISABLE_ICALL_TABLES
8739 no_icall_table (void)
8741 g_assert_not_reached ();
8746 mono_lookup_internal_call (MonoMethod *method)
8751 int typelen = 0, mlen, siglen;
8753 #ifndef DISABLE_ICALL_TABLES
8754 const IcallTypeDesc *imap = NULL;
8757 g_assert (method != NULL);
8759 if (method->is_inflated)
8760 method = ((MonoMethodInflated *) method)->declaring;
8762 if (method->klass->nested_in) {
8763 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8767 mname [pos++] = '/';
8770 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8776 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8781 #ifndef DISABLE_ICALL_TABLES
8782 imap = find_class_icalls (mname);
8785 mname [typelen] = ':';
8786 mname [typelen + 1] = ':';
8788 mlen = strlen (method->name);
8789 memcpy (mname + typelen + 2, method->name, mlen);
8790 sigstart = mname + typelen + 2 + mlen;
8793 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8794 siglen = strlen (tmpsig);
8795 if (typelen + mlen + siglen + 6 > sizeof (mname))
8798 memcpy (sigstart + 1, tmpsig, siglen);
8799 sigstart [siglen + 1] = ')';
8800 sigstart [siglen + 2] = 0;
8805 res = g_hash_table_lookup (icall_hash, mname);
8807 mono_icall_unlock ();;
8810 /* try without signature */
8812 res = g_hash_table_lookup (icall_hash, mname);
8814 mono_icall_unlock ();
8818 #ifdef DISABLE_ICALL_TABLES
8819 mono_icall_unlock ();
8820 /* Fail only when the result is actually used */
8821 /* mono_marshal_get_native_wrapper () depends on this */
8822 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8823 return ves_icall_System_String_ctor_RedirectToCreateString;
8825 return no_icall_table;
8827 /* it wasn't found in the static call tables */
8829 mono_icall_unlock ();
8832 res = find_method_icall (imap, sigstart - mlen);
8834 mono_icall_unlock ();
8837 /* try _with_ signature */
8839 res = find_method_icall (imap, sigstart - mlen);
8841 mono_icall_unlock ();
8845 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8846 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8847 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8848 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8849 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");
8850 g_print ("If you see other errors or faults after this message they are probably related\n");
8851 g_print ("and you need to fix your mono install first.\n");
8853 mono_icall_unlock ();
8859 #ifdef ENABLE_ICALL_SYMBOL_MAP
8861 func_cmp (gconstpointer key, gconstpointer p)
8863 return (gsize)key - (gsize)*(gsize*)p;
8868 * mono_lookup_icall_symbol:
8870 * Given the icall METHOD, returns its C symbol.
8873 mono_lookup_icall_symbol (MonoMethod *m)
8875 #ifdef DISABLE_ICALL_TABLES
8876 g_assert_not_reached ();
8879 #ifdef ENABLE_ICALL_SYMBOL_MAP
8883 static gconstpointer *functions_sorted;
8884 static const char**symbols_sorted;
8885 static gboolean inited;
8890 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8891 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8892 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8893 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8894 /* Bubble sort the two arrays */
8898 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8899 if (functions_sorted [i] > functions_sorted [i + 1]) {
8902 tmp = functions_sorted [i];
8903 functions_sorted [i] = functions_sorted [i + 1];
8904 functions_sorted [i + 1] = tmp;
8905 tmp = symbols_sorted [i];
8906 symbols_sorted [i] = symbols_sorted [i + 1];
8907 symbols_sorted [i + 1] = tmp;
8914 func = mono_lookup_internal_call (m);
8917 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8921 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8923 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8924 g_assert_not_reached ();
8931 type_from_typename (char *type_name)
8933 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8935 if (!strcmp (type_name, "int"))
8936 klass = mono_defaults.int_class;
8937 else if (!strcmp (type_name, "ptr"))
8938 klass = mono_defaults.int_class;
8939 else if (!strcmp (type_name, "void"))
8940 klass = mono_defaults.void_class;
8941 else if (!strcmp (type_name, "int32"))
8942 klass = mono_defaults.int32_class;
8943 else if (!strcmp (type_name, "uint32"))
8944 klass = mono_defaults.uint32_class;
8945 else if (!strcmp (type_name, "int8"))
8946 klass = mono_defaults.sbyte_class;
8947 else if (!strcmp (type_name, "uint8"))
8948 klass = mono_defaults.byte_class;
8949 else if (!strcmp (type_name, "int16"))
8950 klass = mono_defaults.int16_class;
8951 else if (!strcmp (type_name, "uint16"))
8952 klass = mono_defaults.uint16_class;
8953 else if (!strcmp (type_name, "long"))
8954 klass = mono_defaults.int64_class;
8955 else if (!strcmp (type_name, "ulong"))
8956 klass = mono_defaults.uint64_class;
8957 else if (!strcmp (type_name, "float"))
8958 klass = mono_defaults.single_class;
8959 else if (!strcmp (type_name, "double"))
8960 klass = mono_defaults.double_class;
8961 else if (!strcmp (type_name, "object"))
8962 klass = mono_defaults.object_class;
8963 else if (!strcmp (type_name, "obj"))
8964 klass = mono_defaults.object_class;
8965 else if (!strcmp (type_name, "string"))
8966 klass = mono_defaults.string_class;
8967 else if (!strcmp (type_name, "bool"))
8968 klass = mono_defaults.boolean_class;
8969 else if (!strcmp (type_name, "boolean"))
8970 klass = mono_defaults.boolean_class;
8972 g_error ("%s", type_name);
8973 g_assert_not_reached ();
8975 return &klass->byval_arg;
8979 * LOCKING: Take the corlib image lock.
8981 MonoMethodSignature*
8982 mono_create_icall_signature (const char *sigstr)
8987 MonoMethodSignature *res, *res2;
8988 MonoImage *corlib = mono_defaults.corlib;
8990 mono_image_lock (corlib);
8991 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8992 mono_image_unlock (corlib);
8997 parts = g_strsplit (sigstr, " ", 256);
9006 res = mono_metadata_signature_alloc (corlib, len - 1);
9011 * Under windows, the default pinvoke calling convention is STDCALL but
9014 res->call_convention = MONO_CALL_C;
9017 res->ret = type_from_typename (parts [0]);
9018 for (i = 1; i < len; ++i) {
9019 res->params [i - 1] = type_from_typename (parts [i]);
9024 mono_image_lock (corlib);
9025 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
9027 res = res2; /*Value is allocated in the image pool*/
9029 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
9030 mono_image_unlock (corlib);
9036 mono_find_jit_icall_by_name (const char *name)
9038 MonoJitICallInfo *info;
9039 g_assert (jit_icall_hash_name);
9042 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9043 mono_icall_unlock ();
9048 mono_find_jit_icall_by_addr (gconstpointer addr)
9050 MonoJitICallInfo *info;
9051 g_assert (jit_icall_hash_addr);
9054 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
9055 mono_icall_unlock ();
9061 * mono_get_jit_icall_info:
9063 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
9064 * caller should access it while holding the icall lock.
9067 mono_get_jit_icall_info (void)
9069 return jit_icall_hash_name;
9073 * mono_lookup_jit_icall_symbol:
9075 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
9078 mono_lookup_jit_icall_symbol (const char *name)
9080 MonoJitICallInfo *info;
9081 const char *res = NULL;
9084 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9086 res = info->c_symbol;
9087 mono_icall_unlock ();
9092 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
9095 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
9096 mono_icall_unlock ();
9100 * 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
9101 * icalls without wrappers in some cases.
9104 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
9106 MonoJitICallInfo *info;
9113 if (!jit_icall_hash_name) {
9114 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
9115 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
9118 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
9119 g_warning ("jit icall already defined \"%s\"\n", name);
9120 g_assert_not_reached ();
9123 info = g_new0 (MonoJitICallInfo, 1);
9128 info->c_symbol = c_symbol;
9129 info->no_raise = no_raise;
9132 info->wrapper = func;
9134 info->wrapper = NULL;
9137 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
9138 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
9140 mono_icall_unlock ();
9145 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
9147 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);