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_exception_instance (error, mono_class_get_exception_for_failure (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_RuntimeType_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1216 mtype->type = &obj->vtable->klass->byval_arg;
1217 g_assert (mtype->type->type);
1221 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1223 MONO_CHECK_ARG_NULL (obj, 0);
1226 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1227 mono_error_set_pending_exception (&error);
1232 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1233 MonoReflectionMethod *method,
1234 MonoArray *opt_param_types)
1236 MONO_CHECK_ARG_NULL (method, 0);
1239 gint32 result = mono_image_create_method_token (
1240 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1241 mono_error_set_pending_exception (&error);
1246 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1249 mono_image_create_pefile (mb, file, &error);
1250 mono_error_set_pending_exception (&error);
1254 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1257 mono_image_build_metadata (mb, &error);
1258 mono_error_set_pending_exception (&error);
1262 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1264 mono_image_register_token (mb->dynamic_image, token, obj);
1267 ICALL_EXPORT MonoObject*
1268 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1272 mono_loader_lock ();
1273 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1274 mono_loader_unlock ();
1279 ICALL_EXPORT MonoReflectionModule*
1280 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1283 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1284 mono_error_set_pending_exception (&error);
1289 * ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class:
1290 * @tb: a TypeBuilder object
1293 * Creates the generic class after all generic parameters have been added.
1296 ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class (MonoReflectionTypeBuilder *tb)
1299 (void) mono_reflection_create_generic_class (tb, &error);
1300 mono_error_set_pending_exception (&error);
1303 #ifndef DISABLE_REFLECTION_EMIT
1304 ICALL_EXPORT MonoArray*
1305 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
1308 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
1309 mono_error_set_pending_exception (&error);
1315 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1317 MonoMethod **dest = (MonoMethod **)data;
1319 /* skip unmanaged frames */
1324 if (!strcmp (m->klass->name_space, "System.Reflection"))
1333 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1335 MonoMethod **dest = (MonoMethod **)data;
1337 /* skip unmanaged frames */
1341 if (m->wrapper_type != MONO_WRAPPER_NONE)
1349 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1360 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1362 MonoMethod **dest = (MonoMethod **)data;
1364 /* skip unmanaged frames */
1368 if (m->wrapper_type != MONO_WRAPPER_NONE)
1376 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1377 || (!strcmp (m->klass->name_space, "System"))))
1387 static MonoReflectionType *
1388 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1390 MonoMethod *m, *dest;
1392 MonoType *type = NULL;
1393 MonoAssembly *assembly = NULL;
1394 gboolean type_resolve = FALSE;
1395 MonoImage *rootimage = NULL;
1397 mono_error_init (error);
1400 * We must compute the calling assembly as type loading must happen under a metadata context.
1401 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1402 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1404 m = mono_method_get_last_managed ();
1406 if (m && m->klass->image != mono_defaults.corlib) {
1407 /* Happens with inlining */
1409 /* Ugly hack: type_from_parsed_name is called from
1410 * System.Type.internal_from_name, which is called most
1411 * directly from System.Type.GetType(string,bool,bool) but
1412 * also indirectly from places such as
1413 * System.Type.GetType(string,func,func) (via
1414 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1415 * so we need to skip over all of those to find the true caller.
1417 * It would be nice if we had stack marks.
1419 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1425 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1426 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1427 * to crash. This only seems to happen in some strange remoting
1428 * scenarios and I was unable to figure out what's happening there.
1429 * Dec 10, 2005 - Martin.
1433 assembly = dest->klass->image->assembly;
1434 type_resolve = TRUE;
1435 rootimage = assembly->image;
1437 g_warning (G_STRLOC);
1440 if (info->assembly.name)
1441 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1444 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1445 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1446 return_val_if_nok (error, NULL);
1450 // Say we're looking for System.Generic.Dict<int, Local>
1451 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1452 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1453 // is messed up when we go to construct the Local as the type arg...
1455 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1456 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1457 if (!info->assembly.name && !type) {
1459 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1460 return_val_if_nok (error, NULL);
1462 if (assembly && !type && type_resolve) {
1463 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1464 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1465 return_val_if_nok (error, NULL);
1471 return mono_type_get_object_checked (mono_domain_get (), type, error);
1474 ICALL_EXPORT MonoReflectionType*
1475 ves_icall_System_Type_internal_from_name (MonoString *name,
1476 MonoBoolean throwOnError,
1477 MonoBoolean ignoreCase)
1480 char *str = mono_string_to_utf8 (name);
1481 MonoTypeNameParse info;
1482 MonoReflectionType *type;
1485 parsedOk = mono_reflection_parse_type (str, &info);
1487 /* mono_reflection_parse_type() mangles the string */
1489 mono_reflection_free_type_info (&info);
1491 mono_error_init (&error);
1492 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1493 mono_error_set_pending_exception (&error);
1499 type = type_from_parsed_name (&info, ignoreCase, &error);
1501 mono_reflection_free_type_info (&info);
1504 if (!mono_error_ok (&error)) {
1506 mono_error_set_pending_exception (&error);
1508 mono_error_cleanup (&error);
1513 MonoException *e = NULL;
1516 e = mono_get_exception_type_load (name, NULL);
1519 mono_set_pending_exception (e);
1528 ICALL_EXPORT MonoReflectionType*
1529 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1532 MonoReflectionType *ret;
1533 MonoDomain *domain = mono_domain_get ();
1535 ret = mono_type_get_object_checked (domain, handle, &error);
1536 mono_error_set_pending_exception (&error);
1541 /* System.TypeCode */
1560 TYPECODE_STRING = 18
1563 ICALL_EXPORT guint32
1564 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1566 int t = type->type->type;
1568 if (type->type->byref)
1569 return TYPECODE_OBJECT;
1573 case MONO_TYPE_VOID:
1574 return TYPECODE_OBJECT;
1575 case MONO_TYPE_BOOLEAN:
1576 return TYPECODE_BOOLEAN;
1578 return TYPECODE_BYTE;
1580 return TYPECODE_SBYTE;
1582 return TYPECODE_UINT16;
1584 return TYPECODE_INT16;
1585 case MONO_TYPE_CHAR:
1586 return TYPECODE_CHAR;
1590 return TYPECODE_OBJECT;
1592 return TYPECODE_UINT32;
1594 return TYPECODE_INT32;
1596 return TYPECODE_UINT64;
1598 return TYPECODE_INT64;
1600 return TYPECODE_SINGLE;
1602 return TYPECODE_DOUBLE;
1603 case MONO_TYPE_VALUETYPE: {
1604 MonoClass *klass = type->type->data.klass;
1606 if (klass->enumtype) {
1607 t = mono_class_enum_basetype (klass)->type;
1609 } else if (mono_is_corlib_image (klass->image)) {
1610 if (strcmp (klass->name_space, "System") == 0) {
1611 if (strcmp (klass->name, "Decimal") == 0)
1612 return TYPECODE_DECIMAL;
1613 else if (strcmp (klass->name, "DateTime") == 0)
1614 return TYPECODE_DATETIME;
1617 return TYPECODE_OBJECT;
1619 case MONO_TYPE_STRING:
1620 return TYPECODE_STRING;
1621 case MONO_TYPE_SZARRAY:
1622 case MONO_TYPE_ARRAY:
1623 case MONO_TYPE_OBJECT:
1625 case MONO_TYPE_MVAR:
1626 case MONO_TYPE_TYPEDBYREF:
1627 return TYPECODE_OBJECT;
1628 case MONO_TYPE_CLASS:
1630 MonoClass *klass = type->type->data.klass;
1631 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1632 if (strcmp (klass->name, "DBNull") == 0)
1633 return TYPECODE_DBNULL;
1636 return TYPECODE_OBJECT;
1637 case MONO_TYPE_GENERICINST:
1638 return TYPECODE_OBJECT;
1640 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1646 mono_type_is_primitive (MonoType *type)
1648 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1649 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1653 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1655 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1656 return mono_class_enum_basetype (type->data.klass);
1657 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1658 return mono_class_enum_basetype (type->data.generic_class->container_class);
1662 ICALL_EXPORT guint32
1663 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1668 g_assert (type != NULL);
1670 klass = mono_class_from_mono_type (type->type);
1671 klassc = mono_class_from_mono_type (c->type);
1673 if (type->type->byref ^ c->type->byref)
1676 if (type->type->byref) {
1677 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1678 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1680 klass = mono_class_from_mono_type (t);
1681 klassc = mono_class_from_mono_type (ot);
1683 if (mono_type_is_primitive (t)) {
1684 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1685 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1686 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1687 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1688 return t->type == ot->type;
1690 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1693 if (klass->valuetype)
1694 return klass == klassc;
1695 return klass->valuetype == klassc->valuetype;
1698 return mono_class_is_assignable_from (klass, klassc);
1701 ICALL_EXPORT guint32
1702 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1705 MonoClass *klass = mono_class_from_mono_type (type->type);
1706 mono_class_init_checked (klass, &error);
1707 if (!is_ok (&error)) {
1708 mono_error_set_pending_exception (&error);
1711 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1712 mono_error_set_pending_exception (&error);
1716 ICALL_EXPORT guint32
1717 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1719 MonoClass *klass = mono_class_from_mono_type (type->type);
1720 return klass->flags;
1723 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1724 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1727 MonoClass *klass = field->field->parent;
1728 MonoMarshalType *info;
1732 if (klass->generic_container ||
1733 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1736 ftype = mono_field_get_type (field->field);
1737 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1740 info = mono_marshal_load_type_info (klass);
1742 for (i = 0; i < info->num_fields; ++i) {
1743 if (info->fields [i].field == field->field) {
1744 if (!info->fields [i].mspec)
1747 MonoReflectionMarshalAsAttribute* obj;
1748 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1749 if (!mono_error_ok (&error))
1750 mono_error_set_pending_exception (&error);
1759 ICALL_EXPORT MonoReflectionField*
1760 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1763 gboolean found = FALSE;
1770 klass = handle->parent;
1772 klass = mono_class_from_mono_type (type);
1774 /* Check that the field belongs to the class */
1775 for (k = klass; k; k = k->parent) {
1776 if (k == handle->parent) {
1783 /* The managed code will throw the exception */
1787 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1788 mono_error_set_pending_exception (&error);
1792 ICALL_EXPORT MonoArray*
1793 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1796 MonoType *type = mono_field_get_type_checked (field->field, &error);
1799 if (!mono_error_ok (&error)) {
1800 mono_error_set_pending_exception (&error);
1804 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1805 mono_error_set_pending_exception (&error);
1810 vell_icall_get_method_attributes (MonoMethod *method)
1812 return method->flags;
1816 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1819 MonoReflectionType *rt;
1820 MonoDomain *domain = mono_domain_get ();
1821 MonoMethodSignature* sig;
1823 sig = mono_method_signature_checked (method, &error);
1824 if (!mono_error_ok (&error)) {
1825 mono_error_set_pending_exception (&error);
1829 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1830 if (!mono_error_ok (&error)) {
1831 mono_error_set_pending_exception (&error);
1835 MONO_STRUCT_SETREF (info, parent, rt);
1837 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1838 if (!mono_error_ok (&error)) {
1839 mono_error_set_pending_exception (&error);
1843 MONO_STRUCT_SETREF (info, ret, rt);
1845 info->attrs = method->flags;
1846 info->implattrs = method->iflags;
1847 if (sig->call_convention == MONO_CALL_DEFAULT)
1848 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1850 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1855 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1858 ICALL_EXPORT MonoArray*
1859 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1862 MonoDomain *domain = mono_domain_get ();
1864 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1865 mono_error_set_pending_exception (&error);
1869 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1870 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1873 MonoDomain *domain = mono_domain_get ();
1874 MonoReflectionMarshalAsAttribute* res = NULL;
1875 MonoMarshalSpec **mspecs;
1878 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1879 mono_method_get_marshal_info (method, mspecs);
1882 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1883 if (!mono_error_ok (&error)) {
1884 mono_error_set_pending_exception (&error);
1889 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1891 mono_metadata_free_marshal_spec (mspecs [i]);
1898 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1900 MonoClass *parent = field->field->parent;
1901 if (!parent->size_inited)
1902 mono_class_init (parent);
1903 mono_class_setup_fields_locking (parent);
1905 return field->field->offset - sizeof (MonoObject);
1908 ICALL_EXPORT MonoReflectionType*
1909 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1912 MonoReflectionType *ret;
1915 parent = declaring? field->field->parent: field->klass;
1917 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1918 mono_error_set_pending_exception (&error);
1924 ICALL_EXPORT MonoObject *
1925 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1928 MonoClass *fklass = field->klass;
1929 MonoClassField *cf = field->field;
1930 MonoDomain *domain = mono_object_domain (field);
1932 if (fklass->image->assembly->ref_only) {
1933 mono_set_pending_exception (mono_get_exception_invalid_operation (
1934 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1938 if (mono_security_core_clr_enabled () &&
1939 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1940 mono_error_set_pending_exception (&error);
1944 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1945 mono_error_set_pending_exception (&error);
1950 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1953 MonoClassField *cf = field->field;
1957 if (field->klass->image->assembly->ref_only) {
1958 mono_set_pending_exception (mono_get_exception_invalid_operation (
1959 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1963 if (mono_security_core_clr_enabled () &&
1964 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1965 mono_error_set_pending_exception (&error);
1969 type = mono_field_get_type_checked (cf, &error);
1970 if (!mono_error_ok (&error)) {
1971 mono_error_set_pending_exception (&error);
1975 v = (gchar *) value;
1977 switch (type->type) {
1980 case MONO_TYPE_BOOLEAN:
1983 case MONO_TYPE_CHAR:
1992 case MONO_TYPE_VALUETYPE:
1995 v += sizeof (MonoObject);
1997 case MONO_TYPE_STRING:
1998 case MONO_TYPE_OBJECT:
1999 case MONO_TYPE_CLASS:
2000 case MONO_TYPE_ARRAY:
2001 case MONO_TYPE_SZARRAY:
2004 case MONO_TYPE_GENERICINST: {
2005 MonoGenericClass *gclass = type->data.generic_class;
2006 g_assert (!gclass->context.class_inst->is_open);
2008 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
2009 MonoClass *nklass = mono_class_from_mono_type (type);
2010 MonoObject *nullable;
2013 * Convert the boxed vtype into a Nullable structure.
2014 * This is complicated by the fact that Nullables have
2015 * a variable structure.
2017 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2018 if (!mono_error_ok (&error)) {
2019 mono_error_set_pending_exception (&error);
2023 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2025 v = (gchar *)mono_object_unbox (nullable);
2028 if (gclass->container_class->valuetype && (v != NULL))
2029 v += sizeof (MonoObject);
2033 g_error ("type 0x%x not handled in "
2034 "ves_icall_FieldInfo_SetValueInternal", type->type);
2039 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2040 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2041 if (!is_ok (&error)) {
2042 mono_error_set_pending_exception (&error);
2045 if (!vtable->initialized) {
2046 if (!mono_runtime_class_init_full (vtable, &error)) {
2047 mono_error_set_pending_exception (&error);
2051 mono_field_static_set_value (vtable, cf, v);
2053 mono_field_set_value (obj, cf, v);
2058 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2067 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2068 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2072 if (MONO_TYPE_IS_REFERENCE (f->type))
2073 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2075 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2078 ICALL_EXPORT MonoObject *
2079 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2081 MonoObject *o = NULL;
2082 MonoClassField *field = rfield->field;
2084 MonoDomain *domain = mono_object_domain (rfield);
2086 MonoTypeEnum def_type;
2087 const char *def_value;
2091 mono_class_init (field->parent);
2093 t = mono_field_get_type_checked (field, &error);
2094 if (!mono_error_ok (&error)) {
2095 mono_error_set_pending_exception (&error);
2099 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2100 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2104 if (image_is_dynamic (field->parent->image)) {
2105 MonoClass *klass = field->parent;
2106 int fidx = field - klass->fields;
2108 g_assert (fidx >= 0 && fidx < klass->field.count);
2109 g_assert (klass->ext);
2110 g_assert (klass->ext->field_def_values);
2111 def_type = klass->ext->field_def_values [fidx].def_type;
2112 def_value = klass->ext->field_def_values [fidx].data;
2113 if (def_type == MONO_TYPE_END) {
2114 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2118 def_value = mono_class_get_field_default_value (field, &def_type);
2119 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2121 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2126 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2130 case MONO_TYPE_BOOLEAN:
2133 case MONO_TYPE_CHAR:
2141 case MONO_TYPE_R8: {
2144 /* boxed value type */
2145 t = g_new0 (MonoType, 1);
2147 klass = mono_class_from_mono_type (t);
2149 o = mono_object_new_checked (domain, klass, &error);
2150 if (!mono_error_ok (&error)) {
2151 mono_error_set_pending_exception (&error);
2154 v = ((gchar *) o) + sizeof (MonoObject);
2155 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2156 if (mono_error_set_pending_exception (&error))
2160 case MONO_TYPE_STRING:
2161 case MONO_TYPE_CLASS:
2162 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2163 if (mono_error_set_pending_exception (&error))
2167 g_assert_not_reached ();
2173 ICALL_EXPORT MonoReflectionType*
2174 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2177 MonoReflectionType *ret;
2180 type = mono_field_get_type_checked (ref_field->field, &error);
2181 if (!mono_error_ok (&error)) {
2182 mono_error_set_pending_exception (&error);
2186 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2187 if (!mono_error_ok (&error)) {
2188 mono_error_set_pending_exception (&error);
2195 /* From MonoProperty.cs */
2197 PInfo_Attributes = 1,
2198 PInfo_GetMethod = 1 << 1,
2199 PInfo_SetMethod = 1 << 2,
2200 PInfo_ReflectedType = 1 << 3,
2201 PInfo_DeclaringType = 1 << 4,
2206 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2209 MonoReflectionType *rt;
2210 MonoReflectionMethod *rm;
2211 MonoDomain *domain = mono_object_domain (property);
2212 const MonoProperty *pproperty = property->property;
2214 if ((req_info & PInfo_ReflectedType) != 0) {
2215 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2216 if (mono_error_set_pending_exception (&error))
2219 MONO_STRUCT_SETREF (info, parent, rt);
2221 if ((req_info & PInfo_DeclaringType) != 0) {
2222 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2223 if (mono_error_set_pending_exception (&error))
2226 MONO_STRUCT_SETREF (info, declaring_type, rt);
2229 if ((req_info & PInfo_Name) != 0)
2230 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2232 if ((req_info & PInfo_Attributes) != 0)
2233 info->attrs = pproperty->attrs;
2235 if ((req_info & PInfo_GetMethod) != 0) {
2236 if (pproperty->get &&
2237 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2238 pproperty->get->klass == property->klass)) {
2239 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2240 if (mono_error_set_pending_exception (&error))
2246 MONO_STRUCT_SETREF (info, get, rm);
2248 if ((req_info & PInfo_SetMethod) != 0) {
2249 if (pproperty->set &&
2250 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2251 pproperty->set->klass == property->klass)) {
2252 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2253 if (mono_error_set_pending_exception (&error))
2259 MONO_STRUCT_SETREF (info, set, rm);
2262 * There may be other methods defined for properties, though, it seems they are not exposed
2263 * in the reflection API
2268 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2271 MonoReflectionType *rt;
2272 MonoReflectionMethod *rm;
2273 MonoDomain *domain = mono_object_domain (event);
2275 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2276 if (mono_error_set_pending_exception (&error))
2279 MONO_STRUCT_SETREF (info, reflected_type, rt);
2281 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2282 if (mono_error_set_pending_exception (&error))
2285 MONO_STRUCT_SETREF (info, declaring_type, rt);
2287 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2288 info->attrs = event->event->attrs;
2290 if (event->event->add) {
2291 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2292 if (mono_error_set_pending_exception (&error))
2298 MONO_STRUCT_SETREF (info, add_method, rm);
2300 if (event->event->remove) {
2301 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2302 if (mono_error_set_pending_exception (&error))
2308 MONO_STRUCT_SETREF (info, remove_method, rm);
2310 if (event->event->raise) {
2311 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2312 if (mono_error_set_pending_exception (&error))
2318 MONO_STRUCT_SETREF (info, raise_method, rm);
2320 #ifndef MONO_SMALL_CONFIG
2321 if (event->event->other) {
2323 while (event->event->other [n])
2325 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2326 if (mono_error_set_pending_exception (&error))
2328 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2330 for (i = 0; i < n; i++) {
2331 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2332 if (mono_error_set_pending_exception (&error))
2334 mono_array_setref (info->other_methods, i, rm);
2341 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2346 mono_class_setup_interfaces (klass, error);
2347 if (!mono_error_ok (error))
2350 for (i = 0; i < klass->interface_count; i++) {
2351 ic = klass->interfaces [i];
2352 g_hash_table_insert (ifaces, ic, ic);
2354 collect_interfaces (ic, ifaces, error);
2355 if (!mono_error_ok (error))
2361 MonoArray *iface_array;
2362 MonoGenericContext *context;
2366 } FillIfaceArrayData;
2369 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2371 MonoReflectionType *rt;
2372 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2373 MonoClass *ic = (MonoClass *)key;
2374 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2376 if (!mono_error_ok (data->error))
2379 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2380 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2381 if (!mono_error_ok (data->error))
2385 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2386 if (!mono_error_ok (data->error))
2389 mono_array_setref (data->iface_array, data->next_idx++, rt);
2392 mono_metadata_free_type (inflated);
2396 get_interfaces_hash (gconstpointer v1)
2398 MonoClass *k = (MonoClass*)v1;
2400 return k->type_token;
2403 ICALL_EXPORT MonoArray*
2404 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2407 MonoClass *klass = mono_class_from_mono_type (type->type);
2409 FillIfaceArrayData data = { 0 };
2412 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2414 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2415 data.context = mono_class_get_context (klass);
2416 klass = klass->generic_class->container_class;
2419 for (parent = klass; parent; parent = parent->parent) {
2420 mono_class_setup_interfaces (parent, &error);
2421 if (!mono_error_ok (&error))
2423 collect_interfaces (parent, iface_hash, &error);
2424 if (!mono_error_ok (&error))
2428 data.error = &error;
2429 data.domain = mono_object_domain (type);
2431 len = g_hash_table_size (iface_hash);
2433 g_hash_table_destroy (iface_hash);
2434 if (!data.domain->empty_types) {
2435 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2436 if (!is_ok (&error))
2439 return data.domain->empty_types;
2442 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2443 if (!is_ok (&error))
2445 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2446 if (!mono_error_ok (&error))
2449 g_hash_table_destroy (iface_hash);
2450 return data.iface_array;
2453 g_hash_table_destroy (iface_hash);
2454 mono_error_set_pending_exception (&error);
2459 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2461 gboolean variance_used;
2462 MonoClass *klass = mono_class_from_mono_type (type->type);
2463 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2464 MonoReflectionMethod *member;
2467 int i = 0, len, ioffset;
2471 mono_class_init_checked (klass, &error);
2472 if (mono_error_set_pending_exception (&error))
2474 mono_class_init_checked (iclass, &error);
2475 if (mono_error_set_pending_exception (&error))
2478 mono_class_setup_vtable (klass);
2480 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2484 len = mono_class_num_methods (iclass);
2485 domain = mono_object_domain (type);
2486 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2487 if (mono_error_set_pending_exception (&error))
2489 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2490 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2491 if (mono_error_set_pending_exception (&error))
2493 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2495 while ((method = mono_class_get_methods (iclass, &iter))) {
2496 member = mono_method_get_object_checked (domain, method, iclass, &error);
2497 if (mono_error_set_pending_exception (&error))
2499 mono_array_setref (*methods, i, member);
2500 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2501 if (mono_error_set_pending_exception (&error))
2503 mono_array_setref (*targets, i, member);
2510 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2513 MonoClass *klass = mono_class_from_mono_type (type->type);
2515 mono_class_init_checked (klass, &error);
2516 if (mono_error_set_pending_exception (&error))
2519 if (image_is_dynamic (klass->image)) {
2520 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2521 *packing = tb->packing_size;
2522 *size = tb->class_size;
2524 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2528 ICALL_EXPORT MonoReflectionType*
2529 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2532 MonoReflectionType *ret;
2535 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2536 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2537 mono_error_set_pending_exception (&error);
2541 klass = mono_class_from_mono_type (type->type);
2542 mono_class_init_checked (klass, &error);
2543 if (mono_error_set_pending_exception (&error))
2547 // GetElementType should only return a type for:
2548 // Array Pointer PassedByRef
2549 if (type->type->byref)
2550 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2551 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2552 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2553 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2554 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2558 mono_error_set_pending_exception (&error);
2563 ICALL_EXPORT MonoReflectionType*
2564 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2567 MonoReflectionType *ret;
2569 if (type->type->byref)
2572 MonoClass *klass = mono_class_from_mono_type (type->type);
2576 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2577 mono_error_set_pending_exception (&error);
2582 ICALL_EXPORT MonoBoolean
2583 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2585 return type->type->type == MONO_TYPE_PTR;
2588 ICALL_EXPORT MonoBoolean
2589 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2591 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)));
2594 ICALL_EXPORT MonoBoolean
2595 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2597 return type->type->byref;
2600 ICALL_EXPORT MonoBoolean
2601 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2604 MonoClass *klass = mono_class_from_mono_type (type->type);
2605 mono_class_init_checked (klass, &error);
2606 if (mono_error_set_pending_exception (&error))
2609 return mono_class_is_com_object (klass);
2612 ICALL_EXPORT guint32
2613 ves_icall_reflection_get_token (MonoObject* obj)
2616 guint32 result = mono_reflection_get_token_checked (obj, &error);
2617 mono_error_set_pending_exception (&error);
2621 ICALL_EXPORT MonoReflectionModule*
2622 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2625 MonoReflectionModule *result = NULL;
2626 MonoClass *klass = mono_class_from_mono_type (type->type);
2627 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2628 mono_error_set_pending_exception (&error);
2632 ICALL_EXPORT MonoReflectionAssembly*
2633 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2636 MonoDomain *domain = mono_domain_get ();
2637 MonoClass *klass = mono_class_from_mono_type (type->type);
2638 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2639 mono_error_set_pending_exception (&error);
2643 ICALL_EXPORT MonoReflectionType*
2644 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2647 MonoReflectionType *ret;
2648 MonoDomain *domain = mono_domain_get ();
2651 if (type->type->byref)
2653 if (type->type->type == MONO_TYPE_VAR) {
2654 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2655 klass = param ? param->owner.klass : NULL;
2656 } else if (type->type->type == MONO_TYPE_MVAR) {
2657 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2658 klass = param ? param->owner.method->klass : NULL;
2660 klass = mono_class_from_mono_type (type->type)->nested_in;
2666 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2667 mono_error_set_pending_exception (&error);
2672 ICALL_EXPORT MonoString*
2673 ves_icall_RuntimeType_get_Name (MonoReflectionType *type)
2675 MonoDomain *domain = mono_domain_get ();
2676 MonoClass *klass = mono_class_from_mono_type (type->type);
2678 if (type->type->byref) {
2679 char *n = g_strdup_printf ("%s&", klass->name);
2680 MonoString *res = mono_string_new (domain, n);
2686 return mono_string_new (domain, klass->name);
2690 ICALL_EXPORT MonoString*
2691 ves_icall_RuntimeType_get_Namespace (MonoReflectionType *type)
2693 MonoDomain *domain = mono_domain_get ();
2694 MonoClass *klass = mono_class_from_mono_type (type->type);
2696 while (klass->nested_in)
2697 klass = klass->nested_in;
2699 if (klass->name_space [0] == '\0')
2702 return mono_string_new (domain, klass->name_space);
2706 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2710 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2711 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2715 klass = mono_class_from_mono_type (type->type);
2721 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2723 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2726 ICALL_EXPORT MonoArray*
2727 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2730 MonoReflectionType *rt;
2732 MonoClass *klass, *pklass;
2733 MonoDomain *domain = mono_object_domain (type);
2736 klass = mono_class_from_mono_type (type->type);
2738 if (klass->generic_container) {
2739 MonoGenericContainer *container = klass->generic_container;
2740 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2741 if (mono_error_set_pending_exception (&error))
2743 for (i = 0; i < container->type_argc; ++i) {
2744 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2746 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2747 if (mono_error_set_pending_exception (&error))
2750 mono_array_setref (res, i, rt);
2752 } else if (klass->generic_class) {
2753 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2754 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2755 if (mono_error_set_pending_exception (&error))
2757 for (i = 0; i < inst->type_argc; ++i) {
2758 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2759 if (mono_error_set_pending_exception (&error))
2762 mono_array_setref (res, i, rt);
2770 ICALL_EXPORT gboolean
2771 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2775 if (!IS_MONOTYPE (type))
2778 if (type->type->byref)
2781 klass = mono_class_from_mono_type (type->type);
2782 return klass->generic_container != NULL;
2785 ICALL_EXPORT MonoReflectionType*
2786 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2789 MonoReflectionType *ret;
2792 if (type->type->byref)
2795 klass = mono_class_from_mono_type (type->type);
2797 if (klass->generic_container) {
2798 return type; /* check this one */
2800 if (klass->generic_class) {
2801 MonoClass *generic_class = klass->generic_class->container_class;
2804 tb = mono_class_get_ref_info (generic_class);
2806 if (generic_class->wastypebuilder && tb)
2807 return (MonoReflectionType *)tb;
2809 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2810 mono_error_set_pending_exception (&error);
2818 ICALL_EXPORT MonoReflectionType*
2819 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2822 MonoReflectionType *ret;
2824 MonoType *geninst, **types;
2827 g_assert (IS_MONOTYPE (type));
2828 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2829 if (mono_error_set_pending_exception (&error))
2832 count = mono_array_length (type_array);
2833 types = g_new0 (MonoType *, count);
2835 for (i = 0; i < count; i++) {
2836 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2837 types [i] = t->type;
2840 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2843 mono_error_set_pending_exception (&error);
2847 klass = mono_class_from_mono_type (geninst);
2849 /*we might inflate to the GTD*/
2850 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2851 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2855 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2856 mono_error_set_pending_exception (&error);
2861 ICALL_EXPORT gboolean
2862 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2866 if (!IS_MONOTYPE (type))
2869 if (type->type->byref)
2872 klass = mono_class_from_mono_type (type->type);
2873 return klass->generic_class != NULL || klass->generic_container != NULL;
2877 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2879 if (!IS_MONOTYPE (type))
2882 if (is_generic_parameter (type->type))
2883 return mono_type_get_generic_param_num (type->type);
2887 ICALL_EXPORT GenericParameterAttributes
2888 ves_icall_RuntimeType_GetGenericParameterAttributes (MonoReflectionType *type)
2890 g_assert (IS_MONOTYPE (type));
2891 g_assert (is_generic_parameter (type->type));
2892 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2895 ICALL_EXPORT MonoArray *
2896 ves_icall_RuntimeType_GetGenericParameterConstraints (MonoReflectionType *type)
2899 MonoReflectionType *rt;
2900 MonoGenericParamInfo *param_info;
2906 g_assert (IS_MONOTYPE (type));
2908 domain = mono_object_domain (type);
2909 param_info = mono_generic_param_info (type->type->data.generic_param);
2910 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2913 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, &error);
2914 if (mono_error_set_pending_exception (&error))
2916 for (i = 0; i < count; i++) {
2917 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2918 if (mono_error_set_pending_exception (&error))
2921 mono_array_setref (res, i, rt);
2928 ICALL_EXPORT MonoBoolean
2929 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2931 return is_generic_parameter (type->type);
2934 ICALL_EXPORT MonoBoolean
2935 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2937 return is_generic_parameter (tb->type.type);
2941 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2942 MonoReflectionType *t)
2944 enumtype->type = t->type;
2947 ICALL_EXPORT MonoReflectionMethod*
2948 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2949 MonoReflectionMethod* generic)
2956 MonoReflectionMethod *ret = NULL;
2958 domain = ((MonoObject *)type)->vtable->domain;
2960 klass = mono_class_from_mono_type (type->type);
2961 mono_class_init_checked (klass, &error);
2962 if (mono_error_set_pending_exception (&error))
2966 while ((method = mono_class_get_methods (klass, &iter))) {
2967 if (method->token == generic->method->token) {
2968 ret = mono_method_get_object_checked (domain, method, klass, &error);
2969 if (mono_error_set_pending_exception (&error))
2977 ICALL_EXPORT MonoReflectionMethod *
2978 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
2981 MonoType *type = ref_type->type;
2983 MonoReflectionMethod *ret = NULL;
2985 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2986 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2989 if (type->type == MONO_TYPE_VAR)
2992 method = mono_type_get_generic_param_owner (type)->owner.method;
2995 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2996 if (!mono_error_ok (&error))
2997 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3001 ICALL_EXPORT MonoBoolean
3002 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
3004 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3008 ICALL_EXPORT MonoBoolean
3009 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
3011 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3016 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
3018 MonoDomain *domain = mono_domain_get ();
3019 MonoImage *image = method->method->klass->image;
3020 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
3021 MonoTableInfo *tables = image->tables;
3022 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
3023 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
3024 guint32 im_cols [MONO_IMPLMAP_SIZE];
3025 guint32 scope_token;
3026 const char *import = NULL;
3027 const char *scope = NULL;
3029 if (image_is_dynamic (image)) {
3030 MonoReflectionMethodAux *method_aux =
3031 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
3033 import = method_aux->dllentry;
3034 scope = method_aux->dll;
3037 if (!import || !scope) {
3038 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
3043 if (piinfo->implmap_idx) {
3044 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
3046 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
3047 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
3048 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
3049 scope = mono_metadata_string_heap (image, scope_token);
3053 *flags = piinfo->piflags;
3054 *entry_point = mono_string_new (domain, import);
3055 *dll_name = mono_string_new (domain, scope);
3058 ICALL_EXPORT MonoReflectionMethod *
3059 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3061 MonoMethodInflated *imethod;
3063 MonoReflectionMethod *ret = NULL;
3066 if (method->method->is_generic)
3069 if (!method->method->is_inflated)
3072 imethod = (MonoMethodInflated *) method->method;
3074 result = imethod->declaring;
3075 /* Not a generic method. */
3076 if (!result->is_generic)
3079 if (image_is_dynamic (method->method->klass->image)) {
3080 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3081 MonoReflectionMethod *res;
3084 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3085 * the dynamic case as well ?
3087 mono_image_lock ((MonoImage*)image);
3088 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3089 mono_image_unlock ((MonoImage*)image);
3095 if (imethod->context.class_inst) {
3096 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3097 /*Generic methods gets the context of the GTD.*/
3098 if (mono_class_get_context (klass)) {
3099 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3100 if (!mono_error_ok (&error))
3105 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3107 if (!mono_error_ok (&error))
3108 mono_error_set_pending_exception (&error);
3112 ICALL_EXPORT gboolean
3113 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3115 return mono_method_signature (method->method)->generic_param_count != 0;
3118 ICALL_EXPORT gboolean
3119 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3121 return method->method->is_generic;
3124 ICALL_EXPORT MonoArray*
3125 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3128 MonoReflectionType *rt;
3133 domain = mono_object_domain (method);
3135 if (method->method->is_inflated) {
3136 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3139 count = inst->type_argc;
3140 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3141 if (mono_error_set_pending_exception (&error))
3144 for (i = 0; i < count; i++) {
3145 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3146 if (mono_error_set_pending_exception (&error))
3149 mono_array_setref (res, i, rt);
3156 count = mono_method_signature (method->method)->generic_param_count;
3157 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3158 if (mono_error_set_pending_exception (&error))
3161 for (i = 0; i < count; i++) {
3162 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3163 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3164 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3166 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3167 if (mono_error_set_pending_exception (&error))
3170 mono_array_setref (res, i, rt);
3176 ICALL_EXPORT MonoObject *
3177 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3181 * Invoke from reflection is supposed to always be a virtual call (the API
3182 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3183 * greater flexibility.
3185 MonoMethod *m = method->method;
3186 MonoMethodSignature *sig = mono_method_signature (m);
3189 void *obj = this_arg;
3193 if (mono_security_core_clr_enabled () &&
3194 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3195 mono_error_set_pending_exception (&error);
3199 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3200 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3201 mono_error_cleanup (&error); /* FIXME does this make sense? */
3202 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3207 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3208 if (!is_ok (&error)) {
3209 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3212 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3213 char *target_name = mono_type_get_full_name (m->klass);
3214 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3215 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3217 g_free (target_name);
3221 m = mono_object_get_virtual_method (this_arg, m);
3222 /* must pass the pointer to the value for valuetype methods */
3223 if (m->klass->valuetype)
3224 obj = mono_object_unbox (this_arg);
3225 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3226 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3231 if (sig->ret->byref) {
3232 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"));
3236 pcount = params? mono_array_length (params): 0;
3237 if (pcount != sig->param_count) {
3238 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3242 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3243 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."));
3247 image = m->klass->image;
3248 if (image->assembly->ref_only) {
3249 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."));
3253 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3254 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3258 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3262 intptr_t *lower_bounds;
3263 pcount = mono_array_length (params);
3264 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3265 /* Note: the synthetized array .ctors have int32 as argument type */
3266 for (i = 0; i < pcount; ++i)
3267 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3269 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3270 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3271 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3272 if (!mono_error_ok (&error)) {
3273 mono_error_set_pending_exception (&error);
3277 for (i = 0; i < mono_array_length (arr); ++i) {
3278 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3279 if (!mono_error_ok (&error)) {
3280 mono_error_set_pending_exception (&error);
3283 mono_array_setref_fast (arr, i, subarray);
3285 return (MonoObject*)arr;
3288 if (m->klass->rank == pcount) {
3289 /* Only lengths provided. */
3290 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3291 if (!mono_error_ok (&error)) {
3292 mono_error_set_pending_exception (&error);
3296 return (MonoObject*)arr;
3298 g_assert (pcount == (m->klass->rank * 2));
3299 /* The arguments are lower-bound-length pairs */
3300 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3302 for (i = 0; i < pcount / 2; ++i) {
3303 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3304 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3307 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3308 if (!mono_error_ok (&error)) {
3309 mono_error_set_pending_exception (&error);
3313 return (MonoObject*)arr;
3316 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3317 mono_error_set_pending_exception (&error);
3321 #ifndef DISABLE_REMOTING
3322 ICALL_EXPORT MonoObject *
3323 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3326 MonoDomain *domain = mono_object_domain (method);
3327 MonoMethod *m = method->method;
3328 MonoMethodSignature *sig = mono_method_signature (m);
3329 MonoArray *out_args;
3331 int i, j, outarg_count = 0;
3333 if (m->klass == mono_defaults.object_class) {
3334 if (!strcmp (m->name, "FieldGetter")) {
3335 MonoClass *k = this_arg->vtable->klass;
3339 /* If this is a proxy, then it must be a CBO */
3340 if (k == mono_defaults.transparent_proxy_class) {
3341 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3342 this_arg = tp->rp->unwrapped_server;
3343 g_assert (this_arg);
3344 k = this_arg->vtable->klass;
3347 name = mono_array_get (params, MonoString *, 1);
3348 str = mono_string_to_utf8 (name);
3351 MonoClassField* field = mono_class_get_field_from_name (k, str);
3354 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3355 if (field_klass->valuetype) {
3356 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3357 if (mono_error_set_pending_exception (&error))
3360 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3362 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3363 if (mono_error_set_pending_exception (&error))
3365 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3366 mono_array_setref (out_args, 0, result);
3373 g_assert_not_reached ();
3375 } else if (!strcmp (m->name, "FieldSetter")) {
3376 MonoClass *k = this_arg->vtable->klass;
3382 /* If this is a proxy, then it must be a CBO */
3383 if (k == mono_defaults.transparent_proxy_class) {
3384 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3385 this_arg = tp->rp->unwrapped_server;
3386 g_assert (this_arg);
3387 k = this_arg->vtable->klass;
3390 name = mono_array_get (params, MonoString *, 1);
3391 str = mono_string_to_utf8 (name);
3394 MonoClassField* field = mono_class_get_field_from_name (k, str);
3397 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3398 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3400 if (field_klass->valuetype) {
3401 size = mono_type_size (field->type, &align);
3402 g_assert (size == mono_class_value_size (field_klass, NULL));
3403 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3405 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3408 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3409 if (mono_error_set_pending_exception (&error))
3411 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3420 g_assert_not_reached ();
3425 for (i = 0; i < mono_array_length (params); i++) {
3426 if (sig->params [i]->byref)
3430 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3431 if (mono_error_set_pending_exception (&error))
3434 /* handle constructors only for objects already allocated */
3435 if (!strcmp (method->method->name, ".ctor"))
3436 g_assert (this_arg);
3438 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3439 g_assert (!method->method->klass->valuetype);
3440 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3441 if (mono_error_set_pending_exception (&error))
3444 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3445 if (sig->params [i]->byref) {
3447 arg = mono_array_get (params, gpointer, i);
3448 mono_array_setref (out_args, j, arg);
3453 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3460 read_enum_value (const char *mem, int type)
3463 case MONO_TYPE_BOOLEAN:
3465 return *(guint8*)mem;
3467 return *(gint8*)mem;
3468 case MONO_TYPE_CHAR:
3470 return read16 (mem);
3472 return (gint16) read16 (mem);
3474 return read32 (mem);
3476 return (gint32) read32 (mem);
3479 return read64 (mem);
3481 g_assert_not_reached ();
3487 write_enum_value (char *mem, int type, guint64 value)
3491 case MONO_TYPE_I1: {
3492 guint8 *p = (guint8*)mem;
3498 case MONO_TYPE_CHAR: {
3499 guint16 *p = (guint16 *)mem;
3504 case MONO_TYPE_I4: {
3505 guint32 *p = (guint32 *)mem;
3510 case MONO_TYPE_I8: {
3511 guint64 *p = (guint64 *)mem;
3516 g_assert_not_reached ();
3521 ICALL_EXPORT MonoObject *
3522 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3530 domain = mono_object_domain (enumType);
3531 enumc = mono_class_from_mono_type (enumType->type);
3533 mono_class_init_checked (enumc, &error);
3534 if (mono_error_set_pending_exception (&error))
3537 etype = mono_class_enum_basetype (enumc);
3539 res = mono_object_new_checked (domain, enumc, &error);
3540 if (mono_error_set_pending_exception (&error))
3542 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3547 ICALL_EXPORT MonoBoolean
3548 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3550 int size = mono_class_value_size (a->vtable->klass, NULL);
3551 guint64 a_val = 0, b_val = 0;
3553 memcpy (&a_val, mono_object_unbox (a), size);
3554 memcpy (&b_val, mono_object_unbox (b), size);
3556 return (a_val & b_val) == b_val;
3559 ICALL_EXPORT MonoObject *
3560 ves_icall_System_Enum_get_value (MonoObject *eobj)
3572 g_assert (eobj->vtable->klass->enumtype);
3574 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3575 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3576 if (mono_error_set_pending_exception (&error))
3578 dst = (char *)res + sizeof (MonoObject);
3579 src = (char *)eobj + sizeof (MonoObject);
3580 size = mono_class_value_size (enumc, NULL);
3582 memcpy (dst, src, size);
3587 ICALL_EXPORT MonoReflectionType *
3588 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3591 MonoReflectionType *ret;
3595 klass = mono_class_from_mono_type (type->type);
3596 mono_class_init_checked (klass, &error);
3597 if (mono_error_set_pending_exception (&error))
3600 etype = mono_class_enum_basetype (klass);
3602 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3606 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3607 mono_error_set_pending_exception (&error);
3613 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3615 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3616 gpointer odata = (char *)other + sizeof (MonoObject);
3617 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3618 g_assert (basetype);
3623 if (eobj->vtable->klass != other->vtable->klass)
3626 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3627 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3628 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3631 return me > other ? 1 : -1; \
3634 switch (basetype->type) {
3636 COMPARE_ENUM_VALUES (guint8);
3638 COMPARE_ENUM_VALUES (gint8);
3639 case MONO_TYPE_CHAR:
3641 COMPARE_ENUM_VALUES (guint16);
3643 COMPARE_ENUM_VALUES (gint16);
3645 COMPARE_ENUM_VALUES (guint32);
3647 COMPARE_ENUM_VALUES (gint32);
3649 COMPARE_ENUM_VALUES (guint64);
3651 COMPARE_ENUM_VALUES (gint64);
3655 #undef COMPARE_ENUM_VALUES
3656 /* indicates that the enum was of an unsupported unerlying type */
3661 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3663 gpointer data = (char *)eobj + sizeof (MonoObject);
3664 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3665 g_assert (basetype);
3667 switch (basetype->type) {
3668 case MONO_TYPE_I1: {
3669 gint8 value = *((gint8*)data);
3670 return ((int)value ^ (int)value << 8);
3673 return *((guint8*)data);
3674 case MONO_TYPE_CHAR:
3676 return *((guint16*)data);
3678 case MONO_TYPE_I2: {
3679 gint16 value = *((gint16*)data);
3680 return ((int)(guint16)value | (((int)value) << 16));
3683 return *((guint32*)data);
3685 return *((gint32*)data);
3687 case MONO_TYPE_I8: {
3688 gint64 value = *((gint64*)data);
3689 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3692 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3697 ICALL_EXPORT MonoBoolean
3698 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3701 MonoDomain *domain = mono_object_domain (type);
3702 MonoClass *enumc = mono_class_from_mono_type (type->type);
3703 guint j = 0, nvalues;
3705 MonoClassField *field;
3707 guint64 field_value, previous_value = 0;
3708 gboolean sorted = TRUE;
3710 mono_class_init_checked (enumc, &error);
3711 if (mono_error_set_pending_exception (&error))
3715 if (!enumc->enumtype) {
3716 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3720 base_type = mono_class_enum_basetype (enumc)->type;
3722 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3723 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3724 if (mono_error_set_pending_exception (&error))
3726 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3727 if (mono_error_set_pending_exception (&error))
3731 while ((field = mono_class_get_fields (enumc, &iter))) {
3733 MonoTypeEnum def_type;
3735 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3737 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3739 if (mono_field_is_deleted (field))
3741 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3743 p = mono_class_get_field_default_value (field, &def_type);
3744 /* len = */ mono_metadata_decode_blob_size (p, &p);
3746 field_value = read_enum_value (p, base_type);
3747 mono_array_set (*values, guint64, j, field_value);
3749 if (previous_value > field_value)
3752 previous_value = field_value;
3760 BFLAGS_IgnoreCase = 1,
3761 BFLAGS_DeclaredOnly = 2,
3762 BFLAGS_Instance = 4,
3764 BFLAGS_Public = 0x10,
3765 BFLAGS_NonPublic = 0x20,
3766 BFLAGS_FlattenHierarchy = 0x40,
3767 BFLAGS_InvokeMethod = 0x100,
3768 BFLAGS_CreateInstance = 0x200,
3769 BFLAGS_GetField = 0x400,
3770 BFLAGS_SetField = 0x800,
3771 BFLAGS_GetProperty = 0x1000,
3772 BFLAGS_SetProperty = 0x2000,
3773 BFLAGS_ExactBinding = 0x10000,
3774 BFLAGS_SuppressChangeType = 0x20000,
3775 BFLAGS_OptionalParamBinding = 0x40000
3778 ICALL_EXPORT MonoArray*
3779 ves_icall_RuntimeType_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3783 MonoClass *startklass, *klass, *refklass;
3788 char *utf8_name = NULL;
3789 int (*compare_func) (const char *s1, const char *s2) = NULL;
3790 MonoClassField *field;
3791 MonoPtrArray tmp_array;
3793 domain = ((MonoObject *)type)->vtable->domain;
3794 if (type->type->byref) {
3795 MonoArray *result = mono_array_new_checked (domain, mono_defaults.field_info_class, 0, &error);
3796 mono_error_set_pending_exception (&error);
3800 klass = startklass = mono_class_from_mono_type (type->type);
3801 refklass = mono_class_from_mono_type (reftype->type);
3803 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3806 if (mono_class_has_failure (klass)) {
3807 mono_ptr_array_destroy (tmp_array);
3808 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3813 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3814 guint32 flags = mono_field_get_flags (field);
3816 if (mono_field_is_deleted_with_flags (field, flags))
3818 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3819 if (bflags & BFLAGS_Public)
3821 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3822 if (bflags & BFLAGS_NonPublic) {
3829 if (flags & FIELD_ATTRIBUTE_STATIC) {
3830 if (bflags & BFLAGS_Static)
3831 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3834 if (bflags & BFLAGS_Instance)
3842 if (utf8_name == NULL) {
3843 utf8_name = mono_string_to_utf8 (name);
3844 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3847 if (compare_func (mono_field_get_name (field), utf8_name))
3851 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3852 if (!mono_error_ok (&error))
3854 mono_ptr_array_append (tmp_array, member);
3856 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3859 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array), &error);
3860 if (!is_ok (&error))
3863 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3864 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3866 mono_ptr_array_destroy (tmp_array);
3868 if (utf8_name != NULL)
3873 mono_ptr_array_destroy (tmp_array);
3874 mono_error_set_pending_exception (&error);
3879 method_nonpublic (MonoMethod* method, gboolean start_klass)
3881 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3882 case METHOD_ATTRIBUTE_ASSEM:
3883 return (start_klass || mono_defaults.generic_ilist_class);
3884 case METHOD_ATTRIBUTE_PRIVATE:
3886 case METHOD_ATTRIBUTE_PUBLIC:
3894 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3897 MonoClass *startklass;
3901 /*FIXME, use MonoBitSet*/
3902 guint32 method_slots_default [8];
3903 guint32 *method_slots = NULL;
3904 int (*compare_func) (const char *s1, const char *s2) = NULL;
3906 array = g_ptr_array_new ();
3911 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3913 /* An optimization for calls made from Delegate:CreateDelegate () */
3914 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3915 method = mono_get_delegate_invoke (klass);
3918 g_ptr_array_add (array, method);
3922 mono_class_setup_methods (klass);
3923 mono_class_setup_vtable (klass);
3924 if (mono_class_has_failure (klass))
3927 if (is_generic_parameter (&klass->byval_arg))
3928 nslots = mono_class_get_vtable_size (klass->parent);
3930 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3931 if (nslots >= sizeof (method_slots_default) * 8) {
3932 method_slots = g_new0 (guint32, nslots / 32 + 1);
3934 method_slots = method_slots_default;
3935 memset (method_slots, 0, sizeof (method_slots_default));
3938 mono_class_setup_methods (klass);
3939 mono_class_setup_vtable (klass);
3940 if (mono_class_has_failure (klass))
3944 while ((method = mono_class_get_methods (klass, &iter))) {
3946 if (method->slot != -1) {
3947 g_assert (method->slot < nslots);
3948 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3950 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3951 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3954 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3956 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3957 if (bflags & BFLAGS_Public)
3959 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3965 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3966 if (bflags & BFLAGS_Static)
3967 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3970 if (bflags & BFLAGS_Instance)
3978 if (compare_func (name, method->name))
3983 g_ptr_array_add (array, method);
3985 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3987 if (method_slots != method_slots_default)
3988 g_free (method_slots);
3993 if (method_slots != method_slots_default)
3994 g_free (method_slots);
3995 g_ptr_array_free (array, TRUE);
3997 if (mono_class_has_failure (klass)) {
3998 *ex = mono_class_get_exception_for_failure (klass);
4000 *ex = mono_get_exception_execution_engine ("Unknown error");
4005 ICALL_EXPORT MonoArray*
4006 ves_icall_RuntimeType_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4008 static MonoClass *MethodInfo_array;
4012 MonoVTable *array_vtable;
4013 MonoException *ex = NULL;
4014 const char *mname = NULL;
4015 GPtrArray *method_array;
4016 MonoClass *klass, *refklass;
4019 mono_error_init (&error);
4021 if (!MethodInfo_array) {
4022 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
4023 mono_memory_barrier ();
4024 MethodInfo_array = klass;
4027 klass = mono_class_from_mono_type (type->type);
4028 refklass = mono_class_from_mono_type (reftype->type);
4029 domain = ((MonoObject *)type)->vtable->domain;
4030 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
4031 if (!is_ok (&error)) {
4032 mono_error_set_pending_exception (&error);
4035 if (type->type->byref) {
4036 res = mono_array_new_specific_checked (array_vtable, 0, &error);
4037 mono_error_set_pending_exception (&error);
4043 mname = mono_string_to_utf8 (name);
4045 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
4046 g_free ((char*)mname);
4048 mono_set_pending_exception (ex);
4052 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
4053 if (!mono_error_ok (&error)) {
4054 mono_error_set_pending_exception (&error);
4058 for (i = 0; i < method_array->len; ++i) {
4059 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
4060 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
4061 if (!mono_error_ok (&error))
4063 mono_array_setref (res, i, rm);
4067 g_ptr_array_free (method_array, TRUE);
4068 if (!mono_error_ok (&error))
4069 mono_set_pending_exception (mono_error_convert_to_exception (&error));
4073 ICALL_EXPORT MonoArray*
4074 ves_icall_RuntimeType_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4077 MonoClass *startklass, *klass, *refklass;
4078 MonoArray *res = NULL;
4082 gpointer iter = NULL;
4083 MonoPtrArray tmp_array;
4086 domain = ((MonoObject *)type)->vtable->domain;
4087 if (type->type->byref) {
4088 res = mono_array_new_cached (domain, mono_defaults.method_info_class, 0, &error);
4089 mono_error_set_pending_exception (&error);
4093 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
4096 klass = startklass = mono_class_from_mono_type (type->type);
4097 refklass = mono_class_from_mono_type (reftype->type);
4099 mono_class_setup_methods (klass);
4100 if (mono_class_has_failure (klass)) {
4101 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
4106 while ((method = mono_class_get_methods (klass, &iter))) {
4108 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
4110 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4111 if (bflags & BFLAGS_Public)
4114 if (bflags & BFLAGS_NonPublic)
4120 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4121 if (bflags & BFLAGS_Static)
4122 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4125 if (bflags & BFLAGS_Instance)
4131 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
4132 if (mono_error_set_pending_exception (&error))
4135 mono_ptr_array_append (tmp_array, member);
4138 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array), &error);
4139 if (mono_error_set_pending_exception (&error))
4142 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4143 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4146 mono_ptr_array_destroy (tmp_array);
4152 property_hash (gconstpointer data)
4154 MonoProperty *prop = (MonoProperty*)data;
4156 return g_str_hash (prop->name);
4160 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
4162 if (method1->is_inflated)
4163 method1 = ((MonoMethodInflated*) method1)->declaring;
4164 if (method2->is_inflated)
4165 method2 = ((MonoMethodInflated*) method2)->declaring;
4167 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4171 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4173 // Properties are hide-by-name-and-signature
4174 if (!g_str_equal (prop1->name, prop2->name))
4177 /* If we see a property in a generic method, we want to
4178 compare the generic signatures, not the inflated signatures
4179 because we might conflate two properties that were
4183 public T this[T t] { getter { return t; } } // method 1
4184 public U this[U u] { getter { return u; } } // method 2
4187 If we see int Foo<int,int>::Item[int] we need to know if
4188 the indexer came from method 1 or from method 2, and we
4189 shouldn't conflate them. (Bugzilla 36283)
4191 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
4194 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4201 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4206 return method_nonpublic (accessor, start_klass);
4209 ICALL_EXPORT MonoArray*
4210 ves_icall_RuntimeType_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4214 MonoClass *startklass, *klass;
4220 gchar *propname = NULL;
4221 int (*compare_func) (const char *s1, const char *s2) = NULL;
4223 GHashTable *properties = NULL;
4224 MonoPtrArray tmp_array;
4226 mono_error_init (&error);
4228 domain = ((MonoObject *)type)->vtable->domain;
4229 if (type->type->byref) {
4230 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), 0, &error);
4231 mono_error_set_pending_exception (&error);
4235 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4237 klass = startklass = mono_class_from_mono_type (type->type);
4240 propname = mono_string_to_utf8 (name);
4241 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4244 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4246 mono_class_setup_methods (klass);
4247 mono_class_setup_vtable (klass);
4248 if (mono_class_has_failure (klass))
4252 while ((prop = mono_class_get_properties (klass, &iter))) {
4258 flags = method->flags;
4261 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4262 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4263 if (bflags & BFLAGS_Public)
4265 } else if (bflags & BFLAGS_NonPublic) {
4266 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4267 property_accessor_nonpublic(prop->set, startklass == klass)) {
4274 if (flags & METHOD_ATTRIBUTE_STATIC) {
4275 if (bflags & BFLAGS_Static)
4276 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4279 if (bflags & BFLAGS_Instance)
4288 if (compare_func (propname, prop->name))
4292 if (g_hash_table_lookup (properties, prop))
4295 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4298 mono_ptr_array_append (tmp_array, pr);
4300 g_hash_table_insert (properties, prop, prop);
4302 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4305 g_hash_table_destroy (properties);
4308 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array), &error);
4309 if (!is_ok (&error))
4311 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4312 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4314 mono_ptr_array_destroy (tmp_array);
4321 if (mono_class_has_failure (klass)) {
4322 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4327 g_hash_table_destroy (properties);
4330 mono_ptr_array_destroy (tmp_array);
4332 mono_error_set_pending_exception (&error);
4338 event_hash (gconstpointer data)
4340 MonoEvent *event = (MonoEvent*)data;
4342 return g_str_hash (event->name);
4346 event_equal (MonoEvent *event1, MonoEvent *event2)
4348 // Events are hide-by-name
4349 return g_str_equal (event1->name, event2->name);
4352 ICALL_EXPORT MonoArray*
4353 ves_icall_RuntimeType_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4357 MonoClass *startklass, *klass;
4363 char *utf8_name = NULL;
4364 int (*compare_func) (const char *s1, const char *s2) = NULL;
4365 GHashTable *events = NULL;
4366 MonoPtrArray tmp_array;
4368 mono_error_init (&error);
4370 domain = mono_object_domain (type);
4371 if (type->type->byref) {
4372 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), 0, &error);
4373 mono_error_set_pending_exception (&error);
4377 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4379 klass = startklass = mono_class_from_mono_type (type->type);
4381 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4383 mono_class_setup_methods (klass);
4384 mono_class_setup_vtable (klass);
4385 if (mono_class_has_failure (klass))
4389 while ((event = mono_class_get_events (klass, &iter))) {
4391 method = event->add;
4393 method = event->remove;
4395 method = event->raise;
4397 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4398 if (bflags & BFLAGS_Public)
4400 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4401 if (bflags & BFLAGS_NonPublic)
4406 if (bflags & BFLAGS_NonPublic)
4412 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4413 if (bflags & BFLAGS_Static)
4414 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4417 if (bflags & BFLAGS_Instance)
4422 if (bflags & BFLAGS_Instance)
4428 if (utf8_name == NULL) {
4429 utf8_name = mono_string_to_utf8 (name);
4430 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4433 if (compare_func (event->name, utf8_name))
4437 if (g_hash_table_lookup (events, event))
4440 MonoReflectionEvent *ev_obj;
4441 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4444 mono_ptr_array_append (tmp_array, ev_obj);
4446 g_hash_table_insert (events, event, event);
4448 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4451 g_hash_table_destroy (events);
4453 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array), &error);
4454 if (!is_ok (&error))
4457 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4458 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4460 mono_ptr_array_destroy (tmp_array);
4462 if (utf8_name != NULL)
4468 if (mono_class_has_failure (klass)) {
4469 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4475 g_hash_table_destroy (events);
4476 if (utf8_name != NULL)
4479 mono_ptr_array_destroy (tmp_array);
4481 mono_error_set_pending_exception (&error);
4485 ICALL_EXPORT MonoArray*
4486 ves_icall_RuntimeType_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4489 MonoReflectionType *rt;
4492 MonoArray *res = NULL;
4497 MonoPtrArray tmp_array;
4499 mono_error_init (&error);
4501 domain = ((MonoObject *)type)->vtable->domain;
4502 if (type->type->byref) {
4503 MonoArray *result = mono_array_new_cached (domain, mono_defaults.runtimetype_class, 0, &error);
4504 mono_error_set_pending_exception (&error);
4507 klass = mono_class_from_mono_type (type->type);
4510 * If a nested type is generic, return its generic type definition.
4511 * Note that this means that the return value is essentially the set
4512 * of nested types of the generic type definition of @klass.
4514 * A note in MSDN claims that a generic type definition can have
4515 * nested types that aren't generic. In any case, the container of that
4516 * nested type would be the generic type definition.
4518 if (klass->generic_class)
4519 klass = klass->generic_class->container_class;
4521 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4523 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4525 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4526 if (bflags & BFLAGS_Public)
4529 if (bflags & BFLAGS_NonPublic)
4537 str = mono_string_to_utf8 (name);
4538 mono_identifier_unescape_type_name_chars (str);
4541 if (strcmp (nested->name, str))
4545 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4546 if (!is_ok (&error))
4549 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4552 res = mono_array_new_cached (domain, mono_defaults.runtimetype_class, mono_ptr_array_size (tmp_array), &error);
4553 if (!is_ok (&error))
4556 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4557 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4560 mono_ptr_array_destroy (tmp_array);
4564 mono_error_set_pending_exception (&error);
4568 ICALL_EXPORT MonoReflectionType*
4569 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4572 MonoReflectionType *ret;
4574 MonoType *type = NULL;
4575 MonoTypeNameParse info;
4576 gboolean type_resolve;
4578 /* On MS.NET, this does not fire a TypeResolve event */
4579 type_resolve = TRUE;
4580 str = mono_string_to_utf8 (name);
4581 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4582 if (!mono_reflection_parse_type (str, &info)) {
4584 mono_reflection_free_type_info (&info);
4586 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4589 /*g_print ("failed parse\n");*/
4593 if (info.assembly.name) {
4595 mono_reflection_free_type_info (&info);
4597 /* 1.0 and 2.0 throw different exceptions */
4598 if (mono_defaults.generic_ilist_class)
4599 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4601 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4607 if (module != NULL) {
4608 if (module->image) {
4609 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4610 if (!is_ok (&error)) {
4612 mono_reflection_free_type_info (&info);
4613 mono_error_set_pending_exception (&error);
4620 if (assembly_is_dynamic (assembly->assembly)) {
4621 /* Enumerate all modules */
4622 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4626 if (abuilder->modules) {
4627 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4628 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4629 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4630 if (!is_ok (&error)) {
4632 mono_reflection_free_type_info (&info);
4633 mono_error_set_pending_exception (&error);
4641 if (!type && abuilder->loaded_modules) {
4642 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4643 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4644 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4645 if (!is_ok (&error)) {
4647 mono_reflection_free_type_info (&info);
4648 mono_error_set_pending_exception (&error);
4657 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4658 if (!is_ok (&error)) {
4660 mono_reflection_free_type_info (&info);
4661 mono_error_set_pending_exception (&error);
4666 mono_reflection_free_type_info (&info);
4668 MonoException *e = NULL;
4671 e = mono_get_exception_type_load (name, NULL);
4674 mono_set_pending_exception (e);
4678 if (type->type == MONO_TYPE_CLASS) {
4679 MonoClass *klass = mono_type_get_class (type);
4681 /* need to report exceptions ? */
4682 if (throwOnError && mono_class_has_failure (klass)) {
4683 /* report SecurityException (or others) that occured when loading the assembly */
4684 MonoException *exc = mono_class_get_exception_for_failure (klass);
4685 mono_set_pending_exception (exc);
4690 /* g_print ("got it\n"); */
4691 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4692 mono_error_set_pending_exception (&error);
4698 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4701 gchar *shadow_ini_file;
4704 /* Check for shadow-copied assembly */
4705 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4706 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4708 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4709 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4715 g_free (shadow_ini_file);
4716 if (content != NULL) {
4719 *filename = content;
4726 ICALL_EXPORT MonoString *
4727 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4729 MonoDomain *domain = mono_object_domain (assembly);
4730 MonoAssembly *mass = assembly->assembly;
4731 MonoString *res = NULL;
4736 if (g_path_is_absolute (mass->image->name)) {
4737 absolute = g_strdup (mass->image->name);
4738 dirname = g_path_get_dirname (absolute);
4740 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4741 dirname = g_strdup (mass->basedir);
4744 replace_shadow_path (domain, dirname, &absolute);
4749 for (i = strlen (absolute) - 1; i >= 0; i--)
4750 if (absolute [i] == '\\')
4755 uri = g_filename_to_uri (absolute, NULL, NULL);
4757 const char *prepend = "file://";
4759 if (*absolute == '/' && *(absolute + 1) == '/') {
4762 prepend = "file:///";
4765 uri = g_strconcat (prepend, absolute, NULL);
4769 res = mono_string_new (domain, uri);
4776 ICALL_EXPORT MonoBoolean
4777 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4779 MonoAssembly *mass = assembly->assembly;
4781 return mass->in_gac;
4784 ICALL_EXPORT MonoReflectionAssembly*
4785 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4790 MonoImageOpenStatus status;
4791 MonoReflectionAssembly* result = NULL;
4793 name = mono_string_to_utf8 (mname);
4794 res = mono_assembly_load_with_partial_name (name, &status);
4800 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4802 mono_error_set_pending_exception (&error);
4806 ICALL_EXPORT MonoString *
4807 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4809 MonoDomain *domain = mono_object_domain (assembly);
4812 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4817 ICALL_EXPORT MonoBoolean
4818 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4820 return assembly->assembly->ref_only;
4823 ICALL_EXPORT MonoString *
4824 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4826 MonoDomain *domain = mono_object_domain (assembly);
4828 return mono_string_new (domain, assembly->assembly->image->version);
4831 ICALL_EXPORT MonoReflectionMethod*
4832 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4835 MonoReflectionMethod *res = NULL;
4838 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4842 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4843 if (!mono_error_ok (&error))
4846 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4849 if (!mono_error_ok (&error))
4850 mono_error_set_pending_exception (&error);
4854 ICALL_EXPORT MonoReflectionModule*
4855 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4858 MonoReflectionModule *result = NULL;
4859 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4860 if (!mono_error_ok (&error))
4861 mono_error_set_pending_exception (&error);
4865 ICALL_EXPORT MonoArray*
4866 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4869 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4870 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4871 if (mono_error_set_pending_exception (&error))
4876 for (i = 0; i < table->rows; ++i) {
4877 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4878 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4884 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4886 static MonoMethod *create_version = NULL;
4890 mono_error_init (error);
4893 if (!create_version) {
4894 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4895 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4896 g_assert (create_version);
4897 mono_method_desc_free (desc);
4903 args [3] = &revision;
4904 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4905 return_val_if_nok (error, NULL);
4907 mono_runtime_invoke_checked (create_version, result, args, error);
4908 return_val_if_nok (error, NULL);
4913 ICALL_EXPORT MonoArray*
4914 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4918 MonoDomain *domain = mono_object_domain (assembly);
4920 static MonoMethod *create_culture = NULL;
4921 MonoImage *image = assembly->assembly->image;
4925 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4928 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4929 if (mono_error_set_pending_exception (&error))
4933 if (count > 0 && !create_culture) {
4934 MonoMethodDesc *desc = mono_method_desc_new (
4935 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4936 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4937 g_assert (create_culture);
4938 mono_method_desc_free (desc);
4941 for (i = 0; i < count; i++) {
4942 MonoObject *version;
4943 MonoReflectionAssemblyName *aname;
4944 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4946 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4948 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4949 domain, mono_class_get_assembly_name_class (), &error);
4950 if (mono_error_set_pending_exception (&error))
4953 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4955 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4956 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4957 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4958 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4959 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4960 aname->versioncompat = 1; /* SameMachine (default) */
4961 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4963 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4964 if (mono_error_set_pending_exception (&error))
4967 MONO_OBJECT_SETREF (aname, version, version);
4969 if (create_culture) {
4971 MonoBoolean assembly_ref = 1;
4972 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4973 args [1] = &assembly_ref;
4975 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4976 if (mono_error_set_pending_exception (&error))
4979 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4982 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4983 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4984 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4986 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4987 /* public key token isn't copied - the class library will
4988 automatically generate it from the public key if required */
4989 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4990 if (mono_error_set_pending_exception (&error))
4993 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4994 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4996 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4997 if (mono_error_set_pending_exception (&error))
5000 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5001 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
5004 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
5005 if (mono_error_set_pending_exception (&error))
5008 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5011 /* note: this function doesn't return the codebase on purpose (i.e. it can
5012 be used under partial trust as path information isn't present). */
5014 mono_array_setref (result, i, aname);
5019 /* move this in some file in mono/util/ */
5021 g_concat_dir_and_file (const char *dir, const char *file)
5023 g_return_val_if_fail (dir != NULL, NULL);
5024 g_return_val_if_fail (file != NULL, NULL);
5027 * If the directory name doesn't have a / on the end, we need
5028 * to add one so we get a proper path to the file
5030 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
5031 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
5033 return g_strconcat (dir, file, NULL);
5037 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
5040 char *n = mono_string_to_utf8 (name);
5041 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5043 guint32 cols [MONO_MANIFEST_SIZE];
5044 guint32 impl, file_idx;
5048 for (i = 0; i < table->rows; ++i) {
5049 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5050 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5051 if (strcmp (val, n) == 0)
5055 if (i == table->rows)
5058 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
5061 * this code should only be called after obtaining the
5062 * ResourceInfo and handling the other cases.
5064 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
5065 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
5067 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
5072 module = assembly->assembly->image;
5075 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
5076 if (mono_error_set_pending_exception (&error))
5078 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
5080 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
5083 ICALL_EXPORT gboolean
5084 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
5087 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5089 guint32 cols [MONO_MANIFEST_SIZE];
5090 guint32 file_cols [MONO_FILE_SIZE];
5094 n = mono_string_to_utf8 (name);
5095 for (i = 0; i < table->rows; ++i) {
5096 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5097 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5098 if (strcmp (val, n) == 0)
5102 if (i == table->rows)
5105 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
5106 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
5109 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
5110 case MONO_IMPLEMENTATION_FILE:
5111 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5112 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5113 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
5114 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
5115 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
5116 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
5119 info->location = RESOURCE_LOCATION_EMBEDDED;
5122 case MONO_IMPLEMENTATION_ASSEMBLYREF:
5123 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5124 mono_assembly_load_reference (assembly->assembly->image, i - 1);
5125 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
5126 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
5127 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
5129 mono_set_pending_exception (ex);
5132 MonoReflectionAssembly *assm_obj;
5133 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5135 mono_error_set_pending_exception (&error);
5138 MONO_OBJECT_SETREF (info, assembly, assm_obj);
5140 /* Obtain info recursively */
5141 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5142 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5145 case MONO_IMPLEMENTATION_EXP_TYPE:
5146 g_assert_not_reached ();
5154 ICALL_EXPORT MonoObject*
5155 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
5158 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5159 MonoArray *result = NULL;
5164 /* check hash if needed */
5166 n = mono_string_to_utf8 (name);
5167 for (i = 0; i < table->rows; ++i) {
5168 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5169 if (strcmp (val, n) == 0) {
5172 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5173 fn = mono_string_new (mono_object_domain (assembly), n);
5175 return (MonoObject*)fn;
5183 for (i = 0; i < table->rows; ++i) {
5184 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5188 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
5189 if (mono_error_set_pending_exception (&error))
5194 for (i = 0; i < table->rows; ++i) {
5195 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5196 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5197 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5198 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5203 return (MonoObject*)result;
5206 ICALL_EXPORT MonoArray*
5207 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5210 MonoDomain *domain = mono_domain_get();
5213 int i, j, file_count = 0;
5214 MonoImage **modules;
5215 guint32 module_count, real_module_count;
5216 MonoTableInfo *table;
5217 guint32 cols [MONO_FILE_SIZE];
5218 MonoImage *image = assembly->assembly->image;
5220 g_assert (image != NULL);
5221 g_assert (!assembly_is_dynamic (assembly->assembly));
5223 table = &image->tables [MONO_TABLE_FILE];
5224 file_count = table->rows;
5226 modules = image->modules;
5227 module_count = image->module_count;
5229 real_module_count = 0;
5230 for (i = 0; i < module_count; ++i)
5232 real_module_count ++;
5234 klass = mono_class_get_module_class ();
5235 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5236 if (mono_error_set_pending_exception (&error))
5239 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5240 if (mono_error_set_pending_exception (&error))
5243 mono_array_setref (res, 0, image_obj);
5245 for (i = 0; i < module_count; ++i)
5247 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5248 if (mono_error_set_pending_exception (&error))
5250 mono_array_setref (res, j, rm);
5254 for (i = 0; i < file_count; ++i, ++j) {
5255 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5256 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5257 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5258 if (mono_error_set_pending_exception (&error))
5260 mono_array_setref (res, j, rm);
5263 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5265 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5266 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5269 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5270 if (mono_error_set_pending_exception (&error))
5272 mono_array_setref (res, j, rm);
5279 ICALL_EXPORT MonoReflectionMethod*
5280 ves_icall_GetCurrentMethod (void)
5282 MonoReflectionMethod *res = NULL;
5285 MonoMethod *m = mono_method_get_last_managed ();
5288 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5292 while (m->is_inflated)
5293 m = ((MonoMethodInflated*)m)->declaring;
5295 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5296 mono_error_set_pending_exception (&error);
5302 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5305 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5308 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5309 //method is inflated, we should inflate it on the other class
5310 MonoGenericContext ctx;
5311 ctx.method_inst = inflated->context.method_inst;
5312 ctx.class_inst = inflated->context.class_inst;
5313 if (klass->generic_class)
5314 ctx.class_inst = klass->generic_class->context.class_inst;
5315 else if (klass->generic_container)
5316 ctx.class_inst = klass->generic_container->context.class_inst;
5317 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5318 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5322 mono_class_setup_methods (method->klass);
5323 if (mono_class_has_failure (method->klass))
5325 for (i = 0; i < method->klass->method.count; ++i) {
5326 if (method->klass->methods [i] == method) {
5331 mono_class_setup_methods (klass);
5332 if (mono_class_has_failure (klass))
5334 g_assert (offset >= 0 && offset < klass->method.count);
5335 return klass->methods [offset];
5338 ICALL_EXPORT MonoReflectionMethod*
5339 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5341 MonoReflectionMethod *res = NULL;
5345 klass = mono_class_from_mono_type (type);
5346 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5348 if (method->klass != klass) {
5349 method = mono_method_get_equivalent_method (method, klass);
5354 klass = method->klass;
5355 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5356 mono_error_set_pending_exception (&error);
5360 ICALL_EXPORT MonoReflectionMethodBody*
5361 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5364 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5365 mono_error_set_pending_exception (&error);
5369 ICALL_EXPORT MonoReflectionAssembly*
5370 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5373 MonoReflectionAssembly *result;
5374 MonoMethod *dest = NULL;
5376 mono_stack_walk_no_il (get_executing, &dest);
5378 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5380 mono_error_set_pending_exception (&error);
5385 ICALL_EXPORT MonoReflectionAssembly*
5386 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5389 MonoReflectionAssembly *result;
5390 MonoDomain* domain = mono_domain_get ();
5392 if (!domain->entry_assembly)
5395 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5397 mono_error_set_pending_exception (&error);
5401 ICALL_EXPORT MonoReflectionAssembly*
5402 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5407 MonoReflectionAssembly *result;
5410 mono_stack_walk_no_il (get_executing, &dest);
5412 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5416 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5419 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5421 mono_error_set_pending_exception (&error);
5425 ICALL_EXPORT MonoString *
5426 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5427 gboolean assembly_qualified)
5429 MonoDomain *domain = mono_object_domain (object);
5430 MonoTypeNameFormat format;
5435 format = assembly_qualified ?
5436 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5437 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5439 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5441 name = mono_type_get_name_full (object->type, format);
5445 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5450 res = mono_string_new (domain, name);
5457 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5460 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5462 mono_class_init_checked (klass, &error);
5463 mono_error_set_pending_exception (&error);
5464 return mono_security_core_clr_class_level (klass);
5468 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5470 MonoClassField *field = rfield->field;
5471 return mono_security_core_clr_field_level (field, TRUE);
5475 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5477 MonoMethod *method = rfield->method;
5478 return mono_security_core_clr_method_level (method, TRUE);
5482 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)
5484 static MonoMethod *create_culture = NULL;
5488 const char *pkey_ptr;
5490 MonoBoolean assembly_ref = 0;
5492 mono_error_init (error);
5494 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5495 aname->major = name->major;
5496 aname->minor = name->minor;
5497 aname->build = name->build;
5498 aname->flags = name->flags;
5499 aname->revision = name->revision;
5500 aname->hashalg = name->hash_alg;
5501 aname->versioncompat = 1; /* SameMachine (default) */
5502 aname->processor_architecture = name->arch;
5504 if (by_default_version) {
5505 MonoObject *version;
5507 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5508 return_if_nok (error);
5510 MONO_OBJECT_SETREF (aname, version, version);
5514 if (absolute != NULL && *absolute != '\0') {
5515 const gchar *prepend = "file://";
5518 codebase = g_strdup (absolute);
5523 for (i = strlen (codebase) - 1; i >= 0; i--)
5524 if (codebase [i] == '\\')
5527 if (*codebase == '/' && *(codebase + 1) == '/') {
5530 prepend = "file:///";
5534 result = g_strconcat (prepend, codebase, NULL);
5540 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5544 if (!create_culture) {
5545 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5546 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5547 g_assert (create_culture);
5548 mono_method_desc_free (desc);
5551 if (name->culture) {
5552 args [0] = mono_string_new (domain, name->culture);
5553 args [1] = &assembly_ref;
5555 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5556 return_if_nok (error);
5558 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5561 if (name->public_key) {
5562 pkey_ptr = (char*)name->public_key;
5563 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5565 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5566 return_if_nok (error);
5567 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5568 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5569 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5570 } else if (default_publickey) {
5571 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5572 return_if_nok (error);
5573 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5574 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5577 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5578 if (name->public_key_token [0]) {
5582 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5583 return_if_nok (error);
5585 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5586 p = mono_array_addr (keyToken, char, 0);
5588 for (i = 0, j = 0; i < 8; i++) {
5589 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5590 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5593 } else if (default_token) {
5594 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5595 return_if_nok (error);
5596 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5600 ICALL_EXPORT MonoString *
5601 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5603 MonoDomain *domain = mono_object_domain (assembly);
5604 MonoAssembly *mass = assembly->assembly;
5608 name = mono_stringify_assembly_name (&mass->aname);
5609 res = mono_string_new (domain, name);
5616 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5620 MonoAssembly *mass = assembly->assembly;
5622 if (g_path_is_absolute (mass->image->name)) {
5623 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5624 mono_error_set_pending_exception (&error);
5627 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5629 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5630 mono_error_set_pending_exception (&error);
5636 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5640 MonoImageOpenStatus status = MONO_IMAGE_OK;
5643 MonoAssemblyName name;
5646 filename = mono_string_to_utf8 (fname);
5648 dirname = g_path_get_dirname (filename);
5649 replace_shadow_path (mono_domain_get (), dirname, &filename);
5652 image = mono_image_open (filename, &status);
5658 if (status == MONO_IMAGE_IMAGE_INVALID)
5659 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5661 exc = mono_get_exception_file_not_found2 (NULL, fname);
5662 mono_set_pending_exception (exc);
5666 res = mono_assembly_fill_assembly_name (image, &name);
5668 mono_image_close (image);
5670 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5674 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5675 mono_error_set_pending_exception (&error);
5677 mono_image_close (image);
5681 ICALL_EXPORT MonoBoolean
5682 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5683 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5685 MonoBoolean result = FALSE;
5686 MonoDeclSecurityEntry entry;
5688 /* SecurityAction.RequestMinimum */
5689 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5690 *minimum = entry.blob;
5691 *minLength = entry.size;
5694 /* SecurityAction.RequestOptional */
5695 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5696 *optional = entry.blob;
5697 *optLength = entry.size;
5700 /* SecurityAction.RequestRefuse */
5701 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5702 *refused = entry.blob;
5703 *refLength = entry.size;
5711 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5713 guint32 attrs, visibility;
5715 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5716 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5717 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5720 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5726 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5728 MonoReflectionType *rt;
5731 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5734 mono_error_init (error);
5736 /* we start the count from 1 because we skip the special type <Module> */
5739 for (i = 1; i < tdef->rows; ++i) {
5740 if (mono_module_type_is_visible (tdef, image, i + 1))
5744 count = tdef->rows - 1;
5746 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5747 return_val_if_nok (error, NULL);
5748 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5749 return_val_if_nok (error, NULL);
5751 for (i = 1; i < tdef->rows; ++i) {
5752 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5753 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5756 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5757 return_val_if_nok (error, NULL);
5759 mono_array_setref (res, count, rt);
5761 MonoException *ex = mono_error_convert_to_exception (error);
5762 mono_array_setref (*exceptions, count, ex);
5771 ICALL_EXPORT MonoArray*
5772 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5775 MonoArray *res = NULL;
5776 MonoArray *exceptions = NULL;
5777 MonoImage *image = NULL;
5778 MonoTableInfo *table = NULL;
5781 int i, len, ex_count;
5783 domain = mono_object_domain (assembly);
5785 g_assert (!assembly_is_dynamic (assembly->assembly));
5786 image = assembly->assembly->image;
5787 table = &image->tables [MONO_TABLE_FILE];
5788 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5789 if (mono_error_set_pending_exception (&error))
5792 /* Append data from all modules in the assembly */
5793 for (i = 0; i < table->rows; ++i) {
5794 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5795 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5800 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5801 if (mono_error_set_pending_exception (&error))
5805 /* Append the new types to the end of the array */
5806 if (mono_array_length (res2) > 0) {
5808 MonoArray *res3, *ex3;
5810 len1 = mono_array_length (res);
5811 len2 = mono_array_length (res2);
5813 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5814 if (mono_error_set_pending_exception (&error))
5816 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5817 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5820 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5821 if (mono_error_set_pending_exception (&error))
5823 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5824 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5831 /* the ReflectionTypeLoadException must have all the types (Types property),
5832 * NULL replacing types which throws an exception. The LoaderException must
5833 * contain all exceptions for NULL items.
5836 len = mono_array_length (res);
5839 for (i = 0; i < len; i++) {
5840 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5844 klass = mono_type_get_class (t->type);
5845 if ((klass != NULL) && mono_class_has_failure (klass)) {
5846 /* keep the class in the list */
5847 list = g_list_append (list, klass);
5848 /* and replace Type with NULL */
5849 mono_array_setref (res, i, NULL);
5856 if (list || ex_count) {
5858 MonoException *exc = NULL;
5859 MonoArray *exl = NULL;
5860 int j, length = g_list_length (list) + ex_count;
5862 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5863 if (mono_error_set_pending_exception (&error)) {
5867 /* Types for which mono_class_get_checked () succeeded */
5868 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5869 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5870 mono_array_setref (exl, i, exc);
5872 /* Types for which it don't */
5873 for (j = 0; j < mono_array_length (exceptions); ++j) {
5874 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5876 g_assert (i < length);
5877 mono_array_setref (exl, i, exc);
5884 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5885 if (!is_ok (&error)) {
5886 mono_error_set_pending_exception (&error);
5889 mono_set_pending_exception (exc);
5896 ICALL_EXPORT gboolean
5897 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5900 MonoAssemblyName aname;
5901 MonoDomain *domain = mono_object_domain (name);
5903 gboolean is_version_defined;
5904 gboolean is_token_defined;
5906 aname.public_key = NULL;
5907 val = mono_string_to_utf8 (assname);
5908 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5909 g_free ((guint8*) aname.public_key);
5914 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5915 mono_error_set_pending_exception (&error);
5917 mono_assembly_name_free (&aname);
5918 g_free ((guint8*) aname.public_key);
5924 ICALL_EXPORT MonoReflectionType*
5925 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5928 MonoReflectionType *ret;
5929 MonoDomain *domain = mono_object_domain (module);
5932 g_assert (module->image);
5934 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5935 /* These images do not have a global type */
5938 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5939 if (!mono_error_ok (&error)) {
5940 mono_error_set_pending_exception (&error);
5944 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5945 if (!mono_error_ok (&error)) {
5946 mono_error_set_pending_exception (&error);
5954 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5956 /*if (module->image)
5957 mono_image_close (module->image);*/
5960 ICALL_EXPORT MonoString*
5961 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5963 MonoDomain *domain = mono_object_domain (module);
5965 g_assert (module->image);
5966 return mono_string_new (domain, module->image->guid);
5969 ICALL_EXPORT gpointer
5970 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5973 if (module->image && module->image->is_module_handle)
5974 return module->image->raw_data;
5977 return (gpointer) (-1);
5981 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5983 if (image_is_dynamic (image)) {
5984 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5985 *pe_kind = dyn->pe_kind;
5986 *machine = dyn->machine;
5989 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5990 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5995 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5997 return (image->md_version_major << 16) | (image->md_version_minor);
6000 ICALL_EXPORT MonoArray*
6001 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
6004 MonoArray *exceptions;
6007 if (!module->image) {
6008 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
6009 mono_error_set_pending_exception (&error);
6014 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
6015 if (mono_error_set_pending_exception (&error))
6018 for (i = 0; i < mono_array_length (exceptions); ++i) {
6019 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
6021 mono_set_pending_exception (ex);
6030 mono_memberref_is_method (MonoImage *image, guint32 token)
6032 if (!image_is_dynamic (image)) {
6033 guint32 cols [MONO_MEMBERREF_SIZE];
6035 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
6036 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
6037 mono_metadata_decode_blob_size (sig, &sig);
6038 return (*sig != 0x6);
6041 MonoClass *handle_class;
6043 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
6044 mono_error_cleanup (&error); /* just probing, ignore error */
6048 return mono_defaults.methodhandle_class == handle_class;
6053 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
6056 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
6057 mono_array_addr (type_args, MonoType*, 0));
6059 context->class_inst = NULL;
6061 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
6062 mono_array_addr (method_args, MonoType*, 0));
6064 context->method_inst = NULL;
6067 ICALL_EXPORT MonoType*
6068 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6071 int table = mono_metadata_token_table (token);
6072 int index = mono_metadata_token_index (token);
6073 MonoGenericContext context;
6076 *resolve_error = ResolveTokenError_Other;
6078 /* Validate token */
6079 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
6080 (table != MONO_TABLE_TYPESPEC)) {
6081 *resolve_error = ResolveTokenError_BadTable;
6085 if (image_is_dynamic (image)) {
6086 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
6087 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6088 mono_error_cleanup (&error);
6089 return klass ? &klass->byval_arg : NULL;
6092 init_generic_context_from_args (&context, type_args, method_args);
6093 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6094 mono_error_cleanup (&error);
6095 return klass ? &klass->byval_arg : NULL;
6098 if ((index <= 0) || (index > image->tables [table].rows)) {
6099 *resolve_error = ResolveTokenError_OutOfRange;
6103 init_generic_context_from_args (&context, type_args, method_args);
6104 klass = mono_class_get_checked (image, token, &error);
6106 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
6107 if (!mono_error_ok (&error)) {
6108 mono_error_set_pending_exception (&error);
6113 return &klass->byval_arg;
6118 ICALL_EXPORT MonoMethod*
6119 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6122 int table = mono_metadata_token_table (token);
6123 int index = mono_metadata_token_index (token);
6124 MonoGenericContext context;
6127 *resolve_error = ResolveTokenError_Other;
6129 /* Validate token */
6130 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
6131 (table != MONO_TABLE_MEMBERREF)) {
6132 *resolve_error = ResolveTokenError_BadTable;
6136 if (image_is_dynamic (image)) {
6137 if (table == MONO_TABLE_METHOD) {
6138 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6139 mono_error_cleanup (&error);
6143 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
6144 *resolve_error = ResolveTokenError_BadTable;
6148 init_generic_context_from_args (&context, type_args, method_args);
6149 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6150 mono_error_cleanup (&error);
6154 if ((index <= 0) || (index > image->tables [table].rows)) {
6155 *resolve_error = ResolveTokenError_OutOfRange;
6158 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6159 *resolve_error = ResolveTokenError_BadTable;
6163 init_generic_context_from_args (&context, type_args, method_args);
6164 method = mono_get_method_checked (image, token, NULL, &context, &error);
6165 mono_error_set_pending_exception (&error);
6170 ICALL_EXPORT MonoString*
6171 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6174 int index = mono_metadata_token_index (token);
6176 *resolve_error = ResolveTokenError_Other;
6178 /* Validate token */
6179 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6180 *resolve_error = ResolveTokenError_BadTable;
6184 if (image_is_dynamic (image)) {
6185 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6186 mono_error_cleanup (&error);
6190 if ((index <= 0) || (index >= image->heap_us.size)) {
6191 *resolve_error = ResolveTokenError_OutOfRange;
6195 /* FIXME: What to do if the index points into the middle of a string ? */
6197 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
6198 mono_error_set_pending_exception (&error);
6202 ICALL_EXPORT MonoClassField*
6203 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6207 int table = mono_metadata_token_table (token);
6208 int index = mono_metadata_token_index (token);
6209 MonoGenericContext context;
6210 MonoClassField *field;
6212 *resolve_error = ResolveTokenError_Other;
6214 /* Validate token */
6215 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6216 *resolve_error = ResolveTokenError_BadTable;
6220 if (image_is_dynamic (image)) {
6221 if (table == MONO_TABLE_FIELD) {
6222 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6223 mono_error_cleanup (&error);
6227 if (mono_memberref_is_method (image, token)) {
6228 *resolve_error = ResolveTokenError_BadTable;
6232 init_generic_context_from_args (&context, type_args, method_args);
6233 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6234 mono_error_cleanup (&error);
6238 if ((index <= 0) || (index > image->tables [table].rows)) {
6239 *resolve_error = ResolveTokenError_OutOfRange;
6242 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6243 *resolve_error = ResolveTokenError_BadTable;
6247 init_generic_context_from_args (&context, type_args, method_args);
6248 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6249 mono_error_set_pending_exception (&error);
6255 ICALL_EXPORT MonoObject*
6256 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6260 int table = mono_metadata_token_table (token);
6262 *error = ResolveTokenError_Other;
6265 case MONO_TABLE_TYPEDEF:
6266 case MONO_TABLE_TYPEREF:
6267 case MONO_TABLE_TYPESPEC: {
6268 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6270 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6271 mono_error_set_pending_exception (&merror);
6278 case MONO_TABLE_METHOD:
6279 case MONO_TABLE_METHODSPEC: {
6280 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6282 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6283 mono_error_set_pending_exception (&merror);
6289 case MONO_TABLE_FIELD: {
6290 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6292 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6293 mono_error_set_pending_exception (&merror);
6299 case MONO_TABLE_MEMBERREF:
6300 if (mono_memberref_is_method (image, token)) {
6301 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6303 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6304 mono_error_set_pending_exception (&merror);
6311 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6313 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6314 mono_error_set_pending_exception (&merror);
6323 *error = ResolveTokenError_BadTable;
6329 ICALL_EXPORT MonoArray*
6330 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6333 int table = mono_metadata_token_table (token);
6334 int idx = mono_metadata_token_index (token);
6335 MonoTableInfo *tables = image->tables;
6340 *resolve_error = ResolveTokenError_OutOfRange;
6342 /* FIXME: Support other tables ? */
6343 if (table != MONO_TABLE_STANDALONESIG)
6346 if (image_is_dynamic (image))
6349 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6352 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6354 ptr = mono_metadata_blob_heap (image, sig);
6355 len = mono_metadata_decode_blob_size (ptr, &ptr);
6357 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6358 if (mono_error_set_pending_exception (&error))
6360 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6364 ICALL_EXPORT MonoReflectionType*
6365 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6368 MonoReflectionType *ret;
6370 int isbyref = 0, rank;
6371 char *str = mono_string_to_utf8 (smodifiers);
6374 klass = mono_class_from_mono_type (tb->type.type);
6376 /* logic taken from mono_reflection_parse_type(): keep in sync */
6380 if (isbyref) { /* only one level allowed by the spec */
6389 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6390 mono_error_set_pending_exception (&error);
6394 klass = mono_ptr_class_get (&klass->byval_arg);
6395 mono_class_init (klass);
6406 else if (*p != '*') { /* '*' means unknown lower bound */
6417 klass = mono_array_class_get (klass, rank);
6418 mono_class_init (klass);
6427 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6428 mono_error_set_pending_exception (&error);
6433 ICALL_EXPORT MonoBoolean
6434 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6440 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6446 check_for_invalid_type (MonoClass *klass, MonoError *error)
6451 mono_error_init (error);
6453 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6456 name = mono_type_get_full_name (klass);
6457 str = mono_string_new (mono_domain_get (), name);
6459 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6462 ICALL_EXPORT MonoReflectionType *
6463 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6466 MonoReflectionType *ret;
6467 MonoClass *klass, *aklass;
6469 klass = mono_class_from_mono_type (type->type);
6470 check_for_invalid_type (klass, &error);
6471 mono_error_set_pending_exception (&error);
6473 if (rank == 0) //single dimentional array
6474 aklass = mono_array_class_get (klass, 1);
6476 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6478 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6479 mono_error_set_pending_exception (&error);
6484 ICALL_EXPORT MonoReflectionType *
6485 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6488 MonoReflectionType *ret;
6491 klass = mono_class_from_mono_type (type->type);
6492 mono_class_init_checked (klass, &error);
6493 if (mono_error_set_pending_exception (&error))
6496 check_for_invalid_type (klass, &error);
6497 if (mono_error_set_pending_exception (&error))
6500 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6501 mono_error_set_pending_exception (&error);
6506 ICALL_EXPORT MonoReflectionType *
6507 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6510 MonoReflectionType *ret;
6511 MonoClass *klass, *pklass;
6513 klass = mono_class_from_mono_type (type->type);
6514 mono_class_init_checked (klass, &error);
6515 if (mono_error_set_pending_exception (&error))
6517 check_for_invalid_type (klass, &error);
6518 if (mono_error_set_pending_exception (&error))
6521 pklass = mono_ptr_class_get (type->type);
6523 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6524 mono_error_set_pending_exception (&error);
6529 ICALL_EXPORT MonoObject *
6530 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6531 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6534 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6535 MonoObject *delegate;
6537 MonoMethod *method = info->method;
6539 mono_class_init_checked (delegate_class, &error);
6540 if (mono_error_set_pending_exception (&error))
6543 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6544 /* FIXME improve this exception message */
6545 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6547 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6548 mono_error_set_pending_exception (&error);
6552 if (mono_security_core_clr_enabled ()) {
6553 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6554 if (throwOnBindFailure)
6555 mono_error_set_pending_exception (&error);
6557 mono_error_cleanup (&error);
6562 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6563 if (mono_error_set_pending_exception (&error))
6566 if (method_is_dynamic (method)) {
6567 /* Creating a trampoline would leak memory */
6568 func = mono_compile_method_checked (method, &error);
6569 if (mono_error_set_pending_exception (&error))
6572 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6573 method = mono_object_get_virtual_method (target, method);
6574 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6575 if (mono_error_set_pending_exception (&error))
6577 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6580 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6581 if (mono_error_set_pending_exception (&error))
6586 ICALL_EXPORT MonoMulticastDelegate *
6587 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6590 MonoMulticastDelegate *ret;
6592 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6594 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6595 if (mono_error_set_pending_exception (&error))
6598 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6603 ICALL_EXPORT MonoReflectionMethod*
6604 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6606 MonoReflectionMethod *ret = NULL;
6608 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6609 mono_error_set_pending_exception (&error);
6615 static inline gint32
6616 mono_array_get_byte_length (MonoArray *array)
6622 klass = array->obj.vtable->klass;
6624 if (array->bounds == NULL)
6625 length = array->max_length;
6628 for (i = 0; i < klass->rank; ++ i)
6629 length *= array->bounds [i].length;
6632 switch (klass->element_class->byval_arg.type) {
6635 case MONO_TYPE_BOOLEAN:
6639 case MONO_TYPE_CHAR:
6647 return length * sizeof (gpointer);
6658 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6660 return mono_array_get_byte_length (array);
6664 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6666 return mono_array_get (array, gint8, idx);
6670 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6672 mono_array_set (array, gint8, idx, value);
6675 ICALL_EXPORT MonoBoolean
6676 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6678 guint8 *src_buf, *dest_buf;
6681 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6685 g_assert (count >= 0);
6687 /* This is called directly from the class libraries without going through the managed wrapper */
6688 MONO_CHECK_ARG_NULL (src, FALSE);
6689 MONO_CHECK_ARG_NULL (dest, FALSE);
6691 /* watch out for integer overflow */
6692 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6695 src_buf = (guint8 *)src->vector + src_offset;
6696 dest_buf = (guint8 *)dest->vector + dest_offset;
6699 memcpy (dest_buf, src_buf, count);
6701 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6706 #ifndef DISABLE_REMOTING
6707 ICALL_EXPORT MonoObject *
6708 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6711 MonoDomain *domain = mono_object_domain (this_obj);
6713 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6714 MonoTransparentProxy *tp;
6718 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6719 if (mono_error_set_pending_exception (&error))
6722 tp = (MonoTransparentProxy*) res;
6724 MONO_OBJECT_SETREF (tp, rp, rp);
6725 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6726 klass = mono_class_from_mono_type (type);
6728 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6729 mono_class_setup_vtable (klass);
6730 if (mono_class_has_failure (klass)) {
6731 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6735 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6736 if (mono_error_set_pending_exception (&error))
6738 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6739 if (mono_error_set_pending_exception (&error))
6742 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6743 if (mono_error_set_pending_exception (&error))
6748 ICALL_EXPORT MonoReflectionType *
6749 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6752 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6753 mono_error_set_pending_exception (&error);
6759 /* System.Environment */
6762 ves_icall_System_Environment_get_UserName (void)
6764 /* using glib is more portable */
6765 return mono_string_new (mono_domain_get (), g_get_user_name ());
6769 ICALL_EXPORT MonoString *
6770 ves_icall_System_Environment_get_MachineName (void)
6772 #if defined (HOST_WIN32)
6777 len = MAX_COMPUTERNAME_LENGTH + 1;
6778 buf = g_new (gunichar2, len);
6781 if (GetComputerName (buf, (PDWORD) &len)) {
6783 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6784 mono_error_set_pending_exception (&error);
6789 #elif !defined(DISABLE_SOCKETS)
6793 #if defined _SC_HOST_NAME_MAX
6794 n = sysconf (_SC_HOST_NAME_MAX);
6798 buf = g_malloc (n+1);
6800 if (gethostname (buf, n) == 0){
6802 result = mono_string_new (mono_domain_get (), buf);
6809 return mono_string_new (mono_domain_get (), "mono");
6814 ves_icall_System_Environment_get_Platform (void)
6816 #if defined (TARGET_WIN32)
6819 #elif defined(__MACH__)
6822 // Notice that the value is hidden from user code, and only exposed
6823 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6824 // define and making assumptions based on Unix/128/4 values before there
6825 // was a MacOS define. Lots of code would assume that not-Unix meant
6826 // Windows, but in this case, it would be OSX.
6835 ICALL_EXPORT MonoString *
6836 ves_icall_System_Environment_get_NewLine (void)
6838 #if defined (HOST_WIN32)
6839 return mono_string_new (mono_domain_get (), "\r\n");
6841 return mono_string_new (mono_domain_get (), "\n");
6845 ICALL_EXPORT MonoBoolean
6846 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6848 #if SIZEOF_VOID_P == 8
6852 gboolean isWow64Process = FALSE;
6853 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6854 return (MonoBoolean)isWow64Process;
6856 #elif defined(HAVE_SYS_UTSNAME_H)
6857 struct utsname name;
6859 if (uname (&name) >= 0) {
6860 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6867 ICALL_EXPORT MonoString *
6868 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6876 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6877 value = g_getenv (utf8_name);
6884 return mono_string_new (mono_domain_get (), value);
6888 * There is no standard way to get at environ.
6891 #ifndef __MINGW32_VERSION
6892 #if defined(__APPLE__)
6893 #if defined (TARGET_OSX)
6894 /* Apple defines this in crt_externs.h but doesn't provide that header for
6895 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6896 * in fact exist on all implementations (so far)
6898 gchar ***_NSGetEnviron(void);
6899 #define environ (*_NSGetEnviron())
6901 static char *mono_environ[1] = { NULL };
6902 #define environ mono_environ
6903 #endif /* defined (TARGET_OSX) */
6911 ICALL_EXPORT MonoArray *
6912 ves_icall_System_Environment_GetCoomandLineArgs (void)
6915 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6916 mono_error_set_pending_exception (&error);
6920 ICALL_EXPORT MonoArray *
6921 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6933 env_strings = GetEnvironmentStrings();
6936 env_string = env_strings;
6937 while (*env_string != '\0') {
6938 /* weird case that MS seems to skip */
6939 if (*env_string != '=')
6941 while (*env_string != '\0')
6947 domain = mono_domain_get ();
6948 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6949 if (mono_error_set_pending_exception (&error))
6954 env_string = env_strings;
6955 while (*env_string != '\0') {
6956 /* weird case that MS seems to skip */
6957 if (*env_string != '=') {
6958 equal_str = wcschr(env_string, '=');
6959 g_assert(equal_str);
6961 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6962 if (mono_error_set_pending_exception (&error))
6965 mono_array_setref (names, n, str);
6968 while (*env_string != '\0')
6973 FreeEnvironmentStrings (env_strings);
6987 for (e = environ; *e != 0; ++ e)
6990 domain = mono_domain_get ();
6991 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6992 if (mono_error_set_pending_exception (&error))
6996 for (e = environ; *e != 0; ++ e) {
6997 parts = g_strsplit (*e, "=", 2);
6999 str = mono_string_new (domain, *parts);
7000 mono_array_setref (names, n, str);
7013 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
7016 gunichar2 *utf16_name, *utf16_value;
7018 gchar *utf8_name, *utf8_value;
7023 utf16_name = mono_string_to_utf16 (name);
7024 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7025 SetEnvironmentVariable (utf16_name, NULL);
7026 g_free (utf16_name);
7030 utf16_value = mono_string_to_utf16 (value);
7032 SetEnvironmentVariable (utf16_name, utf16_value);
7034 g_free (utf16_name);
7035 g_free (utf16_value);
7037 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
7039 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7040 g_unsetenv (utf8_name);
7045 utf8_value = mono_string_to_utf8_checked (value, &error);
7046 if (!mono_error_ok (&error)) {
7048 mono_error_set_pending_exception (&error);
7051 g_setenv (utf8_name, utf8_value, TRUE);
7054 g_free (utf8_value);
7059 ves_icall_System_Environment_Exit (int result)
7061 mono_environment_exitcode_set (result);
7063 /* FIXME: There are some cleanup hangs that should be worked out, but
7064 * if the program is going to exit, everything will be cleaned up when
7065 * NaCl exits anyway.
7067 #ifndef __native_client__
7068 if (!mono_runtime_try_shutdown ())
7069 mono_thread_exit ();
7071 /* Suspend all managed threads since the runtime is going away */
7072 mono_thread_suspend_all_other_threads ();
7074 mono_runtime_quit ();
7077 /* we may need to do some cleanup here... */
7081 ICALL_EXPORT MonoString*
7082 ves_icall_System_Environment_GetGacPath (void)
7084 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
7087 ICALL_EXPORT MonoString*
7088 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
7090 #if defined (HOST_WIN32)
7091 #ifndef CSIDL_FLAG_CREATE
7092 #define CSIDL_FLAG_CREATE 0x8000
7095 WCHAR path [MAX_PATH];
7096 /* Create directory if no existing */
7097 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
7102 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
7103 mono_error_set_pending_exception (&error);
7107 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7109 return mono_string_new (mono_domain_get (), "");
7112 ICALL_EXPORT MonoArray *
7113 ves_icall_System_Environment_GetLogicalDrives (void)
7116 gunichar2 buf [256], *ptr, *dname;
7118 guint initial_size = 127, size = 128;
7121 MonoString *drivestr;
7122 MonoDomain *domain = mono_domain_get ();
7128 while (size > initial_size) {
7129 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
7130 if (size > initial_size) {
7133 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7134 initial_size = size;
7148 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7149 if (mono_error_set_pending_exception (&error))
7156 while (*u16) { u16++; len ++; }
7157 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7158 if (mono_error_set_pending_exception (&error))
7161 mono_array_setref (result, ndrives++, drivestr);
7172 ICALL_EXPORT MonoString *
7173 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7176 gunichar2 volume_name [MAX_PATH + 1];
7178 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7180 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
7181 mono_error_set_pending_exception (&error);
7185 ICALL_EXPORT MonoString *
7186 ves_icall_System_Environment_InternalGetHome (void)
7188 return mono_string_new (mono_domain_get (), g_get_home_dir ());
7191 static const char *encodings [] = {
7193 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7194 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7195 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7197 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7198 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7199 "x_unicode_2_0_utf_7",
7201 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7202 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7204 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7207 "unicodefffe", "utf_16be",
7214 * Returns the internal codepage, if the value of "int_code_page" is
7215 * 1 at entry, and we can not compute a suitable code page number,
7216 * returns the code page as a string
7218 ICALL_EXPORT MonoString*
7219 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
7224 char *codepage = NULL;
7226 int want_name = *int_code_page;
7229 *int_code_page = -1;
7231 g_get_charset (&cset);
7232 c = codepage = strdup (cset);
7233 for (c = codepage; *c; c++){
7234 if (isascii (*c) && isalpha (*c))
7239 /* g_print ("charset: %s\n", cset); */
7241 /* handle some common aliases */
7244 for (i = 0; p != 0; ){
7247 p = encodings [++i];
7250 if (strcmp (p, codepage) == 0){
7251 *int_code_page = code;
7254 p = encodings [++i];
7257 if (strstr (codepage, "utf_8") != NULL)
7258 *int_code_page |= 0x10000000;
7261 if (want_name && *int_code_page == -1)
7262 return mono_string_new (mono_domain_get (), cset);
7267 ICALL_EXPORT MonoBoolean
7268 ves_icall_System_Environment_get_HasShutdownStarted (void)
7270 if (mono_runtime_is_shutting_down ())
7273 if (mono_domain_is_unloading (mono_domain_get ()))
7280 ves_icall_System_Environment_BroadcastSettingChange (void)
7283 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7289 ves_icall_System_Environment_get_TickCount (void)
7291 /* this will overflow after ~24 days */
7292 return (gint32) (mono_msec_boottime () & 0xffffffff);
7296 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7302 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
7303 MonoReflectionMethod *method,
7304 MonoArray *out_args)
7307 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args, &error);
7308 mono_error_set_pending_exception (&error);
7311 #ifndef DISABLE_REMOTING
7312 ICALL_EXPORT MonoBoolean
7313 ves_icall_IsTransparentProxy (MonoObject *proxy)
7318 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7324 ICALL_EXPORT MonoReflectionMethod *
7325 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7326 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7328 MonoReflectionMethod *ret = NULL;
7333 MonoMethod **vtable;
7334 MonoMethod *res = NULL;
7336 MONO_CHECK_ARG_NULL (rtype, NULL);
7337 MONO_CHECK_ARG_NULL (rmethod, NULL);
7339 method = rmethod->method;
7340 klass = mono_class_from_mono_type (rtype->type);
7341 mono_class_init_checked (klass, &error);
7342 if (mono_error_set_pending_exception (&error))
7345 if (MONO_CLASS_IS_INTERFACE (klass))
7348 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7351 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7352 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7358 mono_class_setup_vtable (klass);
7359 vtable = klass->vtable;
7361 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7362 gboolean variance_used = FALSE;
7363 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7364 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7366 res = vtable [offs + method->slot];
7368 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7371 if (method->slot != -1)
7372 res = vtable [method->slot];
7378 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7379 mono_error_set_pending_exception (&error);
7384 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7390 klass = mono_class_from_mono_type (type->type);
7391 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7392 if (!is_ok (&error)) {
7393 mono_error_set_pending_exception (&error);
7397 mono_vtable_set_is_remote (vtable, enable);
7400 #else /* DISABLE_REMOTING */
7403 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7405 g_assert_not_reached ();
7410 ICALL_EXPORT MonoObject *
7411 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7418 domain = mono_object_domain (type);
7419 klass = mono_class_from_mono_type (type->type);
7420 mono_class_init_checked (klass, &error);
7421 if (mono_error_set_pending_exception (&error))
7424 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7425 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7429 if (klass->rank >= 1) {
7430 g_assert (klass->rank == 1);
7431 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7432 mono_error_set_pending_exception (&error);
7435 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7436 if (!is_ok (&error)) {
7437 mono_error_set_pending_exception (&error);
7440 /* Bypass remoting object creation check */
7441 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7442 mono_error_set_pending_exception (&error);
7448 ICALL_EXPORT MonoString *
7449 ves_icall_System_IO_get_temp_path (void)
7451 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7454 #ifndef PLATFORM_NO_DRIVEINFO
7455 ICALL_EXPORT MonoBoolean
7456 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7457 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7461 ULARGE_INTEGER wapi_free_bytes_avail;
7462 ULARGE_INTEGER wapi_total_number_of_bytes;
7463 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7465 *error = ERROR_SUCCESS;
7466 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7467 &wapi_total_number_of_free_bytes);
7470 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7471 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7472 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7474 *free_bytes_avail = 0;
7475 *total_number_of_bytes = 0;
7476 *total_number_of_free_bytes = 0;
7477 *error = GetLastError ();
7483 ICALL_EXPORT guint32
7484 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7486 return GetDriveType (mono_string_chars (root_path_name));
7490 ICALL_EXPORT gpointer
7491 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7494 gpointer result = mono_compile_method_checked (method, &error);
7495 mono_error_set_pending_exception (&error);
7499 ICALL_EXPORT MonoString *
7500 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7505 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7507 #if defined (HOST_WIN32)
7508 /* Avoid mixing '/' and '\\' */
7511 for (i = strlen (path) - 1; i >= 0; i--)
7512 if (path [i] == '/')
7516 mcpath = mono_string_new (mono_domain_get (), path);
7523 get_bundled_app_config (void)
7525 const gchar *app_config;
7528 gchar *config_file_name, *config_file_path;
7529 gsize len, config_file_path_length, config_ext_length;
7532 domain = mono_domain_get ();
7533 file = domain->setup->configuration_file;
7534 if (!file || file->length == 0)
7537 // Retrieve config file and remove the extension
7538 config_file_name = mono_string_to_utf8 (file);
7539 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7540 if (!config_file_path)
7541 config_file_path = config_file_name;
7543 config_file_path_length = strlen (config_file_path);
7544 config_ext_length = strlen (".config");
7545 if (config_file_path_length <= config_ext_length)
7548 len = config_file_path_length - config_ext_length;
7549 module = (gchar *)g_malloc0 (len + 1);
7550 memcpy (module, config_file_path, len);
7551 // Get the config file from the module name
7552 app_config = mono_config_string_for_assembly_file (module);
7555 if (config_file_name != config_file_path)
7556 g_free (config_file_name);
7557 g_free (config_file_path);
7562 return mono_string_new (mono_domain_get (), app_config);
7566 get_bundled_machine_config (void)
7568 const gchar *machine_config;
7570 machine_config = mono_get_machine_config ();
7572 if (!machine_config)
7575 return mono_string_new (mono_domain_get (), machine_config);
7578 ICALL_EXPORT MonoString *
7579 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7584 path = g_path_get_dirname (mono_get_config_dir ());
7586 #if defined (HOST_WIN32)
7587 /* Avoid mixing '/' and '\\' */
7590 for (i = strlen (path) - 1; i >= 0; i--)
7591 if (path [i] == '/')
7595 ipath = mono_string_new (mono_domain_get (), path);
7601 ICALL_EXPORT gboolean
7602 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7604 MonoPEResourceDataEntry *entry;
7607 if (!assembly || !result || !size)
7612 image = assembly->assembly->image;
7613 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7617 *result = mono_image_rva_map (image, entry->rde_data_offset);
7622 *size = entry->rde_size;
7627 ICALL_EXPORT MonoBoolean
7628 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7630 return mono_is_debugger_attached ();
7633 ICALL_EXPORT MonoBoolean
7634 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7636 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7637 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7643 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7645 if (mono_get_runtime_callbacks ()->debug_log)
7646 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7650 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7652 #if defined (HOST_WIN32)
7653 OutputDebugString (mono_string_chars (message));
7655 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7659 /* Only used for value types */
7660 ICALL_EXPORT MonoObject *
7661 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7668 domain = mono_object_domain (type);
7669 klass = mono_class_from_mono_type (type->type);
7670 mono_class_init_checked (klass, &error);
7671 if (mono_error_set_pending_exception (&error))
7674 if (mono_class_is_nullable (klass))
7675 /* No arguments -> null */
7678 result = mono_object_new_checked (domain, klass, &error);
7679 mono_error_set_pending_exception (&error);
7683 ICALL_EXPORT MonoReflectionMethod *
7684 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7686 MonoReflectionMethod *ret = NULL;
7689 MonoClass *klass, *parent;
7690 MonoGenericContext *generic_inst = NULL;
7691 MonoMethod *method = m->method;
7692 MonoMethod *result = NULL;
7695 if (method->klass == NULL)
7698 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7699 MONO_CLASS_IS_INTERFACE (method->klass) ||
7700 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7703 slot = mono_method_get_vtable_slot (method);
7707 klass = method->klass;
7708 if (klass->generic_class) {
7709 generic_inst = mono_class_get_context (klass);
7710 klass = klass->generic_class->container_class;
7714 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7715 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7716 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7717 or klass is the generic container class and generic_inst is the instantiation.
7719 when we go to the parent, if the parent is an open constructed type, we need to
7720 replace the type parameters by the definitions from the generic_inst, and then take it
7721 apart again into the klass and the generic_inst.
7723 For cases like this:
7724 class C<T> : B<T, int> {
7725 public override void Foo () { ... }
7727 class B<U,V> : A<HashMap<U,V>> {
7728 public override void Foo () { ... }
7731 public virtual void Foo () { ... }
7734 if at each iteration the parent isn't open, we can skip inflating it. if at some
7735 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7738 MonoGenericContext *parent_inst = NULL;
7739 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7740 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7741 if (!mono_error_ok (&error)) {
7742 mono_error_set_pending_exception (&error);
7746 if (parent->generic_class) {
7747 parent_inst = mono_class_get_context (parent);
7748 parent = parent->generic_class->container_class;
7751 mono_class_setup_vtable (parent);
7752 if (parent->vtable_size <= slot)
7755 generic_inst = parent_inst;
7758 klass = klass->parent;
7761 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7762 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7763 if (!mono_error_ok (&error)) {
7764 mono_error_set_pending_exception (&error);
7768 generic_inst = NULL;
7770 if (klass->generic_class) {
7771 generic_inst = mono_class_get_context (klass);
7772 klass = klass->generic_class->container_class;
7778 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7779 if (!mono_error_ok (&error)) {
7780 mono_error_set_pending_exception (&error);
7785 if (klass == method->klass)
7788 /*This is possible if definition == FALSE.
7789 * Do it here to be really sure we don't read invalid memory.
7791 if (slot >= klass->vtable_size)
7794 mono_class_setup_vtable (klass);
7796 result = klass->vtable [slot];
7797 if (result == NULL) {
7798 /* It is an abstract method */
7799 gpointer iter = NULL;
7800 while ((result = mono_class_get_methods (klass, &iter)))
7801 if (result->slot == slot)
7808 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7809 mono_error_set_pending_exception (&error);
7813 ICALL_EXPORT MonoString*
7814 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7816 MonoMethod *method = m->method;
7818 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7823 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7825 iter->sig = *(MonoMethodSignature**)argsp;
7827 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7828 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7831 /* FIXME: it's not documented what start is exactly... */
7835 iter->args = argsp + sizeof (gpointer);
7837 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7839 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7842 ICALL_EXPORT MonoTypedRef
7843 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7845 guint32 i, arg_size;
7849 i = iter->sig->sentinelpos + iter->next_arg;
7851 g_assert (i < iter->sig->param_count);
7853 res.type = iter->sig->params [i];
7854 res.klass = mono_class_from_mono_type (res.type);
7855 arg_size = mono_type_stack_size (res.type, &align);
7856 #if defined(__arm__) || defined(__mips__)
7857 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7859 res.value = iter->args;
7860 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7861 /* Values are stored as 8 byte register sized objects, but 'value'
7862 * is dereferenced as a pointer in other routines.
7864 res.value = (char*)res.value + 4;
7866 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7867 if (arg_size <= sizeof (gpointer)) {
7869 int padding = arg_size - mono_type_size (res.type, &dummy);
7870 res.value = (guint8*)res.value + padding;
7873 iter->args = (char*)iter->args + arg_size;
7876 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7881 ICALL_EXPORT MonoTypedRef
7882 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7884 guint32 i, arg_size;
7888 i = iter->sig->sentinelpos + iter->next_arg;
7890 g_assert (i < iter->sig->param_count);
7892 while (i < iter->sig->param_count) {
7893 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7895 res.type = iter->sig->params [i];
7896 res.klass = mono_class_from_mono_type (res.type);
7897 /* FIXME: endianess issue... */
7898 arg_size = mono_type_stack_size (res.type, &align);
7899 #if defined(__arm__) || defined(__mips__)
7900 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7902 res.value = iter->args;
7903 iter->args = (char*)iter->args + arg_size;
7905 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7908 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7916 ICALL_EXPORT MonoType*
7917 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7921 i = iter->sig->sentinelpos + iter->next_arg;
7923 g_assert (i < iter->sig->param_count);
7925 return iter->sig->params [i];
7928 ICALL_EXPORT MonoObject*
7929 mono_TypedReference_ToObject (MonoTypedRef* tref)
7932 MonoObject *result = NULL;
7933 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7934 MonoObject** objp = (MonoObject **)tref->value;
7938 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7939 mono_error_set_pending_exception (&error);
7943 ICALL_EXPORT MonoTypedRef
7944 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7947 MonoReflectionField *f;
7949 MonoType *ftype = NULL;
7953 memset (&res, 0, sizeof (res));
7956 g_assert (mono_array_length (fields) > 0);
7958 klass = target->vtable->klass;
7960 for (i = 0; i < mono_array_length (fields); ++i) {
7961 f = mono_array_get (fields, MonoReflectionField*, i);
7963 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7966 if (f->field->parent != klass) {
7967 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7971 p = (guint8*)target + f->field->offset;
7973 p += f->field->offset - sizeof (MonoObject);
7974 klass = mono_class_from_mono_type (f->field->type);
7975 ftype = f->field->type;
7979 res.klass = mono_class_from_mono_type (ftype);
7986 prelink_method (MonoMethod *method, MonoError *error)
7988 const char *exc_class, *exc_arg;
7990 mono_error_init (error);
7991 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7993 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7995 mono_error_set_exception_instance (error,
7996 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7999 /* create the wrapper, too? */
8003 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
8007 prelink_method (method->method, &error);
8008 mono_error_set_pending_exception (&error);
8012 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
8015 MonoClass *klass = mono_class_from_mono_type (type->type);
8017 gpointer iter = NULL;
8019 mono_class_init_checked (klass, &error);
8020 if (mono_error_set_pending_exception (&error))
8023 while ((m = mono_class_get_methods (klass, &iter))) {
8024 prelink_method (m, &error);
8025 if (mono_error_set_pending_exception (&error))
8030 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
8032 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
8033 gint32 const **exponents,
8034 gunichar2 const **digitLowerTable,
8035 gunichar2 const **digitUpperTable,
8036 gint64 const **tenPowersList,
8037 gint32 const **decHexDigits)
8039 *mantissas = Formatter_MantissaBitsTable;
8040 *exponents = Formatter_TensExponentTable;
8041 *digitLowerTable = Formatter_DigitLowerTable;
8042 *digitUpperTable = Formatter_DigitUpperTable;
8043 *tenPowersList = Formatter_TenPowersList;
8044 *decHexDigits = Formatter_DecHexDigits;
8048 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
8049 * and avoid useless allocations.
8052 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
8054 MonoReflectionType *rt;
8058 mono_error_init (error);
8059 for (i = 0; i < type->num_mods; ++i) {
8060 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
8065 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
8066 return_val_if_nok (error, NULL);
8068 for (i = 0; i < type->num_mods; ++i) {
8069 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
8070 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
8071 return_val_if_nok (error, NULL);
8073 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8074 return_val_if_nok (error, NULL);
8076 mono_array_setref (res, count, rt);
8083 ICALL_EXPORT MonoArray*
8084 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
8087 MonoType *type = param->ClassImpl->type;
8088 MonoClass *member_class = mono_object_class (param->MemberImpl);
8089 MonoMethod *method = NULL;
8092 MonoMethodSignature *sig;
8095 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8096 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8097 method = rmethod->method;
8098 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
8099 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8100 if (!(method = prop->property->get))
8101 method = prop->property->set;
8104 char *type_name = mono_type_get_full_name (member_class);
8105 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
8106 MonoException *ex = mono_get_exception_not_supported (msg);
8109 mono_set_pending_exception (ex);
8113 image = method->klass->image;
8114 pos = param->PositionImpl;
8115 sig = mono_method_signature (method);
8119 type = sig->params [pos];
8121 res = type_array_from_modifiers (image, type, optional, &error);
8122 mono_error_set_pending_exception (&error);
8127 get_property_type (MonoProperty *prop)
8129 MonoMethodSignature *sig;
8131 sig = mono_method_signature (prop->get);
8133 } else if (prop->set) {
8134 sig = mono_method_signature (prop->set);
8135 return sig->params [sig->param_count - 1];
8140 ICALL_EXPORT MonoArray*
8141 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
8144 MonoType *type = get_property_type (property->property);
8145 MonoImage *image = property->klass->image;
8150 res = type_array_from_modifiers (image, type, optional, &error);
8151 mono_error_set_pending_exception (&error);
8156 *Construct a MonoType suited to be used to decode a constant blob object.
8158 * @type is the target type which will be constructed
8159 * @blob_type is the blob type, for example, that comes from the constant table
8160 * @real_type is the expected constructed type.
8163 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8165 type->type = blob_type;
8166 type->data.klass = NULL;
8167 if (blob_type == MONO_TYPE_CLASS)
8168 type->data.klass = mono_defaults.object_class;
8169 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8170 /* For enums, we need to use the base type */
8171 type->type = MONO_TYPE_VALUETYPE;
8172 type->data.klass = mono_class_from_mono_type (real_type);
8174 type->data.klass = mono_class_from_mono_type (real_type);
8177 ICALL_EXPORT MonoObject*
8178 property_info_get_default_value (MonoReflectionProperty *property)
8182 MonoProperty *prop = property->property;
8183 MonoType *type = get_property_type (prop);
8184 MonoDomain *domain = mono_object_domain (property);
8185 MonoTypeEnum def_type;
8186 const char *def_value;
8189 mono_class_init (prop->parent);
8191 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8192 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8196 def_value = mono_class_get_property_default_value (prop, &def_type);
8198 mono_type_from_blob_type (&blob_type, def_type, type);
8199 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8201 mono_error_set_pending_exception (&error);
8205 ICALL_EXPORT MonoBoolean
8206 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8209 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8210 MonoCustomAttrInfo *cinfo;
8213 mono_class_init_checked (attr_class, &error);
8214 if (mono_error_set_pending_exception (&error))
8217 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8218 if (!is_ok (&error)) {
8219 mono_error_set_pending_exception (&error);
8224 found = mono_custom_attrs_has_attr (cinfo, attr_class);
8226 mono_custom_attrs_free (cinfo);
8230 ICALL_EXPORT MonoArray*
8231 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8233 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8238 mono_class_init_checked (attr_class, &error);
8239 if (mono_error_set_pending_exception (&error))
8243 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8244 if (!mono_error_ok (&error)) {
8245 mono_error_set_pending_exception (&error);
8252 ICALL_EXPORT MonoArray*
8253 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8257 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8258 mono_error_set_pending_exception (&error);
8263 ICALL_EXPORT MonoString*
8264 ves_icall_Mono_Runtime_GetDisplayName (void)
8267 MonoString *display_name;
8269 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8270 display_name = mono_string_new (mono_domain_get (), info);
8272 return display_name;
8275 ICALL_EXPORT MonoString*
8276 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8279 MonoString *message;
8283 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8284 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8287 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8289 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8290 if (mono_error_set_pending_exception (&error))
8297 ICALL_EXPORT gpointer
8298 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8300 return GetCurrentProcess ();
8303 ICALL_EXPORT MonoBoolean
8304 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8306 return GetExitCodeProcess (handle, (guint32*) exitcode);
8309 ICALL_EXPORT MonoBoolean
8310 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8312 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8313 return CloseHandle (handle);
8315 return CloseProcess (handle);
8319 ICALL_EXPORT MonoBoolean
8320 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8322 return TerminateProcess (handle, exitcode);
8326 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8328 return WaitForInputIdle (handle, milliseconds);
8331 ICALL_EXPORT MonoBoolean
8332 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8334 return GetProcessWorkingSetSize (handle, min, max);
8337 ICALL_EXPORT MonoBoolean
8338 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8340 return SetProcessWorkingSetSize (handle, min, max);
8343 ICALL_EXPORT MonoBoolean
8344 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8346 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8350 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8352 return mono_process_current_pid ();
8356 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8358 return GetPriorityClass (handle);
8361 ICALL_EXPORT MonoBoolean
8362 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8364 return SetPriorityClass (handle, priorityClass);
8367 #ifndef DISABLE_ICALL_TABLES
8369 #define ICALL_TYPE(id,name,first)
8370 #define ICALL(id,name,func) Icall_ ## id,
8373 #include "metadata/icall-def.h"
8379 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8380 #define ICALL(id,name,func)
8382 #include "metadata/icall-def.h"
8388 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8389 #define ICALL(id,name,func)
8391 guint16 first_icall;
8394 static const IcallTypeDesc
8395 icall_type_descs [] = {
8396 #include "metadata/icall-def.h"
8400 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8403 #define ICALL_TYPE(id,name,first)
8406 #ifdef HAVE_ARRAY_ELEM_INIT
8407 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8408 #define MSGSTRFIELD1(line) str##line
8410 static const struct msgstrtn_t {
8411 #define ICALL(id,name,func)
8413 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8414 #include "metadata/icall-def.h"
8416 } icall_type_names_str = {
8417 #define ICALL_TYPE(id,name,first) (name),
8418 #include "metadata/icall-def.h"
8421 static const guint16 icall_type_names_idx [] = {
8422 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8423 #include "metadata/icall-def.h"
8426 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8428 static const struct msgstr_t {
8430 #define ICALL_TYPE(id,name,first)
8431 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8432 #include "metadata/icall-def.h"
8434 } icall_names_str = {
8435 #define ICALL(id,name,func) (name),
8436 #include "metadata/icall-def.h"
8439 static const guint16 icall_names_idx [] = {
8440 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8441 #include "metadata/icall-def.h"
8444 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8450 #define ICALL_TYPE(id,name,first) name,
8451 #define ICALL(id,name,func)
8452 static const char* const
8453 icall_type_names [] = {
8454 #include "metadata/icall-def.h"
8458 #define icall_type_name_get(id) (icall_type_names [(id)])
8462 #define ICALL_TYPE(id,name,first)
8463 #define ICALL(id,name,func) name,
8464 static const char* const
8466 #include "metadata/icall-def.h"
8469 #define icall_name_get(id) icall_names [(id)]
8471 #endif /* !HAVE_ARRAY_ELEM_INIT */
8475 #define ICALL_TYPE(id,name,first)
8476 #define ICALL(id,name,func) func,
8477 static const gconstpointer
8478 icall_functions [] = {
8479 #include "metadata/icall-def.h"
8483 #ifdef ENABLE_ICALL_SYMBOL_MAP
8486 #define ICALL_TYPE(id,name,first)
8487 #define ICALL(id,name,func) #func,
8488 static const gconstpointer
8489 icall_symbols [] = {
8490 #include "metadata/icall-def.h"
8495 #endif /* DISABLE_ICALL_TABLES */
8497 static mono_mutex_t icall_mutex;
8498 static GHashTable *icall_hash = NULL;
8499 static GHashTable *jit_icall_hash_name = NULL;
8500 static GHashTable *jit_icall_hash_addr = NULL;
8503 mono_icall_init (void)
8505 #ifndef DISABLE_ICALL_TABLES
8508 /* check that tables are sorted: disable in release */
8511 const char *prev_class = NULL;
8512 const char *prev_method;
8514 for (i = 0; i < Icall_type_num; ++i) {
8515 const IcallTypeDesc *desc;
8518 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8519 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8520 prev_class = icall_type_name_get (i);
8521 desc = &icall_type_descs [i];
8522 num_icalls = icall_desc_num_icalls (desc);
8523 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8524 for (j = 0; j < num_icalls; ++j) {
8525 const char *methodn = icall_name_get (desc->first_icall + j);
8526 if (prev_method && strcmp (prev_method, methodn) >= 0)
8527 g_print ("method %s should come before method %s\n", methodn, prev_method);
8528 prev_method = methodn;
8534 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8535 mono_os_mutex_init (&icall_mutex);
8539 mono_icall_lock (void)
8541 mono_locks_os_acquire (&icall_mutex, IcallLock);
8545 mono_icall_unlock (void)
8547 mono_locks_os_release (&icall_mutex, IcallLock);
8551 mono_icall_cleanup (void)
8553 g_hash_table_destroy (icall_hash);
8554 g_hash_table_destroy (jit_icall_hash_name);
8555 g_hash_table_destroy (jit_icall_hash_addr);
8556 mono_os_mutex_destroy (&icall_mutex);
8560 * mono_add_internal_call:
8561 * @name: method specification to surface to the managed world
8562 * @method: pointer to a C method to invoke when the method is called
8564 * This method surfaces the C function pointed by @method as a method
8565 * that has been surfaced in managed code with the method specified in
8566 * @name as an internal call.
8568 * Internal calls are surfaced to all app domains loaded and they are
8569 * accessibly by a type with the specified name.
8571 * You must provide a fully qualified type name, that is namespaces
8572 * and type name, followed by a colon and the method name, with an
8573 * optional signature to bind.
8575 * For example, the following are all valid declarations:
8577 * "MyApp.Services.ScriptService:Accelerate"
8578 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8580 * You use method parameters in cases where there might be more than
8581 * one surface method to managed code. That way you can register different
8582 * internal calls for different method overloads.
8584 * The internal calls are invoked with no marshalling. This means that .NET
8585 * types like System.String are exposed as `MonoString *` parameters. This is
8586 * different than the way that strings are surfaced in P/Invoke.
8588 * For more information on how the parameters are marshalled, see the
8589 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8592 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8593 * reference for more information on the format of method descriptions.
8596 mono_add_internal_call (const char *name, gconstpointer method)
8600 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8602 mono_icall_unlock ();
8605 #ifndef DISABLE_ICALL_TABLES
8607 #ifdef HAVE_ARRAY_ELEM_INIT
8609 compare_method_imap (const void *key, const void *elem)
8611 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8612 return strcmp (key, method_name);
8616 find_method_icall (const IcallTypeDesc *imap, const char *name)
8618 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);
8621 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8625 compare_class_imap (const void *key, const void *elem)
8627 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8628 return strcmp (key, class_name);
8631 static const IcallTypeDesc*
8632 find_class_icalls (const char *name)
8634 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);
8637 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8640 #else /* HAVE_ARRAY_ELEM_INIT */
8643 compare_method_imap (const void *key, const void *elem)
8645 const char** method_name = (const char**)elem;
8646 return strcmp (key, *method_name);
8650 find_method_icall (const IcallTypeDesc *imap, const char *name)
8652 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8655 return (gpointer)icall_functions [(nameslot - icall_names)];
8659 compare_class_imap (const void *key, const void *elem)
8661 const char** class_name = (const char**)elem;
8662 return strcmp (key, *class_name);
8665 static const IcallTypeDesc*
8666 find_class_icalls (const char *name)
8668 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8671 return &icall_type_descs [nameslot - icall_type_names];
8674 #endif /* HAVE_ARRAY_ELEM_INIT */
8676 #endif /* DISABLE_ICALL_TABLES */
8679 * we should probably export this as an helper (handle nested types).
8680 * Returns the number of chars written in buf.
8683 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8685 int nspacelen, cnamelen;
8686 nspacelen = strlen (klass->name_space);
8687 cnamelen = strlen (klass->name);
8688 if (nspacelen + cnamelen + 2 > bufsize)
8691 memcpy (buf, klass->name_space, nspacelen);
8692 buf [nspacelen ++] = '.';
8694 memcpy (buf + nspacelen, klass->name, cnamelen);
8695 buf [nspacelen + cnamelen] = 0;
8696 return nspacelen + cnamelen;
8699 #ifdef DISABLE_ICALL_TABLES
8701 no_icall_table (void)
8703 g_assert_not_reached ();
8708 mono_lookup_internal_call (MonoMethod *method)
8713 int typelen = 0, mlen, siglen;
8715 #ifndef DISABLE_ICALL_TABLES
8716 const IcallTypeDesc *imap = NULL;
8719 g_assert (method != NULL);
8721 if (method->is_inflated)
8722 method = ((MonoMethodInflated *) method)->declaring;
8724 if (method->klass->nested_in) {
8725 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8729 mname [pos++] = '/';
8732 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8738 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8743 #ifndef DISABLE_ICALL_TABLES
8744 imap = find_class_icalls (mname);
8747 mname [typelen] = ':';
8748 mname [typelen + 1] = ':';
8750 mlen = strlen (method->name);
8751 memcpy (mname + typelen + 2, method->name, mlen);
8752 sigstart = mname + typelen + 2 + mlen;
8755 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8756 siglen = strlen (tmpsig);
8757 if (typelen + mlen + siglen + 6 > sizeof (mname))
8760 memcpy (sigstart + 1, tmpsig, siglen);
8761 sigstart [siglen + 1] = ')';
8762 sigstart [siglen + 2] = 0;
8767 res = g_hash_table_lookup (icall_hash, mname);
8769 mono_icall_unlock ();;
8772 /* try without signature */
8774 res = g_hash_table_lookup (icall_hash, mname);
8776 mono_icall_unlock ();
8780 #ifdef DISABLE_ICALL_TABLES
8781 mono_icall_unlock ();
8782 /* Fail only when the result is actually used */
8783 /* mono_marshal_get_native_wrapper () depends on this */
8784 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8785 return ves_icall_System_String_ctor_RedirectToCreateString;
8787 return no_icall_table;
8789 /* it wasn't found in the static call tables */
8791 mono_icall_unlock ();
8794 res = find_method_icall (imap, sigstart - mlen);
8796 mono_icall_unlock ();
8799 /* try _with_ signature */
8801 res = find_method_icall (imap, sigstart - mlen);
8803 mono_icall_unlock ();
8807 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8808 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8809 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8810 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8811 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");
8812 g_print ("If you see other errors or faults after this message they are probably related\n");
8813 g_print ("and you need to fix your mono install first.\n");
8815 mono_icall_unlock ();
8821 #ifdef ENABLE_ICALL_SYMBOL_MAP
8823 func_cmp (gconstpointer key, gconstpointer p)
8825 return (gsize)key - (gsize)*(gsize*)p;
8830 * mono_lookup_icall_symbol:
8832 * Given the icall METHOD, returns its C symbol.
8835 mono_lookup_icall_symbol (MonoMethod *m)
8837 #ifdef DISABLE_ICALL_TABLES
8838 g_assert_not_reached ();
8841 #ifdef ENABLE_ICALL_SYMBOL_MAP
8845 static gconstpointer *functions_sorted;
8846 static const char**symbols_sorted;
8847 static gboolean inited;
8852 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8853 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8854 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8855 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8856 /* Bubble sort the two arrays */
8860 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8861 if (functions_sorted [i] > functions_sorted [i + 1]) {
8864 tmp = functions_sorted [i];
8865 functions_sorted [i] = functions_sorted [i + 1];
8866 functions_sorted [i + 1] = tmp;
8867 tmp = symbols_sorted [i];
8868 symbols_sorted [i] = symbols_sorted [i + 1];
8869 symbols_sorted [i + 1] = tmp;
8876 func = mono_lookup_internal_call (m);
8879 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8883 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8885 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8886 g_assert_not_reached ();
8893 type_from_typename (char *type_name)
8895 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8897 if (!strcmp (type_name, "int"))
8898 klass = mono_defaults.int_class;
8899 else if (!strcmp (type_name, "ptr"))
8900 klass = mono_defaults.int_class;
8901 else if (!strcmp (type_name, "void"))
8902 klass = mono_defaults.void_class;
8903 else if (!strcmp (type_name, "int32"))
8904 klass = mono_defaults.int32_class;
8905 else if (!strcmp (type_name, "uint32"))
8906 klass = mono_defaults.uint32_class;
8907 else if (!strcmp (type_name, "int8"))
8908 klass = mono_defaults.sbyte_class;
8909 else if (!strcmp (type_name, "uint8"))
8910 klass = mono_defaults.byte_class;
8911 else if (!strcmp (type_name, "int16"))
8912 klass = mono_defaults.int16_class;
8913 else if (!strcmp (type_name, "uint16"))
8914 klass = mono_defaults.uint16_class;
8915 else if (!strcmp (type_name, "long"))
8916 klass = mono_defaults.int64_class;
8917 else if (!strcmp (type_name, "ulong"))
8918 klass = mono_defaults.uint64_class;
8919 else if (!strcmp (type_name, "float"))
8920 klass = mono_defaults.single_class;
8921 else if (!strcmp (type_name, "double"))
8922 klass = mono_defaults.double_class;
8923 else if (!strcmp (type_name, "object"))
8924 klass = mono_defaults.object_class;
8925 else if (!strcmp (type_name, "obj"))
8926 klass = mono_defaults.object_class;
8927 else if (!strcmp (type_name, "string"))
8928 klass = mono_defaults.string_class;
8929 else if (!strcmp (type_name, "bool"))
8930 klass = mono_defaults.boolean_class;
8931 else if (!strcmp (type_name, "boolean"))
8932 klass = mono_defaults.boolean_class;
8934 g_error ("%s", type_name);
8935 g_assert_not_reached ();
8937 return &klass->byval_arg;
8941 * LOCKING: Take the corlib image lock.
8943 MonoMethodSignature*
8944 mono_create_icall_signature (const char *sigstr)
8949 MonoMethodSignature *res, *res2;
8950 MonoImage *corlib = mono_defaults.corlib;
8952 mono_image_lock (corlib);
8953 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8954 mono_image_unlock (corlib);
8959 parts = g_strsplit (sigstr, " ", 256);
8968 res = mono_metadata_signature_alloc (corlib, len - 1);
8973 * Under windows, the default pinvoke calling convention is STDCALL but
8976 res->call_convention = MONO_CALL_C;
8979 res->ret = type_from_typename (parts [0]);
8980 for (i = 1; i < len; ++i) {
8981 res->params [i - 1] = type_from_typename (parts [i]);
8986 mono_image_lock (corlib);
8987 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8989 res = res2; /*Value is allocated in the image pool*/
8991 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8992 mono_image_unlock (corlib);
8998 mono_find_jit_icall_by_name (const char *name)
9000 MonoJitICallInfo *info;
9001 g_assert (jit_icall_hash_name);
9004 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9005 mono_icall_unlock ();
9010 mono_find_jit_icall_by_addr (gconstpointer addr)
9012 MonoJitICallInfo *info;
9013 g_assert (jit_icall_hash_addr);
9016 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
9017 mono_icall_unlock ();
9023 * mono_get_jit_icall_info:
9025 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
9026 * caller should access it while holding the icall lock.
9029 mono_get_jit_icall_info (void)
9031 return jit_icall_hash_name;
9035 * mono_lookup_jit_icall_symbol:
9037 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
9040 mono_lookup_jit_icall_symbol (const char *name)
9042 MonoJitICallInfo *info;
9043 const char *res = NULL;
9046 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9048 res = info->c_symbol;
9049 mono_icall_unlock ();
9054 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
9057 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
9058 mono_icall_unlock ();
9062 * 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
9063 * icalls without wrappers in some cases.
9066 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
9068 MonoJitICallInfo *info;
9075 if (!jit_icall_hash_name) {
9076 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
9077 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
9080 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
9081 g_warning ("jit icall already defined \"%s\"\n", name);
9082 g_assert_not_reached ();
9085 info = g_new0 (MonoJitICallInfo, 1);
9090 info->c_symbol = c_symbol;
9091 info->no_raise = no_raise;
9094 info->wrapper = func;
9096 info->wrapper = NULL;
9099 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
9100 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
9102 mono_icall_unlock ();
9107 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
9109 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);