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_MonoType_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);
2158 case MONO_TYPE_STRING:
2159 case MONO_TYPE_CLASS:
2160 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2163 g_assert_not_reached ();
2169 ICALL_EXPORT MonoReflectionType*
2170 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2173 MonoReflectionType *ret;
2176 type = mono_field_get_type_checked (ref_field->field, &error);
2177 if (!mono_error_ok (&error)) {
2178 mono_error_set_pending_exception (&error);
2182 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2183 if (!mono_error_ok (&error)) {
2184 mono_error_set_pending_exception (&error);
2191 /* From MonoProperty.cs */
2193 PInfo_Attributes = 1,
2194 PInfo_GetMethod = 1 << 1,
2195 PInfo_SetMethod = 1 << 2,
2196 PInfo_ReflectedType = 1 << 3,
2197 PInfo_DeclaringType = 1 << 4,
2202 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2205 MonoReflectionType *rt;
2206 MonoReflectionMethod *rm;
2207 MonoDomain *domain = mono_object_domain (property);
2208 const MonoProperty *pproperty = property->property;
2210 if ((req_info & PInfo_ReflectedType) != 0) {
2211 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2212 if (mono_error_set_pending_exception (&error))
2215 MONO_STRUCT_SETREF (info, parent, rt);
2217 if ((req_info & PInfo_DeclaringType) != 0) {
2218 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2219 if (mono_error_set_pending_exception (&error))
2222 MONO_STRUCT_SETREF (info, declaring_type, rt);
2225 if ((req_info & PInfo_Name) != 0)
2226 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2228 if ((req_info & PInfo_Attributes) != 0)
2229 info->attrs = pproperty->attrs;
2231 if ((req_info & PInfo_GetMethod) != 0) {
2232 if (pproperty->get &&
2233 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2234 pproperty->get->klass == property->klass)) {
2235 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2236 if (mono_error_set_pending_exception (&error))
2242 MONO_STRUCT_SETREF (info, get, rm);
2244 if ((req_info & PInfo_SetMethod) != 0) {
2245 if (pproperty->set &&
2246 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2247 pproperty->set->klass == property->klass)) {
2248 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2249 if (mono_error_set_pending_exception (&error))
2255 MONO_STRUCT_SETREF (info, set, rm);
2258 * There may be other methods defined for properties, though, it seems they are not exposed
2259 * in the reflection API
2264 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2267 MonoReflectionType *rt;
2268 MonoReflectionMethod *rm;
2269 MonoDomain *domain = mono_object_domain (event);
2271 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2272 if (mono_error_set_pending_exception (&error))
2275 MONO_STRUCT_SETREF (info, reflected_type, rt);
2277 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2278 if (mono_error_set_pending_exception (&error))
2281 MONO_STRUCT_SETREF (info, declaring_type, rt);
2283 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2284 info->attrs = event->event->attrs;
2286 if (event->event->add) {
2287 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2288 if (mono_error_set_pending_exception (&error))
2294 MONO_STRUCT_SETREF (info, add_method, rm);
2296 if (event->event->remove) {
2297 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2298 if (mono_error_set_pending_exception (&error))
2304 MONO_STRUCT_SETREF (info, remove_method, rm);
2306 if (event->event->raise) {
2307 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2308 if (mono_error_set_pending_exception (&error))
2314 MONO_STRUCT_SETREF (info, raise_method, rm);
2316 #ifndef MONO_SMALL_CONFIG
2317 if (event->event->other) {
2319 while (event->event->other [n])
2321 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2322 if (mono_error_set_pending_exception (&error))
2324 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2326 for (i = 0; i < n; i++) {
2327 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2328 if (mono_error_set_pending_exception (&error))
2330 mono_array_setref (info->other_methods, i, rm);
2337 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2342 mono_class_setup_interfaces (klass, error);
2343 if (!mono_error_ok (error))
2346 for (i = 0; i < klass->interface_count; i++) {
2347 ic = klass->interfaces [i];
2348 g_hash_table_insert (ifaces, ic, ic);
2350 collect_interfaces (ic, ifaces, error);
2351 if (!mono_error_ok (error))
2357 MonoArray *iface_array;
2358 MonoGenericContext *context;
2362 } FillIfaceArrayData;
2365 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2367 MonoReflectionType *rt;
2368 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2369 MonoClass *ic = (MonoClass *)key;
2370 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2372 if (!mono_error_ok (data->error))
2375 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2376 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2377 if (!mono_error_ok (data->error))
2381 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2382 if (!mono_error_ok (data->error))
2385 mono_array_setref (data->iface_array, data->next_idx++, rt);
2388 mono_metadata_free_type (inflated);
2392 get_interfaces_hash (gconstpointer v1)
2394 MonoClass *k = (MonoClass*)v1;
2396 return k->type_token;
2399 ICALL_EXPORT MonoArray*
2400 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2403 MonoClass *klass = mono_class_from_mono_type (type->type);
2405 FillIfaceArrayData data = { 0 };
2408 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2410 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2411 data.context = mono_class_get_context (klass);
2412 klass = klass->generic_class->container_class;
2415 for (parent = klass; parent; parent = parent->parent) {
2416 mono_class_setup_interfaces (parent, &error);
2417 if (!mono_error_ok (&error))
2419 collect_interfaces (parent, iface_hash, &error);
2420 if (!mono_error_ok (&error))
2424 data.error = &error;
2425 data.domain = mono_object_domain (type);
2427 len = g_hash_table_size (iface_hash);
2429 g_hash_table_destroy (iface_hash);
2430 if (!data.domain->empty_types)
2431 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2432 return data.domain->empty_types;
2435 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2436 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2437 if (!mono_error_ok (&error))
2440 g_hash_table_destroy (iface_hash);
2441 return data.iface_array;
2444 g_hash_table_destroy (iface_hash);
2445 mono_error_set_pending_exception (&error);
2450 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2452 gboolean variance_used;
2453 MonoClass *klass = mono_class_from_mono_type (type->type);
2454 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2455 MonoReflectionMethod *member;
2458 int i = 0, len, ioffset;
2462 mono_class_init_checked (klass, &error);
2463 if (mono_error_set_pending_exception (&error))
2465 mono_class_init_checked (iclass, &error);
2466 if (mono_error_set_pending_exception (&error))
2469 mono_class_setup_vtable (klass);
2471 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2475 len = mono_class_num_methods (iclass);
2476 domain = mono_object_domain (type);
2477 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2478 if (mono_error_set_pending_exception (&error))
2480 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2481 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2482 if (mono_error_set_pending_exception (&error))
2484 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2486 while ((method = mono_class_get_methods (iclass, &iter))) {
2487 member = mono_method_get_object_checked (domain, method, iclass, &error);
2488 if (mono_error_set_pending_exception (&error))
2490 mono_array_setref (*methods, i, member);
2491 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2492 if (mono_error_set_pending_exception (&error))
2494 mono_array_setref (*targets, i, member);
2501 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2504 MonoClass *klass = mono_class_from_mono_type (type->type);
2506 mono_class_init_checked (klass, &error);
2507 if (mono_error_set_pending_exception (&error))
2510 if (image_is_dynamic (klass->image)) {
2511 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2512 *packing = tb->packing_size;
2513 *size = tb->class_size;
2515 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2519 ICALL_EXPORT MonoReflectionType*
2520 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2523 MonoReflectionType *ret;
2526 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2527 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2528 mono_error_set_pending_exception (&error);
2532 klass = mono_class_from_mono_type (type->type);
2533 mono_class_init_checked (klass, &error);
2534 if (mono_error_set_pending_exception (&error))
2538 // GetElementType should only return a type for:
2539 // Array Pointer PassedByRef
2540 if (type->type->byref)
2541 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2542 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2543 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2544 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2545 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2549 mono_error_set_pending_exception (&error);
2554 ICALL_EXPORT MonoReflectionType*
2555 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2558 MonoReflectionType *ret;
2560 if (type->type->byref)
2563 MonoClass *klass = mono_class_from_mono_type (type->type);
2567 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2568 mono_error_set_pending_exception (&error);
2573 ICALL_EXPORT MonoBoolean
2574 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2576 return type->type->type == MONO_TYPE_PTR;
2579 ICALL_EXPORT MonoBoolean
2580 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2582 return (!type->type->byref && (((type->type->type >= MONO_TYPE_BOOLEAN) && (type->type->type <= MONO_TYPE_R8)) || (type->type->type == MONO_TYPE_I) || (type->type->type == MONO_TYPE_U)));
2585 ICALL_EXPORT MonoBoolean
2586 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2588 return type->type->byref;
2591 ICALL_EXPORT MonoBoolean
2592 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2595 MonoClass *klass = mono_class_from_mono_type (type->type);
2596 mono_class_init_checked (klass, &error);
2597 if (mono_error_set_pending_exception (&error))
2600 return mono_class_is_com_object (klass);
2603 ICALL_EXPORT guint32
2604 ves_icall_reflection_get_token (MonoObject* obj)
2607 guint32 result = mono_reflection_get_token_checked (obj, &error);
2608 mono_error_set_pending_exception (&error);
2612 ICALL_EXPORT MonoReflectionModule*
2613 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2616 MonoReflectionModule *result = NULL;
2617 MonoClass *klass = mono_class_from_mono_type (type->type);
2618 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2619 mono_error_set_pending_exception (&error);
2623 ICALL_EXPORT MonoReflectionAssembly*
2624 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2627 MonoDomain *domain = mono_domain_get ();
2628 MonoClass *klass = mono_class_from_mono_type (type->type);
2629 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2630 mono_error_set_pending_exception (&error);
2634 ICALL_EXPORT MonoReflectionType*
2635 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2638 MonoReflectionType *ret;
2639 MonoDomain *domain = mono_domain_get ();
2642 if (type->type->byref)
2644 if (type->type->type == MONO_TYPE_VAR) {
2645 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2646 klass = param ? param->owner.klass : NULL;
2647 } else if (type->type->type == MONO_TYPE_MVAR) {
2648 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2649 klass = param ? param->owner.method->klass : NULL;
2651 klass = mono_class_from_mono_type (type->type)->nested_in;
2657 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2658 mono_error_set_pending_exception (&error);
2663 ICALL_EXPORT MonoString*
2664 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2666 MonoDomain *domain = mono_domain_get ();
2667 MonoClass *klass = mono_class_from_mono_type (type->type);
2669 if (type->type->byref) {
2670 char *n = g_strdup_printf ("%s&", klass->name);
2671 MonoString *res = mono_string_new (domain, n);
2677 return mono_string_new (domain, klass->name);
2681 ICALL_EXPORT MonoString*
2682 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2684 MonoDomain *domain = mono_domain_get ();
2685 MonoClass *klass = mono_class_from_mono_type (type->type);
2687 while (klass->nested_in)
2688 klass = klass->nested_in;
2690 if (klass->name_space [0] == '\0')
2693 return mono_string_new (domain, klass->name_space);
2697 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2701 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2702 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2706 klass = mono_class_from_mono_type (type->type);
2712 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2714 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2717 ICALL_EXPORT MonoArray*
2718 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2721 MonoReflectionType *rt;
2723 MonoClass *klass, *pklass;
2724 MonoDomain *domain = mono_object_domain (type);
2727 klass = mono_class_from_mono_type (type->type);
2729 if (klass->generic_container) {
2730 MonoGenericContainer *container = klass->generic_container;
2731 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2732 if (mono_error_set_pending_exception (&error))
2734 for (i = 0; i < container->type_argc; ++i) {
2735 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2737 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2738 if (mono_error_set_pending_exception (&error))
2741 mono_array_setref (res, i, rt);
2743 } else if (klass->generic_class) {
2744 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2745 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2746 if (mono_error_set_pending_exception (&error))
2748 for (i = 0; i < inst->type_argc; ++i) {
2749 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2750 if (mono_error_set_pending_exception (&error))
2753 mono_array_setref (res, i, rt);
2761 ICALL_EXPORT gboolean
2762 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2766 if (!IS_MONOTYPE (type))
2769 if (type->type->byref)
2772 klass = mono_class_from_mono_type (type->type);
2773 return klass->generic_container != NULL;
2776 ICALL_EXPORT MonoReflectionType*
2777 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2780 MonoReflectionType *ret;
2783 if (type->type->byref)
2786 klass = mono_class_from_mono_type (type->type);
2788 if (klass->generic_container) {
2789 return type; /* check this one */
2791 if (klass->generic_class) {
2792 MonoClass *generic_class = klass->generic_class->container_class;
2795 tb = mono_class_get_ref_info (generic_class);
2797 if (generic_class->wastypebuilder && tb)
2798 return (MonoReflectionType *)tb;
2800 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2801 mono_error_set_pending_exception (&error);
2809 ICALL_EXPORT MonoReflectionType*
2810 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2813 MonoReflectionType *ret;
2815 MonoType *geninst, **types;
2818 g_assert (IS_MONOTYPE (type));
2819 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2820 if (mono_error_set_pending_exception (&error))
2823 count = mono_array_length (type_array);
2824 types = g_new0 (MonoType *, count);
2826 for (i = 0; i < count; i++) {
2827 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2828 types [i] = t->type;
2831 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2834 mono_error_set_pending_exception (&error);
2838 klass = mono_class_from_mono_type (geninst);
2840 /*we might inflate to the GTD*/
2841 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2842 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2846 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2847 mono_error_set_pending_exception (&error);
2852 ICALL_EXPORT gboolean
2853 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2857 if (!IS_MONOTYPE (type))
2860 if (type->type->byref)
2863 klass = mono_class_from_mono_type (type->type);
2864 return klass->generic_class != NULL || klass->generic_container != NULL;
2868 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2870 if (!IS_MONOTYPE (type))
2873 if (is_generic_parameter (type->type))
2874 return mono_type_get_generic_param_num (type->type);
2878 ICALL_EXPORT GenericParameterAttributes
2879 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2881 g_assert (IS_MONOTYPE (type));
2882 g_assert (is_generic_parameter (type->type));
2883 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2886 ICALL_EXPORT MonoArray *
2887 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2890 MonoReflectionType *rt;
2891 MonoGenericParamInfo *param_info;
2897 g_assert (IS_MONOTYPE (type));
2899 domain = mono_object_domain (type);
2900 param_info = mono_generic_param_info (type->type->data.generic_param);
2901 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2904 res = mono_array_new_checked (domain, mono_defaults.monotype_class, count, &error);
2905 if (mono_error_set_pending_exception (&error))
2907 for (i = 0; i < count; i++) {
2908 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2909 if (mono_error_set_pending_exception (&error))
2912 mono_array_setref (res, i, rt);
2919 ICALL_EXPORT MonoBoolean
2920 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2922 return is_generic_parameter (type->type);
2925 ICALL_EXPORT MonoBoolean
2926 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2928 return is_generic_parameter (tb->type.type);
2932 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2933 MonoReflectionType *t)
2935 enumtype->type = t->type;
2938 ICALL_EXPORT MonoReflectionMethod*
2939 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2940 MonoReflectionMethod* generic)
2947 MonoReflectionMethod *ret = NULL;
2949 domain = ((MonoObject *)type)->vtable->domain;
2951 klass = mono_class_from_mono_type (type->type);
2952 mono_class_init_checked (klass, &error);
2953 if (mono_error_set_pending_exception (&error))
2957 while ((method = mono_class_get_methods (klass, &iter))) {
2958 if (method->token == generic->method->token) {
2959 ret = mono_method_get_object_checked (domain, method, klass, &error);
2960 if (mono_error_set_pending_exception (&error))
2968 ICALL_EXPORT MonoReflectionMethod *
2969 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2972 MonoType *type = ref_type->type;
2974 MonoReflectionMethod *ret = NULL;
2976 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2977 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2980 if (type->type == MONO_TYPE_VAR)
2983 method = mono_type_get_generic_param_owner (type)->owner.method;
2986 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2987 if (!mono_error_ok (&error))
2988 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2992 ICALL_EXPORT MonoBoolean
2993 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2995 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2999 ICALL_EXPORT MonoBoolean
3000 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
3002 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3007 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
3009 MonoDomain *domain = mono_domain_get ();
3010 MonoImage *image = method->method->klass->image;
3011 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
3012 MonoTableInfo *tables = image->tables;
3013 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
3014 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
3015 guint32 im_cols [MONO_IMPLMAP_SIZE];
3016 guint32 scope_token;
3017 const char *import = NULL;
3018 const char *scope = NULL;
3020 if (image_is_dynamic (image)) {
3021 MonoReflectionMethodAux *method_aux =
3022 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
3024 import = method_aux->dllentry;
3025 scope = method_aux->dll;
3028 if (!import || !scope) {
3029 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
3034 if (piinfo->implmap_idx) {
3035 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
3037 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
3038 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
3039 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
3040 scope = mono_metadata_string_heap (image, scope_token);
3044 *flags = piinfo->piflags;
3045 *entry_point = mono_string_new (domain, import);
3046 *dll_name = mono_string_new (domain, scope);
3049 ICALL_EXPORT MonoReflectionMethod *
3050 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3052 MonoMethodInflated *imethod;
3054 MonoReflectionMethod *ret = NULL;
3057 if (method->method->is_generic)
3060 if (!method->method->is_inflated)
3063 imethod = (MonoMethodInflated *) method->method;
3065 result = imethod->declaring;
3066 /* Not a generic method. */
3067 if (!result->is_generic)
3070 if (image_is_dynamic (method->method->klass->image)) {
3071 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3072 MonoReflectionMethod *res;
3075 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3076 * the dynamic case as well ?
3078 mono_image_lock ((MonoImage*)image);
3079 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3080 mono_image_unlock ((MonoImage*)image);
3086 if (imethod->context.class_inst) {
3087 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3088 /*Generic methods gets the context of the GTD.*/
3089 if (mono_class_get_context (klass)) {
3090 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3091 if (!mono_error_ok (&error))
3096 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3098 if (!mono_error_ok (&error))
3099 mono_error_set_pending_exception (&error);
3103 ICALL_EXPORT gboolean
3104 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3106 return mono_method_signature (method->method)->generic_param_count != 0;
3109 ICALL_EXPORT gboolean
3110 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3112 return method->method->is_generic;
3115 ICALL_EXPORT MonoArray*
3116 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3119 MonoReflectionType *rt;
3124 domain = mono_object_domain (method);
3126 if (method->method->is_inflated) {
3127 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3130 count = inst->type_argc;
3131 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3132 if (mono_error_set_pending_exception (&error))
3135 for (i = 0; i < count; i++) {
3136 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3137 if (mono_error_set_pending_exception (&error))
3140 mono_array_setref (res, i, rt);
3147 count = mono_method_signature (method->method)->generic_param_count;
3148 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3149 if (mono_error_set_pending_exception (&error))
3152 for (i = 0; i < count; i++) {
3153 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3154 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3155 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3157 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3158 if (mono_error_set_pending_exception (&error))
3161 mono_array_setref (res, i, rt);
3167 ICALL_EXPORT MonoObject *
3168 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3172 * Invoke from reflection is supposed to always be a virtual call (the API
3173 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3174 * greater flexibility.
3176 MonoMethod *m = method->method;
3177 MonoMethodSignature *sig = mono_method_signature (m);
3180 void *obj = this_arg;
3184 if (mono_security_core_clr_enabled () &&
3185 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3186 mono_error_set_pending_exception (&error);
3190 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3191 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3192 mono_error_cleanup (&error); /* FIXME does this make sense? */
3193 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3198 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3199 if (!is_ok (&error)) {
3200 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3203 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3204 char *target_name = mono_type_get_full_name (m->klass);
3205 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3206 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3208 g_free (target_name);
3212 m = mono_object_get_virtual_method (this_arg, m);
3213 /* must pass the pointer to the value for valuetype methods */
3214 if (m->klass->valuetype)
3215 obj = mono_object_unbox (this_arg);
3216 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3217 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3222 if (sig->ret->byref) {
3223 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "Cannot invoke method returning ByRef type via reflection"));
3227 pcount = params? mono_array_length (params): 0;
3228 if (pcount != sig->param_count) {
3229 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3233 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3234 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class."));
3238 image = m->klass->image;
3239 if (image->assembly->ref_only) {
3240 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api."));
3244 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3245 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3249 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3253 intptr_t *lower_bounds;
3254 pcount = mono_array_length (params);
3255 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3256 /* Note: the synthetized array .ctors have int32 as argument type */
3257 for (i = 0; i < pcount; ++i)
3258 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3260 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3261 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3262 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3263 if (!mono_error_ok (&error)) {
3264 mono_error_set_pending_exception (&error);
3268 for (i = 0; i < mono_array_length (arr); ++i) {
3269 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3270 if (!mono_error_ok (&error)) {
3271 mono_error_set_pending_exception (&error);
3274 mono_array_setref_fast (arr, i, subarray);
3276 return (MonoObject*)arr;
3279 if (m->klass->rank == pcount) {
3280 /* Only lengths provided. */
3281 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3282 if (!mono_error_ok (&error)) {
3283 mono_error_set_pending_exception (&error);
3287 return (MonoObject*)arr;
3289 g_assert (pcount == (m->klass->rank * 2));
3290 /* The arguments are lower-bound-length pairs */
3291 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3293 for (i = 0; i < pcount / 2; ++i) {
3294 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3295 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3298 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3299 if (!mono_error_ok (&error)) {
3300 mono_error_set_pending_exception (&error);
3304 return (MonoObject*)arr;
3307 return mono_runtime_invoke_array (m, obj, params, NULL);
3310 #ifndef DISABLE_REMOTING
3311 ICALL_EXPORT MonoObject *
3312 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3315 MonoDomain *domain = mono_object_domain (method);
3316 MonoMethod *m = method->method;
3317 MonoMethodSignature *sig = mono_method_signature (m);
3318 MonoArray *out_args;
3320 int i, j, outarg_count = 0;
3322 if (m->klass == mono_defaults.object_class) {
3323 if (!strcmp (m->name, "FieldGetter")) {
3324 MonoClass *k = this_arg->vtable->klass;
3328 /* If this is a proxy, then it must be a CBO */
3329 if (k == mono_defaults.transparent_proxy_class) {
3330 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3331 this_arg = tp->rp->unwrapped_server;
3332 g_assert (this_arg);
3333 k = this_arg->vtable->klass;
3336 name = mono_array_get (params, MonoString *, 1);
3337 str = mono_string_to_utf8 (name);
3340 MonoClassField* field = mono_class_get_field_from_name (k, str);
3343 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3344 if (field_klass->valuetype) {
3345 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3346 if (mono_error_set_pending_exception (&error))
3349 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3351 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3352 if (mono_error_set_pending_exception (&error))
3354 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3355 mono_array_setref (out_args, 0, result);
3362 g_assert_not_reached ();
3364 } else if (!strcmp (m->name, "FieldSetter")) {
3365 MonoClass *k = this_arg->vtable->klass;
3371 /* If this is a proxy, then it must be a CBO */
3372 if (k == mono_defaults.transparent_proxy_class) {
3373 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3374 this_arg = tp->rp->unwrapped_server;
3375 g_assert (this_arg);
3376 k = this_arg->vtable->klass;
3379 name = mono_array_get (params, MonoString *, 1);
3380 str = mono_string_to_utf8 (name);
3383 MonoClassField* field = mono_class_get_field_from_name (k, str);
3386 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3387 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3389 if (field_klass->valuetype) {
3390 size = mono_type_size (field->type, &align);
3391 g_assert (size == mono_class_value_size (field_klass, NULL));
3392 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3394 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3397 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3398 if (mono_error_set_pending_exception (&error))
3400 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3409 g_assert_not_reached ();
3414 for (i = 0; i < mono_array_length (params); i++) {
3415 if (sig->params [i]->byref)
3419 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3420 if (mono_error_set_pending_exception (&error))
3423 /* handle constructors only for objects already allocated */
3424 if (!strcmp (method->method->name, ".ctor"))
3425 g_assert (this_arg);
3427 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3428 g_assert (!method->method->klass->valuetype);
3429 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3431 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3432 if (sig->params [i]->byref) {
3434 arg = mono_array_get (params, gpointer, i);
3435 mono_array_setref (out_args, j, arg);
3440 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3447 read_enum_value (const char *mem, int type)
3450 case MONO_TYPE_BOOLEAN:
3452 return *(guint8*)mem;
3454 return *(gint8*)mem;
3455 case MONO_TYPE_CHAR:
3457 return read16 (mem);
3459 return (gint16) read16 (mem);
3461 return read32 (mem);
3463 return (gint32) read32 (mem);
3466 return read64 (mem);
3468 g_assert_not_reached ();
3474 write_enum_value (char *mem, int type, guint64 value)
3478 case MONO_TYPE_I1: {
3479 guint8 *p = (guint8*)mem;
3484 case MONO_TYPE_I2: {
3485 guint16 *p = (guint16 *)mem;
3490 case MONO_TYPE_I4: {
3491 guint32 *p = (guint32 *)mem;
3496 case MONO_TYPE_I8: {
3497 guint64 *p = (guint64 *)mem;
3502 g_assert_not_reached ();
3507 ICALL_EXPORT MonoObject *
3508 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3516 domain = mono_object_domain (enumType);
3517 enumc = mono_class_from_mono_type (enumType->type);
3519 mono_class_init_checked (enumc, &error);
3520 if (mono_error_set_pending_exception (&error))
3523 etype = mono_class_enum_basetype (enumc);
3525 res = mono_object_new_checked (domain, enumc, &error);
3526 if (mono_error_set_pending_exception (&error))
3528 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3533 ICALL_EXPORT MonoBoolean
3534 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3536 int size = mono_class_value_size (a->vtable->klass, NULL);
3537 guint64 a_val = 0, b_val = 0;
3539 memcpy (&a_val, mono_object_unbox (a), size);
3540 memcpy (&b_val, mono_object_unbox (b), size);
3542 return (a_val & b_val) == b_val;
3545 ICALL_EXPORT MonoObject *
3546 ves_icall_System_Enum_get_value (MonoObject *eobj)
3558 g_assert (eobj->vtable->klass->enumtype);
3560 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3561 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3562 if (mono_error_set_pending_exception (&error))
3564 dst = (char *)res + sizeof (MonoObject);
3565 src = (char *)eobj + sizeof (MonoObject);
3566 size = mono_class_value_size (enumc, NULL);
3568 memcpy (dst, src, size);
3573 ICALL_EXPORT MonoReflectionType *
3574 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3577 MonoReflectionType *ret;
3581 klass = mono_class_from_mono_type (type->type);
3582 mono_class_init_checked (klass, &error);
3583 if (mono_error_set_pending_exception (&error))
3586 etype = mono_class_enum_basetype (klass);
3588 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3592 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3593 mono_error_set_pending_exception (&error);
3599 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3601 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3602 gpointer odata = (char *)other + sizeof (MonoObject);
3603 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3604 g_assert (basetype);
3609 if (eobj->vtable->klass != other->vtable->klass)
3612 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3613 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3614 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3617 return me > other ? 1 : -1; \
3620 switch (basetype->type) {
3622 COMPARE_ENUM_VALUES (guint8);
3624 COMPARE_ENUM_VALUES (gint8);
3625 case MONO_TYPE_CHAR:
3627 COMPARE_ENUM_VALUES (guint16);
3629 COMPARE_ENUM_VALUES (gint16);
3631 COMPARE_ENUM_VALUES (guint32);
3633 COMPARE_ENUM_VALUES (gint32);
3635 COMPARE_ENUM_VALUES (guint64);
3637 COMPARE_ENUM_VALUES (gint64);
3641 #undef COMPARE_ENUM_VALUES
3642 /* indicates that the enum was of an unsupported unerlying type */
3647 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3649 gpointer data = (char *)eobj + sizeof (MonoObject);
3650 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3651 g_assert (basetype);
3653 switch (basetype->type) {
3654 case MONO_TYPE_I1: {
3655 gint8 value = *((gint8*)data);
3656 return ((int)value ^ (int)value << 8);
3659 return *((guint8*)data);
3660 case MONO_TYPE_CHAR:
3662 return *((guint16*)data);
3664 case MONO_TYPE_I2: {
3665 gint16 value = *((gint16*)data);
3666 return ((int)(guint16)value | (((int)value) << 16));
3669 return *((guint32*)data);
3671 return *((gint32*)data);
3673 case MONO_TYPE_I8: {
3674 gint64 value = *((gint64*)data);
3675 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3678 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3683 ICALL_EXPORT MonoBoolean
3684 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3687 MonoDomain *domain = mono_object_domain (type);
3688 MonoClass *enumc = mono_class_from_mono_type (type->type);
3689 guint j = 0, nvalues;
3691 MonoClassField *field;
3693 guint64 field_value, previous_value = 0;
3694 gboolean sorted = TRUE;
3696 mono_class_init_checked (enumc, &error);
3697 if (mono_error_set_pending_exception (&error))
3701 if (!enumc->enumtype) {
3702 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3706 base_type = mono_class_enum_basetype (enumc)->type;
3708 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3709 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3710 if (mono_error_set_pending_exception (&error))
3712 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3713 if (mono_error_set_pending_exception (&error))
3717 while ((field = mono_class_get_fields (enumc, &iter))) {
3719 MonoTypeEnum def_type;
3721 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3723 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3725 if (mono_field_is_deleted (field))
3727 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3729 p = mono_class_get_field_default_value (field, &def_type);
3730 /* len = */ mono_metadata_decode_blob_size (p, &p);
3732 field_value = read_enum_value (p, base_type);
3733 mono_array_set (*values, guint64, j, field_value);
3735 if (previous_value > field_value)
3738 previous_value = field_value;
3746 BFLAGS_IgnoreCase = 1,
3747 BFLAGS_DeclaredOnly = 2,
3748 BFLAGS_Instance = 4,
3750 BFLAGS_Public = 0x10,
3751 BFLAGS_NonPublic = 0x20,
3752 BFLAGS_FlattenHierarchy = 0x40,
3753 BFLAGS_InvokeMethod = 0x100,
3754 BFLAGS_CreateInstance = 0x200,
3755 BFLAGS_GetField = 0x400,
3756 BFLAGS_SetField = 0x800,
3757 BFLAGS_GetProperty = 0x1000,
3758 BFLAGS_SetProperty = 0x2000,
3759 BFLAGS_ExactBinding = 0x10000,
3760 BFLAGS_SuppressChangeType = 0x20000,
3761 BFLAGS_OptionalParamBinding = 0x40000
3764 ICALL_EXPORT MonoArray*
3765 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3769 MonoClass *startklass, *klass, *refklass;
3774 char *utf8_name = NULL;
3775 int (*compare_func) (const char *s1, const char *s2) = NULL;
3776 MonoClassField *field;
3777 MonoPtrArray tmp_array;
3779 domain = ((MonoObject *)type)->vtable->domain;
3780 if (type->type->byref) {
3781 MonoArray *result = mono_array_new_checked (domain, mono_defaults.field_info_class, 0, &error);
3782 mono_error_set_pending_exception (&error);
3786 klass = startklass = mono_class_from_mono_type (type->type);
3787 refklass = mono_class_from_mono_type (reftype->type);
3789 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3792 if (mono_class_has_failure (klass)) {
3793 mono_ptr_array_destroy (tmp_array);
3794 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3799 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3800 guint32 flags = mono_field_get_flags (field);
3802 if (mono_field_is_deleted_with_flags (field, flags))
3804 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3805 if (bflags & BFLAGS_Public)
3807 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3808 if (bflags & BFLAGS_NonPublic) {
3815 if (flags & FIELD_ATTRIBUTE_STATIC) {
3816 if (bflags & BFLAGS_Static)
3817 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3820 if (bflags & BFLAGS_Instance)
3828 if (utf8_name == NULL) {
3829 utf8_name = mono_string_to_utf8 (name);
3830 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3833 if (compare_func (mono_field_get_name (field), utf8_name))
3837 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3838 if (!mono_error_ok (&error))
3840 mono_ptr_array_append (tmp_array, member);
3842 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3845 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3847 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3848 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3850 mono_ptr_array_destroy (tmp_array);
3852 if (utf8_name != NULL)
3857 mono_ptr_array_destroy (tmp_array);
3858 mono_error_set_pending_exception (&error);
3863 method_nonpublic (MonoMethod* method, gboolean start_klass)
3865 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3866 case METHOD_ATTRIBUTE_ASSEM:
3867 return (start_klass || mono_defaults.generic_ilist_class);
3868 case METHOD_ATTRIBUTE_PRIVATE:
3870 case METHOD_ATTRIBUTE_PUBLIC:
3878 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3881 MonoClass *startklass;
3885 /*FIXME, use MonoBitSet*/
3886 guint32 method_slots_default [8];
3887 guint32 *method_slots = NULL;
3888 int (*compare_func) (const char *s1, const char *s2) = NULL;
3890 array = g_ptr_array_new ();
3895 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3897 /* An optimization for calls made from Delegate:CreateDelegate () */
3898 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3899 method = mono_get_delegate_invoke (klass);
3902 g_ptr_array_add (array, method);
3906 mono_class_setup_methods (klass);
3907 mono_class_setup_vtable (klass);
3908 if (mono_class_has_failure (klass))
3911 if (is_generic_parameter (&klass->byval_arg))
3912 nslots = mono_class_get_vtable_size (klass->parent);
3914 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3915 if (nslots >= sizeof (method_slots_default) * 8) {
3916 method_slots = g_new0 (guint32, nslots / 32 + 1);
3918 method_slots = method_slots_default;
3919 memset (method_slots, 0, sizeof (method_slots_default));
3922 mono_class_setup_methods (klass);
3923 mono_class_setup_vtable (klass);
3924 if (mono_class_has_failure (klass))
3928 while ((method = mono_class_get_methods (klass, &iter))) {
3930 if (method->slot != -1) {
3931 g_assert (method->slot < nslots);
3932 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3934 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3935 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3938 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3940 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3941 if (bflags & BFLAGS_Public)
3943 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3949 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3950 if (bflags & BFLAGS_Static)
3951 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3954 if (bflags & BFLAGS_Instance)
3962 if (compare_func (name, method->name))
3967 g_ptr_array_add (array, method);
3969 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3971 if (method_slots != method_slots_default)
3972 g_free (method_slots);
3977 if (method_slots != method_slots_default)
3978 g_free (method_slots);
3979 g_ptr_array_free (array, TRUE);
3981 if (mono_class_has_failure (klass)) {
3982 *ex = mono_class_get_exception_for_failure (klass);
3984 *ex = mono_get_exception_execution_engine ("Unknown error");
3989 ICALL_EXPORT MonoArray*
3990 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3992 static MonoClass *MethodInfo_array;
3996 MonoVTable *array_vtable;
3997 MonoException *ex = NULL;
3998 const char *mname = NULL;
3999 GPtrArray *method_array;
4000 MonoClass *klass, *refklass;
4003 mono_error_init (&error);
4005 if (!MethodInfo_array) {
4006 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
4007 mono_memory_barrier ();
4008 MethodInfo_array = klass;
4011 klass = mono_class_from_mono_type (type->type);
4012 refklass = mono_class_from_mono_type (reftype->type);
4013 domain = ((MonoObject *)type)->vtable->domain;
4014 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
4015 if (!is_ok (&error)) {
4016 mono_error_set_pending_exception (&error);
4019 if (type->type->byref) {
4020 res = mono_array_new_specific_checked (array_vtable, 0, &error);
4021 mono_error_set_pending_exception (&error);
4027 mname = mono_string_to_utf8 (name);
4029 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
4030 g_free ((char*)mname);
4032 mono_set_pending_exception (ex);
4036 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
4037 if (!mono_error_ok (&error)) {
4038 mono_error_set_pending_exception (&error);
4042 for (i = 0; i < method_array->len; ++i) {
4043 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
4044 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
4045 if (!mono_error_ok (&error))
4047 mono_array_setref (res, i, rm);
4051 g_ptr_array_free (method_array, TRUE);
4052 if (!mono_error_ok (&error))
4053 mono_set_pending_exception (mono_error_convert_to_exception (&error));
4057 ICALL_EXPORT MonoArray*
4058 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4061 MonoClass *startklass, *klass, *refklass;
4066 gpointer iter = NULL;
4067 MonoPtrArray tmp_array;
4070 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
4072 domain = ((MonoObject *)type)->vtable->domain;
4073 if (type->type->byref)
4074 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
4075 klass = startklass = mono_class_from_mono_type (type->type);
4076 refklass = mono_class_from_mono_type (reftype->type);
4078 mono_class_setup_methods (klass);
4079 if (mono_class_has_failure (klass)) {
4080 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
4085 while ((method = mono_class_get_methods (klass, &iter))) {
4087 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
4089 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4090 if (bflags & BFLAGS_Public)
4093 if (bflags & BFLAGS_NonPublic)
4099 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4100 if (bflags & BFLAGS_Static)
4101 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4104 if (bflags & BFLAGS_Instance)
4110 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
4111 if (!mono_error_ok (&error)) {
4112 mono_error_set_pending_exception (&error);
4116 mono_ptr_array_append (tmp_array, member);
4119 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
4121 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4122 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4124 mono_ptr_array_destroy (tmp_array);
4130 property_hash (gconstpointer data)
4132 MonoProperty *prop = (MonoProperty*)data;
4134 return g_str_hash (prop->name);
4138 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
4140 if (method1->is_inflated)
4141 method1 = ((MonoMethodInflated*) method1)->declaring;
4142 if (method2->is_inflated)
4143 method2 = ((MonoMethodInflated*) method2)->declaring;
4145 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4149 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4151 // Properties are hide-by-name-and-signature
4152 if (!g_str_equal (prop1->name, prop2->name))
4155 /* If we see a property in a generic method, we want to
4156 compare the generic signatures, not the inflated signatures
4157 because we might conflate two properties that were
4161 public T this[T t] { getter { return t; } } // method 1
4162 public U this[U u] { getter { return u; } } // method 2
4165 If we see int Foo<int,int>::Item[int] we need to know if
4166 the indexer came from method 1 or from method 2, and we
4167 shouldn't conflate them. (Bugzilla 36283)
4169 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
4172 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4179 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4184 return method_nonpublic (accessor, start_klass);
4187 ICALL_EXPORT MonoArray*
4188 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4192 MonoClass *startklass, *klass;
4198 gchar *propname = NULL;
4199 int (*compare_func) (const char *s1, const char *s2) = NULL;
4201 GHashTable *properties = NULL;
4202 MonoPtrArray tmp_array;
4204 mono_error_init (&error);
4206 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4208 domain = ((MonoObject *)type)->vtable->domain;
4209 if (type->type->byref)
4210 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
4211 klass = startklass = mono_class_from_mono_type (type->type);
4214 propname = mono_string_to_utf8 (name);
4215 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4218 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4220 mono_class_setup_methods (klass);
4221 mono_class_setup_vtable (klass);
4222 if (mono_class_has_failure (klass))
4226 while ((prop = mono_class_get_properties (klass, &iter))) {
4232 flags = method->flags;
4235 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4236 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4237 if (bflags & BFLAGS_Public)
4239 } else if (bflags & BFLAGS_NonPublic) {
4240 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4241 property_accessor_nonpublic(prop->set, startklass == klass)) {
4248 if (flags & METHOD_ATTRIBUTE_STATIC) {
4249 if (bflags & BFLAGS_Static)
4250 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4253 if (bflags & BFLAGS_Instance)
4262 if (compare_func (propname, prop->name))
4266 if (g_hash_table_lookup (properties, prop))
4269 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4272 mono_ptr_array_append (tmp_array, pr);
4274 g_hash_table_insert (properties, prop, prop);
4276 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4279 g_hash_table_destroy (properties);
4282 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4283 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4284 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4286 mono_ptr_array_destroy (tmp_array);
4293 if (mono_class_has_failure (klass)) {
4294 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4299 g_hash_table_destroy (properties);
4302 mono_ptr_array_destroy (tmp_array);
4304 mono_error_set_pending_exception (&error);
4310 event_hash (gconstpointer data)
4312 MonoEvent *event = (MonoEvent*)data;
4314 return g_str_hash (event->name);
4318 event_equal (MonoEvent *event1, MonoEvent *event2)
4320 // Events are hide-by-name
4321 return g_str_equal (event1->name, event2->name);
4324 ICALL_EXPORT MonoArray*
4325 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4329 MonoClass *startklass, *klass;
4335 char *utf8_name = NULL;
4336 int (*compare_func) (const char *s1, const char *s2) = NULL;
4337 GHashTable *events = NULL;
4338 MonoPtrArray tmp_array;
4340 mono_error_init (&error);
4342 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4344 domain = mono_object_domain (type);
4345 if (type->type->byref)
4346 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4347 klass = startklass = mono_class_from_mono_type (type->type);
4349 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4351 mono_class_setup_methods (klass);
4352 mono_class_setup_vtable (klass);
4353 if (mono_class_has_failure (klass))
4357 while ((event = mono_class_get_events (klass, &iter))) {
4359 method = event->add;
4361 method = event->remove;
4363 method = event->raise;
4365 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4366 if (bflags & BFLAGS_Public)
4368 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4369 if (bflags & BFLAGS_NonPublic)
4374 if (bflags & BFLAGS_NonPublic)
4380 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4381 if (bflags & BFLAGS_Static)
4382 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4385 if (bflags & BFLAGS_Instance)
4390 if (bflags & BFLAGS_Instance)
4396 if (utf8_name == NULL) {
4397 utf8_name = mono_string_to_utf8 (name);
4398 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4401 if (compare_func (event->name, utf8_name))
4405 if (g_hash_table_lookup (events, event))
4408 MonoReflectionEvent *ev_obj;
4409 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4412 mono_ptr_array_append (tmp_array, ev_obj);
4414 g_hash_table_insert (events, event, event);
4416 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4419 g_hash_table_destroy (events);
4421 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4423 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4424 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4426 mono_ptr_array_destroy (tmp_array);
4428 if (utf8_name != NULL)
4434 if (mono_class_has_failure (klass)) {
4435 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4441 g_hash_table_destroy (events);
4442 if (utf8_name != NULL)
4445 mono_ptr_array_destroy (tmp_array);
4447 mono_error_set_pending_exception (&error);
4451 ICALL_EXPORT MonoArray*
4452 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4455 MonoReflectionType *rt;
4458 MonoArray *res = NULL;
4463 MonoPtrArray tmp_array;
4465 mono_error_init (&error);
4467 domain = ((MonoObject *)type)->vtable->domain;
4468 if (type->type->byref) {
4469 MonoArray *result = mono_array_new_checked (domain, mono_defaults.monotype_class, 0, &error);
4470 mono_error_set_pending_exception (&error);
4473 klass = mono_class_from_mono_type (type->type);
4476 * If a nested type is generic, return its generic type definition.
4477 * Note that this means that the return value is essentially the set
4478 * of nested types of the generic type definition of @klass.
4480 * A note in MSDN claims that a generic type definition can have
4481 * nested types that aren't generic. In any case, the container of that
4482 * nested type would be the generic type definition.
4484 if (klass->generic_class)
4485 klass = klass->generic_class->container_class;
4487 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4489 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4491 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4492 if (bflags & BFLAGS_Public)
4495 if (bflags & BFLAGS_NonPublic)
4503 str = mono_string_to_utf8 (name);
4504 mono_identifier_unescape_type_name_chars (str);
4507 if (strcmp (nested->name, str))
4511 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4512 if (!is_ok (&error))
4515 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4518 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4520 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4521 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4524 mono_ptr_array_destroy (tmp_array);
4528 mono_error_set_pending_exception (&error);
4532 ICALL_EXPORT MonoReflectionType*
4533 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4536 MonoReflectionType *ret;
4538 MonoType *type = NULL;
4539 MonoTypeNameParse info;
4540 gboolean type_resolve;
4542 /* On MS.NET, this does not fire a TypeResolve event */
4543 type_resolve = TRUE;
4544 str = mono_string_to_utf8 (name);
4545 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4546 if (!mono_reflection_parse_type (str, &info)) {
4548 mono_reflection_free_type_info (&info);
4550 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4553 /*g_print ("failed parse\n");*/
4557 if (info.assembly.name) {
4559 mono_reflection_free_type_info (&info);
4561 /* 1.0 and 2.0 throw different exceptions */
4562 if (mono_defaults.generic_ilist_class)
4563 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4565 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4571 if (module != NULL) {
4572 if (module->image) {
4573 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4574 if (!is_ok (&error)) {
4576 mono_reflection_free_type_info (&info);
4577 mono_error_set_pending_exception (&error);
4584 if (assembly_is_dynamic (assembly->assembly)) {
4585 /* Enumerate all modules */
4586 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4590 if (abuilder->modules) {
4591 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4592 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4593 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4594 if (!is_ok (&error)) {
4596 mono_reflection_free_type_info (&info);
4597 mono_error_set_pending_exception (&error);
4605 if (!type && abuilder->loaded_modules) {
4606 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4607 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4608 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4609 if (!is_ok (&error)) {
4611 mono_reflection_free_type_info (&info);
4612 mono_error_set_pending_exception (&error);
4621 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4622 if (!is_ok (&error)) {
4624 mono_reflection_free_type_info (&info);
4625 mono_error_set_pending_exception (&error);
4630 mono_reflection_free_type_info (&info);
4632 MonoException *e = NULL;
4635 e = mono_get_exception_type_load (name, NULL);
4638 mono_set_pending_exception (e);
4642 if (type->type == MONO_TYPE_CLASS) {
4643 MonoClass *klass = mono_type_get_class (type);
4645 /* need to report exceptions ? */
4646 if (throwOnError && mono_class_has_failure (klass)) {
4647 /* report SecurityException (or others) that occured when loading the assembly */
4648 MonoException *exc = mono_class_get_exception_for_failure (klass);
4649 mono_set_pending_exception (exc);
4654 /* g_print ("got it\n"); */
4655 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4656 mono_error_set_pending_exception (&error);
4662 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4665 gchar *shadow_ini_file;
4668 /* Check for shadow-copied assembly */
4669 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4670 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4672 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4673 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4679 g_free (shadow_ini_file);
4680 if (content != NULL) {
4683 *filename = content;
4690 ICALL_EXPORT MonoString *
4691 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4693 MonoDomain *domain = mono_object_domain (assembly);
4694 MonoAssembly *mass = assembly->assembly;
4695 MonoString *res = NULL;
4700 if (g_path_is_absolute (mass->image->name)) {
4701 absolute = g_strdup (mass->image->name);
4702 dirname = g_path_get_dirname (absolute);
4704 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4705 dirname = g_strdup (mass->basedir);
4708 replace_shadow_path (domain, dirname, &absolute);
4713 for (i = strlen (absolute) - 1; i >= 0; i--)
4714 if (absolute [i] == '\\')
4719 uri = g_filename_to_uri (absolute, NULL, NULL);
4721 const char *prepend = "file://";
4723 if (*absolute == '/' && *(absolute + 1) == '/') {
4726 prepend = "file:///";
4729 uri = g_strconcat (prepend, absolute, NULL);
4733 res = mono_string_new (domain, uri);
4740 ICALL_EXPORT MonoBoolean
4741 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4743 MonoAssembly *mass = assembly->assembly;
4745 return mass->in_gac;
4748 ICALL_EXPORT MonoReflectionAssembly*
4749 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4754 MonoImageOpenStatus status;
4755 MonoReflectionAssembly* result = NULL;
4757 name = mono_string_to_utf8 (mname);
4758 res = mono_assembly_load_with_partial_name (name, &status);
4764 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4766 mono_error_set_pending_exception (&error);
4770 ICALL_EXPORT MonoString *
4771 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4773 MonoDomain *domain = mono_object_domain (assembly);
4776 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4781 ICALL_EXPORT MonoBoolean
4782 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4784 return assembly->assembly->ref_only;
4787 ICALL_EXPORT MonoString *
4788 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4790 MonoDomain *domain = mono_object_domain (assembly);
4792 return mono_string_new (domain, assembly->assembly->image->version);
4795 ICALL_EXPORT MonoReflectionMethod*
4796 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4799 MonoReflectionMethod *res = NULL;
4802 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4806 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4807 if (!mono_error_ok (&error))
4810 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4813 if (!mono_error_ok (&error))
4814 mono_error_set_pending_exception (&error);
4818 ICALL_EXPORT MonoReflectionModule*
4819 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4822 MonoReflectionModule *result = NULL;
4823 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4824 if (!mono_error_ok (&error))
4825 mono_error_set_pending_exception (&error);
4829 ICALL_EXPORT MonoArray*
4830 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4833 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4834 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4835 if (mono_error_set_pending_exception (&error))
4840 for (i = 0; i < table->rows; ++i) {
4841 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4842 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4848 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4850 static MonoMethod *create_version = NULL;
4854 mono_error_init (error);
4857 if (!create_version) {
4858 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4859 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4860 g_assert (create_version);
4861 mono_method_desc_free (desc);
4867 args [3] = &revision;
4868 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4869 return_val_if_nok (error, NULL);
4871 mono_runtime_invoke_checked (create_version, result, args, error);
4872 return_val_if_nok (error, NULL);
4877 ICALL_EXPORT MonoArray*
4878 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4882 MonoDomain *domain = mono_object_domain (assembly);
4884 static MonoMethod *create_culture = NULL;
4885 MonoImage *image = assembly->assembly->image;
4889 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4892 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4893 if (mono_error_set_pending_exception (&error))
4897 if (count > 0 && !create_culture) {
4898 MonoMethodDesc *desc = mono_method_desc_new (
4899 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4900 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4901 g_assert (create_culture);
4902 mono_method_desc_free (desc);
4905 for (i = 0; i < count; i++) {
4906 MonoObject *version;
4907 MonoReflectionAssemblyName *aname;
4908 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4910 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4912 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4913 domain, mono_class_get_assembly_name_class (), &error);
4914 if (mono_error_set_pending_exception (&error))
4917 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4919 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4920 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4921 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4922 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4923 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4924 aname->versioncompat = 1; /* SameMachine (default) */
4925 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4927 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4928 if (mono_error_set_pending_exception (&error))
4931 MONO_OBJECT_SETREF (aname, version, version);
4933 if (create_culture) {
4935 MonoBoolean assembly_ref = 1;
4936 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4937 args [1] = &assembly_ref;
4939 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4940 if (mono_error_set_pending_exception (&error))
4943 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4946 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4947 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4948 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4950 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4951 /* public key token isn't copied - the class library will
4952 automatically generate it from the public key if required */
4953 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4954 if (mono_error_set_pending_exception (&error))
4957 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4958 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4960 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4961 if (mono_error_set_pending_exception (&error))
4964 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4965 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
4968 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
4969 if (mono_error_set_pending_exception (&error))
4972 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4975 /* note: this function doesn't return the codebase on purpose (i.e. it can
4976 be used under partial trust as path information isn't present). */
4978 mono_array_setref (result, i, aname);
4983 /* move this in some file in mono/util/ */
4985 g_concat_dir_and_file (const char *dir, const char *file)
4987 g_return_val_if_fail (dir != NULL, NULL);
4988 g_return_val_if_fail (file != NULL, NULL);
4991 * If the directory name doesn't have a / on the end, we need
4992 * to add one so we get a proper path to the file
4994 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4995 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4997 return g_strconcat (dir, file, NULL);
5001 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
5004 char *n = mono_string_to_utf8 (name);
5005 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5007 guint32 cols [MONO_MANIFEST_SIZE];
5008 guint32 impl, file_idx;
5012 for (i = 0; i < table->rows; ++i) {
5013 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5014 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5015 if (strcmp (val, n) == 0)
5019 if (i == table->rows)
5022 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
5025 * this code should only be called after obtaining the
5026 * ResourceInfo and handling the other cases.
5028 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
5029 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
5031 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
5036 module = assembly->assembly->image;
5039 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
5040 if (mono_error_set_pending_exception (&error))
5042 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
5044 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
5047 ICALL_EXPORT gboolean
5048 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
5051 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5053 guint32 cols [MONO_MANIFEST_SIZE];
5054 guint32 file_cols [MONO_FILE_SIZE];
5058 n = mono_string_to_utf8 (name);
5059 for (i = 0; i < table->rows; ++i) {
5060 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5061 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5062 if (strcmp (val, n) == 0)
5066 if (i == table->rows)
5069 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
5070 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
5073 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
5074 case MONO_IMPLEMENTATION_FILE:
5075 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5076 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5077 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
5078 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
5079 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
5080 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
5083 info->location = RESOURCE_LOCATION_EMBEDDED;
5086 case MONO_IMPLEMENTATION_ASSEMBLYREF:
5087 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5088 mono_assembly_load_reference (assembly->assembly->image, i - 1);
5089 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
5090 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
5091 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
5093 mono_set_pending_exception (ex);
5096 MonoReflectionAssembly *assm_obj;
5097 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5099 mono_error_set_pending_exception (&error);
5102 MONO_OBJECT_SETREF (info, assembly, assm_obj);
5104 /* Obtain info recursively */
5105 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5106 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5109 case MONO_IMPLEMENTATION_EXP_TYPE:
5110 g_assert_not_reached ();
5118 ICALL_EXPORT MonoObject*
5119 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
5122 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5123 MonoArray *result = NULL;
5128 /* check hash if needed */
5130 n = mono_string_to_utf8 (name);
5131 for (i = 0; i < table->rows; ++i) {
5132 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5133 if (strcmp (val, n) == 0) {
5136 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5137 fn = mono_string_new (mono_object_domain (assembly), n);
5139 return (MonoObject*)fn;
5147 for (i = 0; i < table->rows; ++i) {
5148 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5152 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
5153 if (mono_error_set_pending_exception (&error))
5158 for (i = 0; i < table->rows; ++i) {
5159 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5160 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5161 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5162 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5167 return (MonoObject*)result;
5170 ICALL_EXPORT MonoArray*
5171 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5174 MonoDomain *domain = mono_domain_get();
5177 int i, j, file_count = 0;
5178 MonoImage **modules;
5179 guint32 module_count, real_module_count;
5180 MonoTableInfo *table;
5181 guint32 cols [MONO_FILE_SIZE];
5182 MonoImage *image = assembly->assembly->image;
5184 g_assert (image != NULL);
5185 g_assert (!assembly_is_dynamic (assembly->assembly));
5187 table = &image->tables [MONO_TABLE_FILE];
5188 file_count = table->rows;
5190 modules = image->modules;
5191 module_count = image->module_count;
5193 real_module_count = 0;
5194 for (i = 0; i < module_count; ++i)
5196 real_module_count ++;
5198 klass = mono_class_get_module_class ();
5199 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5200 if (mono_error_set_pending_exception (&error))
5203 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5204 if (mono_error_set_pending_exception (&error))
5207 mono_array_setref (res, 0, image_obj);
5209 for (i = 0; i < module_count; ++i)
5211 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5212 if (mono_error_set_pending_exception (&error))
5214 mono_array_setref (res, j, rm);
5218 for (i = 0; i < file_count; ++i, ++j) {
5219 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5220 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5221 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5222 if (mono_error_set_pending_exception (&error))
5224 mono_array_setref (res, j, rm);
5227 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5229 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5230 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5233 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5234 if (mono_error_set_pending_exception (&error))
5236 mono_array_setref (res, j, rm);
5243 ICALL_EXPORT MonoReflectionMethod*
5244 ves_icall_GetCurrentMethod (void)
5246 MonoReflectionMethod *res = NULL;
5249 MonoMethod *m = mono_method_get_last_managed ();
5252 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5256 while (m->is_inflated)
5257 m = ((MonoMethodInflated*)m)->declaring;
5259 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5260 mono_error_set_pending_exception (&error);
5266 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5269 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5272 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5273 //method is inflated, we should inflate it on the other class
5274 MonoGenericContext ctx;
5275 ctx.method_inst = inflated->context.method_inst;
5276 ctx.class_inst = inflated->context.class_inst;
5277 if (klass->generic_class)
5278 ctx.class_inst = klass->generic_class->context.class_inst;
5279 else if (klass->generic_container)
5280 ctx.class_inst = klass->generic_container->context.class_inst;
5281 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5282 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5286 mono_class_setup_methods (method->klass);
5287 if (mono_class_has_failure (method->klass))
5289 for (i = 0; i < method->klass->method.count; ++i) {
5290 if (method->klass->methods [i] == method) {
5295 mono_class_setup_methods (klass);
5296 if (mono_class_has_failure (klass))
5298 g_assert (offset >= 0 && offset < klass->method.count);
5299 return klass->methods [offset];
5302 ICALL_EXPORT MonoReflectionMethod*
5303 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5305 MonoReflectionMethod *res = NULL;
5309 klass = mono_class_from_mono_type (type);
5310 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5312 if (method->klass != klass) {
5313 method = mono_method_get_equivalent_method (method, klass);
5318 klass = method->klass;
5319 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5320 mono_error_set_pending_exception (&error);
5324 ICALL_EXPORT MonoReflectionMethodBody*
5325 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5328 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5329 mono_error_set_pending_exception (&error);
5333 ICALL_EXPORT MonoReflectionAssembly*
5334 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5337 MonoReflectionAssembly *result;
5338 MonoMethod *dest = NULL;
5340 mono_stack_walk_no_il (get_executing, &dest);
5342 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5344 mono_error_set_pending_exception (&error);
5349 ICALL_EXPORT MonoReflectionAssembly*
5350 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5353 MonoReflectionAssembly *result;
5354 MonoDomain* domain = mono_domain_get ();
5356 if (!domain->entry_assembly)
5359 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5361 mono_error_set_pending_exception (&error);
5365 ICALL_EXPORT MonoReflectionAssembly*
5366 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5371 MonoReflectionAssembly *result;
5374 mono_stack_walk_no_il (get_executing, &dest);
5376 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5380 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5383 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5385 mono_error_set_pending_exception (&error);
5389 ICALL_EXPORT MonoString *
5390 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5391 gboolean assembly_qualified)
5393 MonoDomain *domain = mono_object_domain (object);
5394 MonoTypeNameFormat format;
5399 format = assembly_qualified ?
5400 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5401 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5403 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5405 name = mono_type_get_name_full (object->type, format);
5409 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5414 res = mono_string_new (domain, name);
5421 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5424 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5426 mono_class_init_checked (klass, &error);
5427 mono_error_set_pending_exception (&error);
5428 return mono_security_core_clr_class_level (klass);
5432 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5434 MonoClassField *field = rfield->field;
5435 return mono_security_core_clr_field_level (field, TRUE);
5439 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5441 MonoMethod *method = rfield->method;
5442 return mono_security_core_clr_method_level (method, TRUE);
5446 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)
5448 static MonoMethod *create_culture = NULL;
5452 const char *pkey_ptr;
5454 MonoBoolean assembly_ref = 0;
5456 mono_error_init (error);
5458 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5459 aname->major = name->major;
5460 aname->minor = name->minor;
5461 aname->build = name->build;
5462 aname->flags = name->flags;
5463 aname->revision = name->revision;
5464 aname->hashalg = name->hash_alg;
5465 aname->versioncompat = 1; /* SameMachine (default) */
5466 aname->processor_architecture = name->arch;
5468 if (by_default_version) {
5469 MonoObject *version;
5471 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5472 return_if_nok (error);
5474 MONO_OBJECT_SETREF (aname, version, version);
5478 if (absolute != NULL && *absolute != '\0') {
5479 const gchar *prepend = "file://";
5482 codebase = g_strdup (absolute);
5487 for (i = strlen (codebase) - 1; i >= 0; i--)
5488 if (codebase [i] == '\\')
5491 if (*codebase == '/' && *(codebase + 1) == '/') {
5494 prepend = "file:///";
5498 result = g_strconcat (prepend, codebase, NULL);
5504 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5508 if (!create_culture) {
5509 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5510 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5511 g_assert (create_culture);
5512 mono_method_desc_free (desc);
5515 if (name->culture) {
5516 args [0] = mono_string_new (domain, name->culture);
5517 args [1] = &assembly_ref;
5519 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5520 return_if_nok (error);
5522 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5525 if (name->public_key) {
5526 pkey_ptr = (char*)name->public_key;
5527 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5529 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5530 return_if_nok (error);
5531 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5532 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5533 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5534 } else if (default_publickey) {
5535 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5536 return_if_nok (error);
5537 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5538 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5541 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5542 if (name->public_key_token [0]) {
5546 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5547 return_if_nok (error);
5549 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5550 p = mono_array_addr (keyToken, char, 0);
5552 for (i = 0, j = 0; i < 8; i++) {
5553 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5554 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5557 } else if (default_token) {
5558 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5559 return_if_nok (error);
5560 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5564 ICALL_EXPORT MonoString *
5565 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5567 MonoDomain *domain = mono_object_domain (assembly);
5568 MonoAssembly *mass = assembly->assembly;
5572 name = mono_stringify_assembly_name (&mass->aname);
5573 res = mono_string_new (domain, name);
5580 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5584 MonoAssembly *mass = assembly->assembly;
5586 if (g_path_is_absolute (mass->image->name)) {
5587 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5588 mono_error_set_pending_exception (&error);
5591 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5593 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5594 mono_error_set_pending_exception (&error);
5600 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5604 MonoImageOpenStatus status = MONO_IMAGE_OK;
5607 MonoAssemblyName name;
5610 filename = mono_string_to_utf8 (fname);
5612 dirname = g_path_get_dirname (filename);
5613 replace_shadow_path (mono_domain_get (), dirname, &filename);
5616 image = mono_image_open (filename, &status);
5622 if (status == MONO_IMAGE_IMAGE_INVALID)
5623 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5625 exc = mono_get_exception_file_not_found2 (NULL, fname);
5626 mono_set_pending_exception (exc);
5630 res = mono_assembly_fill_assembly_name (image, &name);
5632 mono_image_close (image);
5634 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5638 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5639 mono_error_set_pending_exception (&error);
5641 mono_image_close (image);
5645 ICALL_EXPORT MonoBoolean
5646 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5647 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5649 MonoBoolean result = FALSE;
5650 MonoDeclSecurityEntry entry;
5652 /* SecurityAction.RequestMinimum */
5653 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5654 *minimum = entry.blob;
5655 *minLength = entry.size;
5658 /* SecurityAction.RequestOptional */
5659 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5660 *optional = entry.blob;
5661 *optLength = entry.size;
5664 /* SecurityAction.RequestRefuse */
5665 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5666 *refused = entry.blob;
5667 *refLength = entry.size;
5675 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5677 guint32 attrs, visibility;
5679 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5680 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5681 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5684 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5690 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5692 MonoReflectionType *rt;
5695 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5698 mono_error_init (error);
5700 /* we start the count from 1 because we skip the special type <Module> */
5703 for (i = 1; i < tdef->rows; ++i) {
5704 if (mono_module_type_is_visible (tdef, image, i + 1))
5708 count = tdef->rows - 1;
5710 res = mono_array_new_checked (domain, mono_defaults.monotype_class, count, error);
5711 return_val_if_nok (error, NULL);
5712 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5713 return_val_if_nok (error, NULL);
5715 for (i = 1; i < tdef->rows; ++i) {
5716 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5717 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5720 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5721 return_val_if_nok (error, NULL);
5723 mono_array_setref (res, count, rt);
5725 MonoException *ex = mono_error_convert_to_exception (error);
5726 mono_array_setref (*exceptions, count, ex);
5735 ICALL_EXPORT MonoArray*
5736 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5739 MonoArray *res = NULL;
5740 MonoArray *exceptions = NULL;
5741 MonoImage *image = NULL;
5742 MonoTableInfo *table = NULL;
5745 int i, len, ex_count;
5747 domain = mono_object_domain (assembly);
5749 g_assert (!assembly_is_dynamic (assembly->assembly));
5750 image = assembly->assembly->image;
5751 table = &image->tables [MONO_TABLE_FILE];
5752 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5753 if (mono_error_set_pending_exception (&error))
5756 /* Append data from all modules in the assembly */
5757 for (i = 0; i < table->rows; ++i) {
5758 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5759 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5764 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5765 if (mono_error_set_pending_exception (&error))
5769 /* Append the new types to the end of the array */
5770 if (mono_array_length (res2) > 0) {
5772 MonoArray *res3, *ex3;
5774 len1 = mono_array_length (res);
5775 len2 = mono_array_length (res2);
5777 res3 = mono_array_new_checked (domain, mono_defaults.monotype_class, len1 + len2, &error);
5778 if (mono_error_set_pending_exception (&error))
5780 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5781 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5784 ex3 = mono_array_new_checked (domain, mono_defaults.monotype_class, len1 + len2, &error);
5785 if (mono_error_set_pending_exception (&error))
5787 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5788 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5795 /* the ReflectionTypeLoadException must have all the types (Types property),
5796 * NULL replacing types which throws an exception. The LoaderException must
5797 * contain all exceptions for NULL items.
5800 len = mono_array_length (res);
5803 for (i = 0; i < len; i++) {
5804 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5808 klass = mono_type_get_class (t->type);
5809 if ((klass != NULL) && mono_class_has_failure (klass)) {
5810 /* keep the class in the list */
5811 list = g_list_append (list, klass);
5812 /* and replace Type with NULL */
5813 mono_array_setref (res, i, NULL);
5820 if (list || ex_count) {
5822 MonoException *exc = NULL;
5823 MonoArray *exl = NULL;
5824 int j, length = g_list_length (list) + ex_count;
5826 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5827 if (mono_error_set_pending_exception (&error)) {
5831 /* Types for which mono_class_get_checked () succeeded */
5832 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5833 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5834 mono_array_setref (exl, i, exc);
5836 /* Types for which it don't */
5837 for (j = 0; j < mono_array_length (exceptions); ++j) {
5838 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5840 g_assert (i < length);
5841 mono_array_setref (exl, i, exc);
5848 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5849 if (!is_ok (&error)) {
5850 mono_error_set_pending_exception (&error);
5853 mono_set_pending_exception (exc);
5860 ICALL_EXPORT gboolean
5861 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5864 MonoAssemblyName aname;
5865 MonoDomain *domain = mono_object_domain (name);
5867 gboolean is_version_defined;
5868 gboolean is_token_defined;
5870 aname.public_key = NULL;
5871 val = mono_string_to_utf8 (assname);
5872 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5873 g_free ((guint8*) aname.public_key);
5878 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5879 mono_error_set_pending_exception (&error);
5881 mono_assembly_name_free (&aname);
5882 g_free ((guint8*) aname.public_key);
5888 ICALL_EXPORT MonoReflectionType*
5889 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5892 MonoReflectionType *ret;
5893 MonoDomain *domain = mono_object_domain (module);
5896 g_assert (module->image);
5898 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5899 /* These images do not have a global type */
5902 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5903 if (!mono_error_ok (&error)) {
5904 mono_error_set_pending_exception (&error);
5908 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5909 if (!mono_error_ok (&error)) {
5910 mono_error_set_pending_exception (&error);
5918 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5920 /*if (module->image)
5921 mono_image_close (module->image);*/
5924 ICALL_EXPORT MonoString*
5925 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5927 MonoDomain *domain = mono_object_domain (module);
5929 g_assert (module->image);
5930 return mono_string_new (domain, module->image->guid);
5933 ICALL_EXPORT gpointer
5934 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5937 if (module->image && module->image->is_module_handle)
5938 return module->image->raw_data;
5941 return (gpointer) (-1);
5945 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5947 if (image_is_dynamic (image)) {
5948 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5949 *pe_kind = dyn->pe_kind;
5950 *machine = dyn->machine;
5953 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5954 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5959 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5961 return (image->md_version_major << 16) | (image->md_version_minor);
5964 ICALL_EXPORT MonoArray*
5965 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5968 MonoArray *exceptions;
5971 if (!module->image) {
5972 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.monotype_class, 0, &error);
5973 mono_error_set_pending_exception (&error);
5978 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5979 if (mono_error_set_pending_exception (&error))
5982 for (i = 0; i < mono_array_length (exceptions); ++i) {
5983 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5985 mono_set_pending_exception (ex);
5994 mono_memberref_is_method (MonoImage *image, guint32 token)
5996 if (!image_is_dynamic (image)) {
5997 guint32 cols [MONO_MEMBERREF_SIZE];
5999 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
6000 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
6001 mono_metadata_decode_blob_size (sig, &sig);
6002 return (*sig != 0x6);
6005 MonoClass *handle_class;
6007 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
6008 mono_error_cleanup (&error); /* just probing, ignore error */
6012 return mono_defaults.methodhandle_class == handle_class;
6017 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
6020 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
6021 mono_array_addr (type_args, MonoType*, 0));
6023 context->class_inst = NULL;
6025 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
6026 mono_array_addr (method_args, MonoType*, 0));
6028 context->method_inst = NULL;
6031 ICALL_EXPORT MonoType*
6032 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6035 int table = mono_metadata_token_table (token);
6036 int index = mono_metadata_token_index (token);
6037 MonoGenericContext context;
6040 *resolve_error = ResolveTokenError_Other;
6042 /* Validate token */
6043 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
6044 (table != MONO_TABLE_TYPESPEC)) {
6045 *resolve_error = ResolveTokenError_BadTable;
6049 if (image_is_dynamic (image)) {
6050 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
6051 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6052 mono_error_cleanup (&error);
6053 return klass ? &klass->byval_arg : NULL;
6056 init_generic_context_from_args (&context, type_args, method_args);
6057 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6058 mono_error_cleanup (&error);
6059 return klass ? &klass->byval_arg : NULL;
6062 if ((index <= 0) || (index > image->tables [table].rows)) {
6063 *resolve_error = ResolveTokenError_OutOfRange;
6067 init_generic_context_from_args (&context, type_args, method_args);
6068 klass = mono_class_get_checked (image, token, &error);
6070 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
6071 if (!mono_error_ok (&error)) {
6072 mono_error_set_pending_exception (&error);
6077 return &klass->byval_arg;
6082 ICALL_EXPORT MonoMethod*
6083 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6086 int table = mono_metadata_token_table (token);
6087 int index = mono_metadata_token_index (token);
6088 MonoGenericContext context;
6091 *resolve_error = ResolveTokenError_Other;
6093 /* Validate token */
6094 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
6095 (table != MONO_TABLE_MEMBERREF)) {
6096 *resolve_error = ResolveTokenError_BadTable;
6100 if (image_is_dynamic (image)) {
6101 if (table == MONO_TABLE_METHOD) {
6102 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6103 mono_error_cleanup (&error);
6107 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
6108 *resolve_error = ResolveTokenError_BadTable;
6112 init_generic_context_from_args (&context, type_args, method_args);
6113 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6114 mono_error_cleanup (&error);
6118 if ((index <= 0) || (index > image->tables [table].rows)) {
6119 *resolve_error = ResolveTokenError_OutOfRange;
6122 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6123 *resolve_error = ResolveTokenError_BadTable;
6127 init_generic_context_from_args (&context, type_args, method_args);
6128 method = mono_get_method_checked (image, token, NULL, &context, &error);
6129 mono_error_set_pending_exception (&error);
6134 ICALL_EXPORT MonoString*
6135 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6138 int index = mono_metadata_token_index (token);
6140 *resolve_error = ResolveTokenError_Other;
6142 /* Validate token */
6143 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6144 *resolve_error = ResolveTokenError_BadTable;
6148 if (image_is_dynamic (image)) {
6149 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6150 mono_error_cleanup (&error);
6154 if ((index <= 0) || (index >= image->heap_us.size)) {
6155 *resolve_error = ResolveTokenError_OutOfRange;
6159 /* FIXME: What to do if the index points into the middle of a string ? */
6161 return mono_ldstr (mono_domain_get (), image, index);
6164 ICALL_EXPORT MonoClassField*
6165 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6169 int table = mono_metadata_token_table (token);
6170 int index = mono_metadata_token_index (token);
6171 MonoGenericContext context;
6172 MonoClassField *field;
6174 *resolve_error = ResolveTokenError_Other;
6176 /* Validate token */
6177 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6178 *resolve_error = ResolveTokenError_BadTable;
6182 if (image_is_dynamic (image)) {
6183 if (table == MONO_TABLE_FIELD) {
6184 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6185 mono_error_cleanup (&error);
6189 if (mono_memberref_is_method (image, token)) {
6190 *resolve_error = ResolveTokenError_BadTable;
6194 init_generic_context_from_args (&context, type_args, method_args);
6195 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6196 mono_error_cleanup (&error);
6200 if ((index <= 0) || (index > image->tables [table].rows)) {
6201 *resolve_error = ResolveTokenError_OutOfRange;
6204 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6205 *resolve_error = ResolveTokenError_BadTable;
6209 init_generic_context_from_args (&context, type_args, method_args);
6210 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6211 mono_error_set_pending_exception (&error);
6217 ICALL_EXPORT MonoObject*
6218 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6222 int table = mono_metadata_token_table (token);
6224 *error = ResolveTokenError_Other;
6227 case MONO_TABLE_TYPEDEF:
6228 case MONO_TABLE_TYPEREF:
6229 case MONO_TABLE_TYPESPEC: {
6230 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6232 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6233 mono_error_set_pending_exception (&merror);
6240 case MONO_TABLE_METHOD:
6241 case MONO_TABLE_METHODSPEC: {
6242 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6244 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6245 mono_error_set_pending_exception (&merror);
6251 case MONO_TABLE_FIELD: {
6252 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6254 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6255 mono_error_set_pending_exception (&merror);
6261 case MONO_TABLE_MEMBERREF:
6262 if (mono_memberref_is_method (image, token)) {
6263 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6265 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6266 mono_error_set_pending_exception (&merror);
6273 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6275 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6276 mono_error_set_pending_exception (&merror);
6285 *error = ResolveTokenError_BadTable;
6291 ICALL_EXPORT MonoArray*
6292 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6295 int table = mono_metadata_token_table (token);
6296 int idx = mono_metadata_token_index (token);
6297 MonoTableInfo *tables = image->tables;
6302 *resolve_error = ResolveTokenError_OutOfRange;
6304 /* FIXME: Support other tables ? */
6305 if (table != MONO_TABLE_STANDALONESIG)
6308 if (image_is_dynamic (image))
6311 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6314 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6316 ptr = mono_metadata_blob_heap (image, sig);
6317 len = mono_metadata_decode_blob_size (ptr, &ptr);
6319 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6320 if (mono_error_set_pending_exception (&error))
6322 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6326 ICALL_EXPORT MonoReflectionType*
6327 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6330 MonoReflectionType *ret;
6332 int isbyref = 0, rank;
6333 char *str = mono_string_to_utf8 (smodifiers);
6336 klass = mono_class_from_mono_type (tb->type.type);
6338 /* logic taken from mono_reflection_parse_type(): keep in sync */
6342 if (isbyref) { /* only one level allowed by the spec */
6351 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6352 mono_error_set_pending_exception (&error);
6356 klass = mono_ptr_class_get (&klass->byval_arg);
6357 mono_class_init (klass);
6368 else if (*p != '*') { /* '*' means unknown lower bound */
6379 klass = mono_array_class_get (klass, rank);
6380 mono_class_init (klass);
6389 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6390 mono_error_set_pending_exception (&error);
6395 ICALL_EXPORT MonoBoolean
6396 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6402 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6408 check_for_invalid_type (MonoClass *klass, MonoError *error)
6413 mono_error_init (error);
6415 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6418 name = mono_type_get_full_name (klass);
6419 str = mono_string_new (mono_domain_get (), name);
6421 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6424 ICALL_EXPORT MonoReflectionType *
6425 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6428 MonoReflectionType *ret;
6429 MonoClass *klass, *aklass;
6431 klass = mono_class_from_mono_type (type->type);
6432 check_for_invalid_type (klass, &error);
6433 mono_error_set_pending_exception (&error);
6435 if (rank == 0) //single dimentional array
6436 aklass = mono_array_class_get (klass, 1);
6438 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6440 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6441 mono_error_set_pending_exception (&error);
6446 ICALL_EXPORT MonoReflectionType *
6447 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6450 MonoReflectionType *ret;
6453 klass = mono_class_from_mono_type (type->type);
6454 mono_class_init_checked (klass, &error);
6455 if (mono_error_set_pending_exception (&error))
6458 check_for_invalid_type (klass, &error);
6459 if (mono_error_set_pending_exception (&error))
6462 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6463 mono_error_set_pending_exception (&error);
6468 ICALL_EXPORT MonoReflectionType *
6469 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6472 MonoReflectionType *ret;
6473 MonoClass *klass, *pklass;
6475 klass = mono_class_from_mono_type (type->type);
6476 mono_class_init_checked (klass, &error);
6477 if (mono_error_set_pending_exception (&error))
6479 check_for_invalid_type (klass, &error);
6480 if (mono_error_set_pending_exception (&error))
6483 pklass = mono_ptr_class_get (type->type);
6485 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6486 mono_error_set_pending_exception (&error);
6491 ICALL_EXPORT MonoObject *
6492 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6493 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6496 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6497 MonoObject *delegate;
6499 MonoMethod *method = info->method;
6501 mono_class_init_checked (delegate_class, &error);
6502 if (mono_error_set_pending_exception (&error))
6505 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6506 /* FIXME improve this exception message */
6507 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6509 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6510 mono_error_set_pending_exception (&error);
6514 if (mono_security_core_clr_enabled ()) {
6515 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6516 if (throwOnBindFailure)
6517 mono_error_set_pending_exception (&error);
6519 mono_error_cleanup (&error);
6524 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6525 if (mono_error_set_pending_exception (&error))
6528 if (method_is_dynamic (method)) {
6529 /* Creating a trampoline would leak memory */
6530 func = mono_compile_method (method);
6532 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6533 method = mono_object_get_virtual_method (target, method);
6534 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6535 if (mono_error_set_pending_exception (&error))
6537 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6540 mono_delegate_ctor_with_method (delegate, target, func, method);
6545 ICALL_EXPORT MonoMulticastDelegate *
6546 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6549 MonoMulticastDelegate *ret;
6551 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6553 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6554 if (mono_error_set_pending_exception (&error))
6557 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6562 ICALL_EXPORT MonoReflectionMethod*
6563 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6565 MonoReflectionMethod *ret = NULL;
6567 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6568 mono_error_set_pending_exception (&error);
6574 static inline gint32
6575 mono_array_get_byte_length (MonoArray *array)
6581 klass = array->obj.vtable->klass;
6583 if (array->bounds == NULL)
6584 length = array->max_length;
6587 for (i = 0; i < klass->rank; ++ i)
6588 length *= array->bounds [i].length;
6591 switch (klass->element_class->byval_arg.type) {
6594 case MONO_TYPE_BOOLEAN:
6598 case MONO_TYPE_CHAR:
6606 return length * sizeof (gpointer);
6617 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6619 return mono_array_get_byte_length (array);
6623 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6625 return mono_array_get (array, gint8, idx);
6629 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6631 mono_array_set (array, gint8, idx, value);
6634 ICALL_EXPORT MonoBoolean
6635 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6637 guint8 *src_buf, *dest_buf;
6640 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6644 g_assert (count >= 0);
6646 /* This is called directly from the class libraries without going through the managed wrapper */
6647 MONO_CHECK_ARG_NULL (src, FALSE);
6648 MONO_CHECK_ARG_NULL (dest, FALSE);
6650 /* watch out for integer overflow */
6651 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6654 src_buf = (guint8 *)src->vector + src_offset;
6655 dest_buf = (guint8 *)dest->vector + dest_offset;
6658 memcpy (dest_buf, src_buf, count);
6660 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6665 #ifndef DISABLE_REMOTING
6666 ICALL_EXPORT MonoObject *
6667 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6670 MonoDomain *domain = mono_object_domain (this_obj);
6672 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6673 MonoTransparentProxy *tp;
6677 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6678 if (mono_error_set_pending_exception (&error))
6681 tp = (MonoTransparentProxy*) res;
6683 MONO_OBJECT_SETREF (tp, rp, rp);
6684 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6685 klass = mono_class_from_mono_type (type);
6687 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6688 mono_class_setup_vtable (klass);
6689 if (mono_class_has_failure (klass)) {
6690 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6694 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6695 if (!is_ok (&error)) {
6696 mono_error_set_pending_exception (&error);
6699 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6700 if (!is_ok (&error)) {
6701 mono_error_set_pending_exception (&error);
6705 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6709 ICALL_EXPORT MonoReflectionType *
6710 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6713 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6714 mono_error_set_pending_exception (&error);
6720 /* System.Environment */
6723 ves_icall_System_Environment_get_UserName (void)
6725 /* using glib is more portable */
6726 return mono_string_new (mono_domain_get (), g_get_user_name ());
6730 ICALL_EXPORT MonoString *
6731 ves_icall_System_Environment_get_MachineName (void)
6733 #if defined (HOST_WIN32)
6738 len = MAX_COMPUTERNAME_LENGTH + 1;
6739 buf = g_new (gunichar2, len);
6742 if (GetComputerName (buf, (PDWORD) &len)) {
6744 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6745 mono_error_set_pending_exception (&error);
6750 #elif !defined(DISABLE_SOCKETS)
6754 #if defined _SC_HOST_NAME_MAX
6755 n = sysconf (_SC_HOST_NAME_MAX);
6759 buf = g_malloc (n+1);
6761 if (gethostname (buf, n) == 0){
6763 result = mono_string_new (mono_domain_get (), buf);
6770 return mono_string_new (mono_domain_get (), "mono");
6775 ves_icall_System_Environment_get_Platform (void)
6777 #if defined (TARGET_WIN32)
6780 #elif defined(__MACH__)
6783 // Notice that the value is hidden from user code, and only exposed
6784 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6785 // define and making assumptions based on Unix/128/4 values before there
6786 // was a MacOS define. Lots of code would assume that not-Unix meant
6787 // Windows, but in this case, it would be OSX.
6796 ICALL_EXPORT MonoString *
6797 ves_icall_System_Environment_get_NewLine (void)
6799 #if defined (HOST_WIN32)
6800 return mono_string_new (mono_domain_get (), "\r\n");
6802 return mono_string_new (mono_domain_get (), "\n");
6806 ICALL_EXPORT MonoBoolean
6807 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6809 #if SIZEOF_VOID_P == 8
6813 gboolean isWow64Process = FALSE;
6814 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6815 return (MonoBoolean)isWow64Process;
6817 #elif defined(HAVE_SYS_UTSNAME_H)
6818 struct utsname name;
6820 if (uname (&name) >= 0) {
6821 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6828 ICALL_EXPORT MonoString *
6829 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6837 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6838 value = g_getenv (utf8_name);
6845 return mono_string_new (mono_domain_get (), value);
6849 * There is no standard way to get at environ.
6852 #ifndef __MINGW32_VERSION
6853 #if defined(__APPLE__)
6854 #if defined (TARGET_OSX)
6855 /* Apple defines this in crt_externs.h but doesn't provide that header for
6856 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6857 * in fact exist on all implementations (so far)
6859 gchar ***_NSGetEnviron(void);
6860 #define environ (*_NSGetEnviron())
6862 static char *mono_environ[1] = { NULL };
6863 #define environ mono_environ
6864 #endif /* defined (TARGET_OSX) */
6872 ICALL_EXPORT MonoArray *
6873 ves_icall_System_Environment_GetCoomandLineArgs (void)
6876 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6877 mono_error_set_pending_exception (&error);
6881 ICALL_EXPORT MonoArray *
6882 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6894 env_strings = GetEnvironmentStrings();
6897 env_string = env_strings;
6898 while (*env_string != '\0') {
6899 /* weird case that MS seems to skip */
6900 if (*env_string != '=')
6902 while (*env_string != '\0')
6908 domain = mono_domain_get ();
6909 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6910 if (mono_error_set_pending_exception (&error))
6915 env_string = env_strings;
6916 while (*env_string != '\0') {
6917 /* weird case that MS seems to skip */
6918 if (*env_string != '=') {
6919 equal_str = wcschr(env_string, '=');
6920 g_assert(equal_str);
6922 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6923 if (mono_error_set_pending_exception (&error))
6926 mono_array_setref (names, n, str);
6929 while (*env_string != '\0')
6934 FreeEnvironmentStrings (env_strings);
6948 for (e = environ; *e != 0; ++ e)
6951 domain = mono_domain_get ();
6952 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6953 if (mono_error_set_pending_exception (&error))
6957 for (e = environ; *e != 0; ++ e) {
6958 parts = g_strsplit (*e, "=", 2);
6960 str = mono_string_new (domain, *parts);
6961 mono_array_setref (names, n, str);
6974 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6976 #if !GLIB_CHECK_VERSION(2,4,0)
6977 #define g_setenv(a,b,c) setenv(a,b,c)
6978 #define g_unsetenv(a) unsetenv(a)
6982 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6985 gunichar2 *utf16_name, *utf16_value;
6987 gchar *utf8_name, *utf8_value;
6992 utf16_name = mono_string_to_utf16 (name);
6993 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6994 SetEnvironmentVariable (utf16_name, NULL);
6995 g_free (utf16_name);
6999 utf16_value = mono_string_to_utf16 (value);
7001 SetEnvironmentVariable (utf16_name, utf16_value);
7003 g_free (utf16_name);
7004 g_free (utf16_value);
7006 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
7008 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7009 g_unsetenv (utf8_name);
7014 utf8_value = mono_string_to_utf8_checked (value, &error);
7015 if (!mono_error_ok (&error)) {
7017 mono_error_set_pending_exception (&error);
7020 g_setenv (utf8_name, utf8_value, TRUE);
7023 g_free (utf8_value);
7028 ves_icall_System_Environment_Exit (int result)
7030 mono_environment_exitcode_set (result);
7032 /* FIXME: There are some cleanup hangs that should be worked out, but
7033 * if the program is going to exit, everything will be cleaned up when
7034 * NaCl exits anyway.
7036 #ifndef __native_client__
7037 if (!mono_runtime_try_shutdown ())
7038 mono_thread_exit ();
7040 /* Suspend all managed threads since the runtime is going away */
7041 mono_thread_suspend_all_other_threads ();
7043 mono_runtime_quit ();
7046 /* we may need to do some cleanup here... */
7050 ICALL_EXPORT MonoString*
7051 ves_icall_System_Environment_GetGacPath (void)
7053 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
7056 ICALL_EXPORT MonoString*
7057 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
7059 #if defined (HOST_WIN32)
7060 #ifndef CSIDL_FLAG_CREATE
7061 #define CSIDL_FLAG_CREATE 0x8000
7064 WCHAR path [MAX_PATH];
7065 /* Create directory if no existing */
7066 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
7071 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
7072 mono_error_set_pending_exception (&error);
7076 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7078 return mono_string_new (mono_domain_get (), "");
7081 ICALL_EXPORT MonoArray *
7082 ves_icall_System_Environment_GetLogicalDrives (void)
7085 gunichar2 buf [256], *ptr, *dname;
7087 guint initial_size = 127, size = 128;
7090 MonoString *drivestr;
7091 MonoDomain *domain = mono_domain_get ();
7097 while (size > initial_size) {
7098 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
7099 if (size > initial_size) {
7102 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7103 initial_size = size;
7117 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7118 if (mono_error_set_pending_exception (&error))
7125 while (*u16) { u16++; len ++; }
7126 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7127 if (mono_error_set_pending_exception (&error))
7130 mono_array_setref (result, ndrives++, drivestr);
7141 ICALL_EXPORT MonoString *
7142 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7144 gunichar2 volume_name [MAX_PATH + 1];
7146 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7148 return mono_string_from_utf16 (volume_name);
7151 ICALL_EXPORT MonoString *
7152 ves_icall_System_Environment_InternalGetHome (void)
7154 return mono_string_new (mono_domain_get (), g_get_home_dir ());
7157 static const char *encodings [] = {
7159 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7160 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7161 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7163 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7164 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7165 "x_unicode_2_0_utf_7",
7167 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7168 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7170 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7173 "unicodefffe", "utf_16be",
7180 * Returns the internal codepage, if the value of "int_code_page" is
7181 * 1 at entry, and we can not compute a suitable code page number,
7182 * returns the code page as a string
7184 ICALL_EXPORT MonoString*
7185 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
7190 char *codepage = NULL;
7192 int want_name = *int_code_page;
7195 *int_code_page = -1;
7197 g_get_charset (&cset);
7198 c = codepage = strdup (cset);
7199 for (c = codepage; *c; c++){
7200 if (isascii (*c) && isalpha (*c))
7205 /* g_print ("charset: %s\n", cset); */
7207 /* handle some common aliases */
7210 for (i = 0; p != 0; ){
7213 p = encodings [++i];
7216 if (strcmp (p, codepage) == 0){
7217 *int_code_page = code;
7220 p = encodings [++i];
7223 if (strstr (codepage, "utf_8") != NULL)
7224 *int_code_page |= 0x10000000;
7227 if (want_name && *int_code_page == -1)
7228 return mono_string_new (mono_domain_get (), cset);
7233 ICALL_EXPORT MonoBoolean
7234 ves_icall_System_Environment_get_HasShutdownStarted (void)
7236 if (mono_runtime_is_shutting_down ())
7239 if (mono_domain_is_unloading (mono_domain_get ()))
7246 ves_icall_System_Environment_BroadcastSettingChange (void)
7249 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7254 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7260 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
7261 MonoReflectionMethod *method,
7262 MonoArray *out_args)
7264 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
7267 #ifndef DISABLE_REMOTING
7268 ICALL_EXPORT MonoBoolean
7269 ves_icall_IsTransparentProxy (MonoObject *proxy)
7274 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7280 ICALL_EXPORT MonoReflectionMethod *
7281 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7282 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7284 MonoReflectionMethod *ret = NULL;
7289 MonoMethod **vtable;
7290 MonoMethod *res = NULL;
7292 MONO_CHECK_ARG_NULL (rtype, NULL);
7293 MONO_CHECK_ARG_NULL (rmethod, NULL);
7295 method = rmethod->method;
7296 klass = mono_class_from_mono_type (rtype->type);
7297 mono_class_init_checked (klass, &error);
7298 if (mono_error_set_pending_exception (&error))
7301 if (MONO_CLASS_IS_INTERFACE (klass))
7304 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7307 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7308 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7314 mono_class_setup_vtable (klass);
7315 vtable = klass->vtable;
7317 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7318 gboolean variance_used = FALSE;
7319 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7320 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7322 res = vtable [offs + method->slot];
7324 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7327 if (method->slot != -1)
7328 res = vtable [method->slot];
7334 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7335 mono_error_set_pending_exception (&error);
7340 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7346 klass = mono_class_from_mono_type (type->type);
7347 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7348 if (!is_ok (&error)) {
7349 mono_error_set_pending_exception (&error);
7353 mono_vtable_set_is_remote (vtable, enable);
7356 #else /* DISABLE_REMOTING */
7359 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7361 g_assert_not_reached ();
7366 ICALL_EXPORT MonoObject *
7367 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7374 domain = mono_object_domain (type);
7375 klass = mono_class_from_mono_type (type->type);
7376 mono_class_init_checked (klass, &error);
7377 if (mono_error_set_pending_exception (&error))
7380 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7381 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7385 if (klass->rank >= 1) {
7386 g_assert (klass->rank == 1);
7387 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7388 mono_error_set_pending_exception (&error);
7391 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7392 if (!is_ok (&error)) {
7393 mono_error_set_pending_exception (&error);
7396 /* Bypass remoting object creation check */
7397 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7398 mono_error_set_pending_exception (&error);
7404 ICALL_EXPORT MonoString *
7405 ves_icall_System_IO_get_temp_path (void)
7407 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7410 #ifndef PLATFORM_NO_DRIVEINFO
7411 ICALL_EXPORT MonoBoolean
7412 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7413 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7417 ULARGE_INTEGER wapi_free_bytes_avail;
7418 ULARGE_INTEGER wapi_total_number_of_bytes;
7419 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7421 *error = ERROR_SUCCESS;
7422 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7423 &wapi_total_number_of_free_bytes);
7426 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7427 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7428 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7430 *free_bytes_avail = 0;
7431 *total_number_of_bytes = 0;
7432 *total_number_of_free_bytes = 0;
7433 *error = GetLastError ();
7439 ICALL_EXPORT guint32
7440 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7442 return GetDriveType (mono_string_chars (root_path_name));
7446 ICALL_EXPORT gpointer
7447 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7449 return mono_compile_method (method);
7452 ICALL_EXPORT MonoString *
7453 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7458 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7460 #if defined (HOST_WIN32)
7461 /* Avoid mixing '/' and '\\' */
7464 for (i = strlen (path) - 1; i >= 0; i--)
7465 if (path [i] == '/')
7469 mcpath = mono_string_new (mono_domain_get (), path);
7476 get_bundled_app_config (void)
7478 const gchar *app_config;
7481 gchar *config_file_name, *config_file_path;
7482 gsize len, config_file_path_length, config_ext_length;
7485 domain = mono_domain_get ();
7486 file = domain->setup->configuration_file;
7487 if (!file || file->length == 0)
7490 // Retrieve config file and remove the extension
7491 config_file_name = mono_string_to_utf8 (file);
7492 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7493 if (!config_file_path)
7494 config_file_path = config_file_name;
7496 config_file_path_length = strlen (config_file_path);
7497 config_ext_length = strlen (".config");
7498 if (config_file_path_length <= config_ext_length)
7501 len = config_file_path_length - config_ext_length;
7502 module = (gchar *)g_malloc0 (len + 1);
7503 memcpy (module, config_file_path, len);
7504 // Get the config file from the module name
7505 app_config = mono_config_string_for_assembly_file (module);
7508 if (config_file_name != config_file_path)
7509 g_free (config_file_name);
7510 g_free (config_file_path);
7515 return mono_string_new (mono_domain_get (), app_config);
7519 get_bundled_machine_config (void)
7521 const gchar *machine_config;
7523 machine_config = mono_get_machine_config ();
7525 if (!machine_config)
7528 return mono_string_new (mono_domain_get (), machine_config);
7531 ICALL_EXPORT MonoString *
7532 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7537 path = g_path_get_dirname (mono_get_config_dir ());
7539 #if defined (HOST_WIN32)
7540 /* Avoid mixing '/' and '\\' */
7543 for (i = strlen (path) - 1; i >= 0; i--)
7544 if (path [i] == '/')
7548 ipath = mono_string_new (mono_domain_get (), path);
7554 ICALL_EXPORT gboolean
7555 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7557 MonoPEResourceDataEntry *entry;
7560 if (!assembly || !result || !size)
7565 image = assembly->assembly->image;
7566 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7570 *result = mono_image_rva_map (image, entry->rde_data_offset);
7575 *size = entry->rde_size;
7580 ICALL_EXPORT MonoBoolean
7581 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7583 return mono_is_debugger_attached ();
7586 ICALL_EXPORT MonoBoolean
7587 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7589 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7590 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7596 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7598 if (mono_get_runtime_callbacks ()->debug_log)
7599 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7603 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7605 #if defined (HOST_WIN32)
7606 OutputDebugString (mono_string_chars (message));
7608 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7612 /* Only used for value types */
7613 ICALL_EXPORT MonoObject *
7614 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7621 domain = mono_object_domain (type);
7622 klass = mono_class_from_mono_type (type->type);
7623 mono_class_init_checked (klass, &error);
7624 if (mono_error_set_pending_exception (&error))
7627 if (mono_class_is_nullable (klass))
7628 /* No arguments -> null */
7631 result = mono_object_new_checked (domain, klass, &error);
7632 mono_error_set_pending_exception (&error);
7636 ICALL_EXPORT MonoReflectionMethod *
7637 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7639 MonoReflectionMethod *ret = NULL;
7642 MonoClass *klass, *parent;
7643 MonoGenericContext *generic_inst = NULL;
7644 MonoMethod *method = m->method;
7645 MonoMethod *result = NULL;
7648 if (method->klass == NULL)
7651 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7652 MONO_CLASS_IS_INTERFACE (method->klass) ||
7653 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7656 slot = mono_method_get_vtable_slot (method);
7660 klass = method->klass;
7661 if (klass->generic_class) {
7662 generic_inst = mono_class_get_context (klass);
7663 klass = klass->generic_class->container_class;
7667 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7668 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7669 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7670 or klass is the generic container class and generic_inst is the instantiation.
7672 when we go to the parent, if the parent is an open constructed type, we need to
7673 replace the type parameters by the definitions from the generic_inst, and then take it
7674 apart again into the klass and the generic_inst.
7676 For cases like this:
7677 class C<T> : B<T, int> {
7678 public override void Foo () { ... }
7680 class B<U,V> : A<HashMap<U,V>> {
7681 public override void Foo () { ... }
7684 public virtual void Foo () { ... }
7687 if at each iteration the parent isn't open, we can skip inflating it. if at some
7688 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7691 MonoGenericContext *parent_inst = NULL;
7692 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7693 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7694 if (!mono_error_ok (&error)) {
7695 mono_error_set_pending_exception (&error);
7699 if (parent->generic_class) {
7700 parent_inst = mono_class_get_context (parent);
7701 parent = parent->generic_class->container_class;
7704 mono_class_setup_vtable (parent);
7705 if (parent->vtable_size <= slot)
7708 generic_inst = parent_inst;
7711 klass = klass->parent;
7714 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7715 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7716 if (!mono_error_ok (&error)) {
7717 mono_error_set_pending_exception (&error);
7721 generic_inst = NULL;
7723 if (klass->generic_class) {
7724 generic_inst = mono_class_get_context (klass);
7725 klass = klass->generic_class->container_class;
7731 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7732 if (!mono_error_ok (&error)) {
7733 mono_error_set_pending_exception (&error);
7738 if (klass == method->klass)
7741 /*This is possible if definition == FALSE.
7742 * Do it here to be really sure we don't read invalid memory.
7744 if (slot >= klass->vtable_size)
7747 mono_class_setup_vtable (klass);
7749 result = klass->vtable [slot];
7750 if (result == NULL) {
7751 /* It is an abstract method */
7752 gpointer iter = NULL;
7753 while ((result = mono_class_get_methods (klass, &iter)))
7754 if (result->slot == slot)
7761 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7762 mono_error_set_pending_exception (&error);
7766 ICALL_EXPORT MonoString*
7767 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7769 MonoMethod *method = m->method;
7771 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7776 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7778 iter->sig = *(MonoMethodSignature**)argsp;
7780 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7781 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7784 /* FIXME: it's not documented what start is exactly... */
7788 iter->args = argsp + sizeof (gpointer);
7790 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7792 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7795 ICALL_EXPORT MonoTypedRef
7796 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7798 guint32 i, arg_size;
7802 i = iter->sig->sentinelpos + iter->next_arg;
7804 g_assert (i < iter->sig->param_count);
7806 res.type = iter->sig->params [i];
7807 res.klass = mono_class_from_mono_type (res.type);
7808 arg_size = mono_type_stack_size (res.type, &align);
7809 #if defined(__arm__) || defined(__mips__)
7810 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7812 res.value = iter->args;
7813 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7814 /* Values are stored as 8 byte register sized objects, but 'value'
7815 * is dereferenced as a pointer in other routines.
7817 res.value = (char*)res.value + 4;
7819 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7820 if (arg_size <= sizeof (gpointer)) {
7822 int padding = arg_size - mono_type_size (res.type, &dummy);
7823 res.value = (guint8*)res.value + padding;
7826 iter->args = (char*)iter->args + arg_size;
7829 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7834 ICALL_EXPORT MonoTypedRef
7835 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7837 guint32 i, arg_size;
7841 i = iter->sig->sentinelpos + iter->next_arg;
7843 g_assert (i < iter->sig->param_count);
7845 while (i < iter->sig->param_count) {
7846 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7848 res.type = iter->sig->params [i];
7849 res.klass = mono_class_from_mono_type (res.type);
7850 /* FIXME: endianess issue... */
7851 arg_size = mono_type_stack_size (res.type, &align);
7852 #if defined(__arm__) || defined(__mips__)
7853 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7855 res.value = iter->args;
7856 iter->args = (char*)iter->args + arg_size;
7858 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7861 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7869 ICALL_EXPORT MonoType*
7870 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7874 i = iter->sig->sentinelpos + iter->next_arg;
7876 g_assert (i < iter->sig->param_count);
7878 return iter->sig->params [i];
7881 ICALL_EXPORT MonoObject*
7882 mono_TypedReference_ToObject (MonoTypedRef* tref)
7885 MonoObject *result = NULL;
7886 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7887 MonoObject** objp = (MonoObject **)tref->value;
7891 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7892 mono_error_set_pending_exception (&error);
7896 ICALL_EXPORT MonoTypedRef
7897 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7900 MonoReflectionField *f;
7902 MonoType *ftype = NULL;
7906 memset (&res, 0, sizeof (res));
7909 g_assert (mono_array_length (fields) > 0);
7911 klass = target->vtable->klass;
7913 for (i = 0; i < mono_array_length (fields); ++i) {
7914 f = mono_array_get (fields, MonoReflectionField*, i);
7916 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7919 if (f->field->parent != klass) {
7920 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7924 p = (guint8*)target + f->field->offset;
7926 p += f->field->offset - sizeof (MonoObject);
7927 klass = mono_class_from_mono_type (f->field->type);
7928 ftype = f->field->type;
7932 res.klass = mono_class_from_mono_type (ftype);
7939 prelink_method (MonoMethod *method, MonoError *error)
7941 const char *exc_class, *exc_arg;
7943 mono_error_init (error);
7944 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7946 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7948 mono_error_set_exception_instance (error,
7949 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7952 /* create the wrapper, too? */
7956 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7960 prelink_method (method->method, &error);
7961 mono_error_set_pending_exception (&error);
7965 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7968 MonoClass *klass = mono_class_from_mono_type (type->type);
7970 gpointer iter = NULL;
7972 mono_class_init_checked (klass, &error);
7973 if (mono_error_set_pending_exception (&error))
7976 while ((m = mono_class_get_methods (klass, &iter))) {
7977 prelink_method (m, &error);
7978 if (mono_error_set_pending_exception (&error))
7983 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7985 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7986 gint32 const **exponents,
7987 gunichar2 const **digitLowerTable,
7988 gunichar2 const **digitUpperTable,
7989 gint64 const **tenPowersList,
7990 gint32 const **decHexDigits)
7992 *mantissas = Formatter_MantissaBitsTable;
7993 *exponents = Formatter_TensExponentTable;
7994 *digitLowerTable = Formatter_DigitLowerTable;
7995 *digitUpperTable = Formatter_DigitUpperTable;
7996 *tenPowersList = Formatter_TenPowersList;
7997 *decHexDigits = Formatter_DecHexDigits;
8001 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
8002 * and avoid useless allocations.
8005 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
8007 MonoReflectionType *rt;
8011 mono_error_init (error);
8012 for (i = 0; i < type->num_mods; ++i) {
8013 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
8018 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
8019 return_val_if_nok (error, NULL);
8021 for (i = 0; i < type->num_mods; ++i) {
8022 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
8023 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
8024 return_val_if_nok (error, NULL);
8026 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8027 return_val_if_nok (error, NULL);
8029 mono_array_setref (res, count, rt);
8036 ICALL_EXPORT MonoArray*
8037 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
8040 MonoType *type = param->ClassImpl->type;
8041 MonoClass *member_class = mono_object_class (param->MemberImpl);
8042 MonoMethod *method = NULL;
8045 MonoMethodSignature *sig;
8048 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8049 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8050 method = rmethod->method;
8051 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
8052 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8053 if (!(method = prop->property->get))
8054 method = prop->property->set;
8057 char *type_name = mono_type_get_full_name (member_class);
8058 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
8059 MonoException *ex = mono_get_exception_not_supported (msg);
8062 mono_set_pending_exception (ex);
8066 image = method->klass->image;
8067 pos = param->PositionImpl;
8068 sig = mono_method_signature (method);
8072 type = sig->params [pos];
8074 res = type_array_from_modifiers (image, type, optional, &error);
8075 mono_error_set_pending_exception (&error);
8080 get_property_type (MonoProperty *prop)
8082 MonoMethodSignature *sig;
8084 sig = mono_method_signature (prop->get);
8086 } else if (prop->set) {
8087 sig = mono_method_signature (prop->set);
8088 return sig->params [sig->param_count - 1];
8093 ICALL_EXPORT MonoArray*
8094 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
8097 MonoType *type = get_property_type (property->property);
8098 MonoImage *image = property->klass->image;
8103 res = type_array_from_modifiers (image, type, optional, &error);
8104 mono_error_set_pending_exception (&error);
8109 *Construct a MonoType suited to be used to decode a constant blob object.
8111 * @type is the target type which will be constructed
8112 * @blob_type is the blob type, for example, that comes from the constant table
8113 * @real_type is the expected constructed type.
8116 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8118 type->type = blob_type;
8119 type->data.klass = NULL;
8120 if (blob_type == MONO_TYPE_CLASS)
8121 type->data.klass = mono_defaults.object_class;
8122 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8123 /* For enums, we need to use the base type */
8124 type->type = MONO_TYPE_VALUETYPE;
8125 type->data.klass = mono_class_from_mono_type (real_type);
8127 type->data.klass = mono_class_from_mono_type (real_type);
8130 ICALL_EXPORT MonoObject*
8131 property_info_get_default_value (MonoReflectionProperty *property)
8135 MonoProperty *prop = property->property;
8136 MonoType *type = get_property_type (prop);
8137 MonoDomain *domain = mono_object_domain (property);
8138 MonoTypeEnum def_type;
8139 const char *def_value;
8142 mono_class_init (prop->parent);
8144 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8145 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8149 def_value = mono_class_get_property_default_value (prop, &def_type);
8151 mono_type_from_blob_type (&blob_type, def_type, type);
8152 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8154 mono_error_set_pending_exception (&error);
8158 ICALL_EXPORT MonoBoolean
8159 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8162 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8163 MonoCustomAttrInfo *cinfo;
8166 mono_class_init_checked (attr_class, &error);
8167 if (mono_error_set_pending_exception (&error))
8170 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8171 if (!is_ok (&error)) {
8172 mono_error_set_pending_exception (&error);
8177 found = mono_custom_attrs_has_attr (cinfo, attr_class);
8179 mono_custom_attrs_free (cinfo);
8183 ICALL_EXPORT MonoArray*
8184 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8186 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8191 mono_class_init_checked (attr_class, &error);
8192 if (mono_error_set_pending_exception (&error))
8196 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8197 if (!mono_error_ok (&error)) {
8198 mono_error_set_pending_exception (&error);
8205 ICALL_EXPORT MonoArray*
8206 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8210 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8211 mono_error_set_pending_exception (&error);
8216 ICALL_EXPORT MonoString*
8217 ves_icall_Mono_Runtime_GetDisplayName (void)
8220 MonoString *display_name;
8222 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8223 display_name = mono_string_new (mono_domain_get (), info);
8225 return display_name;
8228 ICALL_EXPORT MonoString*
8229 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8232 MonoString *message;
8236 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8237 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8240 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8242 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8243 if (mono_error_set_pending_exception (&error))
8250 ICALL_EXPORT gpointer
8251 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8253 return GetCurrentProcess ();
8256 ICALL_EXPORT MonoBoolean
8257 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8259 return GetExitCodeProcess (handle, (guint32*) exitcode);
8262 ICALL_EXPORT MonoBoolean
8263 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8265 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8266 return CloseHandle (handle);
8268 return CloseProcess (handle);
8272 ICALL_EXPORT MonoBoolean
8273 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8275 return TerminateProcess (handle, exitcode);
8279 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8281 return WaitForInputIdle (handle, milliseconds);
8284 ICALL_EXPORT MonoBoolean
8285 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8287 return GetProcessWorkingSetSize (handle, min, max);
8290 ICALL_EXPORT MonoBoolean
8291 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8293 return SetProcessWorkingSetSize (handle, min, max);
8296 ICALL_EXPORT MonoBoolean
8297 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8299 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8303 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8305 return mono_process_current_pid ();
8309 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8311 return GetPriorityClass (handle);
8314 ICALL_EXPORT MonoBoolean
8315 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8317 return SetPriorityClass (handle, priorityClass);
8320 #ifndef DISABLE_ICALL_TABLES
8322 #define ICALL_TYPE(id,name,first)
8323 #define ICALL(id,name,func) Icall_ ## id,
8326 #include "metadata/icall-def.h"
8332 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8333 #define ICALL(id,name,func)
8335 #include "metadata/icall-def.h"
8341 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8342 #define ICALL(id,name,func)
8344 guint16 first_icall;
8347 static const IcallTypeDesc
8348 icall_type_descs [] = {
8349 #include "metadata/icall-def.h"
8353 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8356 #define ICALL_TYPE(id,name,first)
8359 #ifdef HAVE_ARRAY_ELEM_INIT
8360 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8361 #define MSGSTRFIELD1(line) str##line
8363 static const struct msgstrtn_t {
8364 #define ICALL(id,name,func)
8366 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8367 #include "metadata/icall-def.h"
8369 } icall_type_names_str = {
8370 #define ICALL_TYPE(id,name,first) (name),
8371 #include "metadata/icall-def.h"
8374 static const guint16 icall_type_names_idx [] = {
8375 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8376 #include "metadata/icall-def.h"
8379 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8381 static const struct msgstr_t {
8383 #define ICALL_TYPE(id,name,first)
8384 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8385 #include "metadata/icall-def.h"
8387 } icall_names_str = {
8388 #define ICALL(id,name,func) (name),
8389 #include "metadata/icall-def.h"
8392 static const guint16 icall_names_idx [] = {
8393 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8394 #include "metadata/icall-def.h"
8397 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8403 #define ICALL_TYPE(id,name,first) name,
8404 #define ICALL(id,name,func)
8405 static const char* const
8406 icall_type_names [] = {
8407 #include "metadata/icall-def.h"
8411 #define icall_type_name_get(id) (icall_type_names [(id)])
8415 #define ICALL_TYPE(id,name,first)
8416 #define ICALL(id,name,func) name,
8417 static const char* const
8419 #include "metadata/icall-def.h"
8422 #define icall_name_get(id) icall_names [(id)]
8424 #endif /* !HAVE_ARRAY_ELEM_INIT */
8428 #define ICALL_TYPE(id,name,first)
8429 #define ICALL(id,name,func) func,
8430 static const gconstpointer
8431 icall_functions [] = {
8432 #include "metadata/icall-def.h"
8436 #ifdef ENABLE_ICALL_SYMBOL_MAP
8439 #define ICALL_TYPE(id,name,first)
8440 #define ICALL(id,name,func) #func,
8441 static const gconstpointer
8442 icall_symbols [] = {
8443 #include "metadata/icall-def.h"
8448 #endif /* DISABLE_ICALL_TABLES */
8450 static mono_mutex_t icall_mutex;
8451 static GHashTable *icall_hash = NULL;
8452 static GHashTable *jit_icall_hash_name = NULL;
8453 static GHashTable *jit_icall_hash_addr = NULL;
8456 mono_icall_init (void)
8458 #ifndef DISABLE_ICALL_TABLES
8461 /* check that tables are sorted: disable in release */
8464 const char *prev_class = NULL;
8465 const char *prev_method;
8467 for (i = 0; i < Icall_type_num; ++i) {
8468 const IcallTypeDesc *desc;
8471 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8472 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8473 prev_class = icall_type_name_get (i);
8474 desc = &icall_type_descs [i];
8475 num_icalls = icall_desc_num_icalls (desc);
8476 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8477 for (j = 0; j < num_icalls; ++j) {
8478 const char *methodn = icall_name_get (desc->first_icall + j);
8479 if (prev_method && strcmp (prev_method, methodn) >= 0)
8480 g_print ("method %s should come before method %s\n", methodn, prev_method);
8481 prev_method = methodn;
8487 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8488 mono_os_mutex_init (&icall_mutex);
8492 mono_icall_lock (void)
8494 mono_locks_os_acquire (&icall_mutex, IcallLock);
8498 mono_icall_unlock (void)
8500 mono_locks_os_release (&icall_mutex, IcallLock);
8504 mono_icall_cleanup (void)
8506 g_hash_table_destroy (icall_hash);
8507 g_hash_table_destroy (jit_icall_hash_name);
8508 g_hash_table_destroy (jit_icall_hash_addr);
8509 mono_os_mutex_destroy (&icall_mutex);
8513 * mono_add_internal_call:
8514 * @name: method specification to surface to the managed world
8515 * @method: pointer to a C method to invoke when the method is called
8517 * This method surfaces the C function pointed by @method as a method
8518 * that has been surfaced in managed code with the method specified in
8519 * @name as an internal call.
8521 * Internal calls are surfaced to all app domains loaded and they are
8522 * accessibly by a type with the specified name.
8524 * You must provide a fully qualified type name, that is namespaces
8525 * and type name, followed by a colon and the method name, with an
8526 * optional signature to bind.
8528 * For example, the following are all valid declarations:
8530 * "MyApp.Services.ScriptService:Accelerate"
8531 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8533 * You use method parameters in cases where there might be more than
8534 * one surface method to managed code. That way you can register different
8535 * internal calls for different method overloads.
8537 * The internal calls are invoked with no marshalling. This means that .NET
8538 * types like System.String are exposed as `MonoString *` parameters. This is
8539 * different than the way that strings are surfaced in P/Invoke.
8541 * For more information on how the parameters are marshalled, see the
8542 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8545 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8546 * reference for more information on the format of method descriptions.
8549 mono_add_internal_call (const char *name, gconstpointer method)
8553 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8555 mono_icall_unlock ();
8558 #ifndef DISABLE_ICALL_TABLES
8560 #ifdef HAVE_ARRAY_ELEM_INIT
8562 compare_method_imap (const void *key, const void *elem)
8564 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8565 return strcmp (key, method_name);
8569 find_method_icall (const IcallTypeDesc *imap, const char *name)
8571 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);
8574 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8578 compare_class_imap (const void *key, const void *elem)
8580 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8581 return strcmp (key, class_name);
8584 static const IcallTypeDesc*
8585 find_class_icalls (const char *name)
8587 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);
8590 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8593 #else /* HAVE_ARRAY_ELEM_INIT */
8596 compare_method_imap (const void *key, const void *elem)
8598 const char** method_name = (const char**)elem;
8599 return strcmp (key, *method_name);
8603 find_method_icall (const IcallTypeDesc *imap, const char *name)
8605 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8608 return (gpointer)icall_functions [(nameslot - icall_names)];
8612 compare_class_imap (const void *key, const void *elem)
8614 const char** class_name = (const char**)elem;
8615 return strcmp (key, *class_name);
8618 static const IcallTypeDesc*
8619 find_class_icalls (const char *name)
8621 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8624 return &icall_type_descs [nameslot - icall_type_names];
8627 #endif /* HAVE_ARRAY_ELEM_INIT */
8629 #endif /* DISABLE_ICALL_TABLES */
8632 * we should probably export this as an helper (handle nested types).
8633 * Returns the number of chars written in buf.
8636 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8638 int nspacelen, cnamelen;
8639 nspacelen = strlen (klass->name_space);
8640 cnamelen = strlen (klass->name);
8641 if (nspacelen + cnamelen + 2 > bufsize)
8644 memcpy (buf, klass->name_space, nspacelen);
8645 buf [nspacelen ++] = '.';
8647 memcpy (buf + nspacelen, klass->name, cnamelen);
8648 buf [nspacelen + cnamelen] = 0;
8649 return nspacelen + cnamelen;
8652 #ifdef DISABLE_ICALL_TABLES
8654 no_icall_table (void)
8656 g_assert_not_reached ();
8661 mono_lookup_internal_call (MonoMethod *method)
8666 int typelen = 0, mlen, siglen;
8668 #ifndef DISABLE_ICALL_TABLES
8669 const IcallTypeDesc *imap = NULL;
8672 g_assert (method != NULL);
8674 if (method->is_inflated)
8675 method = ((MonoMethodInflated *) method)->declaring;
8677 if (method->klass->nested_in) {
8678 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8682 mname [pos++] = '/';
8685 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8691 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8696 #ifndef DISABLE_ICALL_TABLES
8697 imap = find_class_icalls (mname);
8700 mname [typelen] = ':';
8701 mname [typelen + 1] = ':';
8703 mlen = strlen (method->name);
8704 memcpy (mname + typelen + 2, method->name, mlen);
8705 sigstart = mname + typelen + 2 + mlen;
8708 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8709 siglen = strlen (tmpsig);
8710 if (typelen + mlen + siglen + 6 > sizeof (mname))
8713 memcpy (sigstart + 1, tmpsig, siglen);
8714 sigstart [siglen + 1] = ')';
8715 sigstart [siglen + 2] = 0;
8720 res = g_hash_table_lookup (icall_hash, mname);
8722 mono_icall_unlock ();;
8725 /* try without signature */
8727 res = g_hash_table_lookup (icall_hash, mname);
8729 mono_icall_unlock ();
8733 #ifdef DISABLE_ICALL_TABLES
8734 mono_icall_unlock ();
8735 /* Fail only when the result is actually used */
8736 /* mono_marshal_get_native_wrapper () depends on this */
8737 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8738 return ves_icall_System_String_ctor_RedirectToCreateString;
8740 return no_icall_table;
8742 /* it wasn't found in the static call tables */
8744 mono_icall_unlock ();
8747 res = find_method_icall (imap, sigstart - mlen);
8749 mono_icall_unlock ();
8752 /* try _with_ signature */
8754 res = find_method_icall (imap, sigstart - mlen);
8756 mono_icall_unlock ();
8760 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8761 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8762 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8763 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8764 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");
8765 g_print ("If you see other errors or faults after this message they are probably related\n");
8766 g_print ("and you need to fix your mono install first.\n");
8768 mono_icall_unlock ();
8774 #ifdef ENABLE_ICALL_SYMBOL_MAP
8776 func_cmp (gconstpointer key, gconstpointer p)
8778 return (gsize)key - (gsize)*(gsize*)p;
8783 * mono_lookup_icall_symbol:
8785 * Given the icall METHOD, returns its C symbol.
8788 mono_lookup_icall_symbol (MonoMethod *m)
8790 #ifdef DISABLE_ICALL_TABLES
8791 g_assert_not_reached ();
8794 #ifdef ENABLE_ICALL_SYMBOL_MAP
8798 static gconstpointer *functions_sorted;
8799 static const char**symbols_sorted;
8800 static gboolean inited;
8805 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8806 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8807 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8808 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8809 /* Bubble sort the two arrays */
8813 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8814 if (functions_sorted [i] > functions_sorted [i + 1]) {
8817 tmp = functions_sorted [i];
8818 functions_sorted [i] = functions_sorted [i + 1];
8819 functions_sorted [i + 1] = tmp;
8820 tmp = symbols_sorted [i];
8821 symbols_sorted [i] = symbols_sorted [i + 1];
8822 symbols_sorted [i + 1] = tmp;
8829 func = mono_lookup_internal_call (m);
8832 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8836 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8838 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8839 g_assert_not_reached ();
8846 type_from_typename (char *type_name)
8848 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8850 if (!strcmp (type_name, "int"))
8851 klass = mono_defaults.int_class;
8852 else if (!strcmp (type_name, "ptr"))
8853 klass = mono_defaults.int_class;
8854 else if (!strcmp (type_name, "void"))
8855 klass = mono_defaults.void_class;
8856 else if (!strcmp (type_name, "int32"))
8857 klass = mono_defaults.int32_class;
8858 else if (!strcmp (type_name, "uint32"))
8859 klass = mono_defaults.uint32_class;
8860 else if (!strcmp (type_name, "int8"))
8861 klass = mono_defaults.sbyte_class;
8862 else if (!strcmp (type_name, "uint8"))
8863 klass = mono_defaults.byte_class;
8864 else if (!strcmp (type_name, "int16"))
8865 klass = mono_defaults.int16_class;
8866 else if (!strcmp (type_name, "uint16"))
8867 klass = mono_defaults.uint16_class;
8868 else if (!strcmp (type_name, "long"))
8869 klass = mono_defaults.int64_class;
8870 else if (!strcmp (type_name, "ulong"))
8871 klass = mono_defaults.uint64_class;
8872 else if (!strcmp (type_name, "float"))
8873 klass = mono_defaults.single_class;
8874 else if (!strcmp (type_name, "double"))
8875 klass = mono_defaults.double_class;
8876 else if (!strcmp (type_name, "object"))
8877 klass = mono_defaults.object_class;
8878 else if (!strcmp (type_name, "obj"))
8879 klass = mono_defaults.object_class;
8880 else if (!strcmp (type_name, "string"))
8881 klass = mono_defaults.string_class;
8882 else if (!strcmp (type_name, "bool"))
8883 klass = mono_defaults.boolean_class;
8884 else if (!strcmp (type_name, "boolean"))
8885 klass = mono_defaults.boolean_class;
8887 g_error ("%s", type_name);
8888 g_assert_not_reached ();
8890 return &klass->byval_arg;
8894 * LOCKING: Take the corlib image lock.
8896 MonoMethodSignature*
8897 mono_create_icall_signature (const char *sigstr)
8902 MonoMethodSignature *res, *res2;
8903 MonoImage *corlib = mono_defaults.corlib;
8905 mono_image_lock (corlib);
8906 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8907 mono_image_unlock (corlib);
8912 parts = g_strsplit (sigstr, " ", 256);
8921 res = mono_metadata_signature_alloc (corlib, len - 1);
8926 * Under windows, the default pinvoke calling convention is STDCALL but
8929 res->call_convention = MONO_CALL_C;
8932 res->ret = type_from_typename (parts [0]);
8933 for (i = 1; i < len; ++i) {
8934 res->params [i - 1] = type_from_typename (parts [i]);
8939 mono_image_lock (corlib);
8940 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8942 res = res2; /*Value is allocated in the image pool*/
8944 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8945 mono_image_unlock (corlib);
8951 mono_find_jit_icall_by_name (const char *name)
8953 MonoJitICallInfo *info;
8954 g_assert (jit_icall_hash_name);
8957 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8958 mono_icall_unlock ();
8963 mono_find_jit_icall_by_addr (gconstpointer addr)
8965 MonoJitICallInfo *info;
8966 g_assert (jit_icall_hash_addr);
8969 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8970 mono_icall_unlock ();
8976 * mono_get_jit_icall_info:
8978 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8979 * caller should access it while holding the icall lock.
8982 mono_get_jit_icall_info (void)
8984 return jit_icall_hash_name;
8988 * mono_lookup_jit_icall_symbol:
8990 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8993 mono_lookup_jit_icall_symbol (const char *name)
8995 MonoJitICallInfo *info;
8996 const char *res = NULL;
8999 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9001 res = info->c_symbol;
9002 mono_icall_unlock ();
9007 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
9010 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
9011 mono_icall_unlock ();
9015 * 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
9016 * icalls without wrappers in some cases.
9019 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
9021 MonoJitICallInfo *info;
9028 if (!jit_icall_hash_name) {
9029 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
9030 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
9033 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
9034 g_warning ("jit icall already defined \"%s\"\n", name);
9035 g_assert_not_reached ();
9038 info = g_new0 (MonoJitICallInfo, 1);
9043 info->c_symbol = c_symbol;
9044 info->no_raise = no_raise;
9047 info->wrapper = func;
9049 info->wrapper = NULL;
9052 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
9053 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
9055 mono_icall_unlock ();
9060 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
9062 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);