5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
9 * Aleksey Kliger (aleksey@xamarin.com)
11 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
12 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
14 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
25 #ifdef HAVE_SYS_TIME_H
31 #if defined (HOST_WIN32)
34 #if defined (HAVE_WCHAR_H)
38 #include "mono/utils/mono-membar.h"
39 #include <mono/metadata/object.h>
40 #include <mono/metadata/threads.h>
41 #include <mono/metadata/threads-types.h>
42 #include <mono/metadata/threadpool-ms.h>
43 #include <mono/metadata/threadpool-ms-io.h>
44 #include <mono/metadata/monitor.h>
45 #include <mono/metadata/reflection.h>
46 #include <mono/metadata/assembly.h>
47 #include <mono/metadata/tabledefs.h>
48 #include <mono/metadata/exception.h>
49 #include <mono/metadata/exception-internals.h>
50 #include <mono/metadata/file-io.h>
51 #include <mono/metadata/console-io.h>
52 #include <mono/metadata/mono-route.h>
53 #include <mono/metadata/socket-io.h>
54 #include <mono/metadata/mono-endian.h>
55 #include <mono/metadata/tokentype.h>
56 #include <mono/metadata/domain-internals.h>
57 #include <mono/metadata/metadata-internals.h>
58 #include <mono/metadata/class-internals.h>
59 #include <mono/metadata/reflection-internals.h>
60 #include <mono/metadata/marshal.h>
61 #include <mono/metadata/gc-internals.h>
62 #include <mono/metadata/mono-gc.h>
63 #include <mono/metadata/rand.h>
64 #include <mono/metadata/sysmath.h>
65 #include <mono/metadata/string-icalls.h>
66 #include <mono/metadata/debug-helpers.h>
67 #include <mono/metadata/process.h>
68 #include <mono/metadata/environment.h>
69 #include <mono/metadata/profiler-private.h>
70 #include <mono/metadata/locales.h>
71 #include <mono/metadata/filewatcher.h>
72 #include <mono/metadata/security.h>
73 #include <mono/metadata/mono-config.h>
74 #include <mono/metadata/cil-coff.h>
75 #include <mono/metadata/number-formatter.h>
76 #include <mono/metadata/security-manager.h>
77 #include <mono/metadata/security-core-clr.h>
78 #include <mono/metadata/mono-perfcounters.h>
79 #include <mono/metadata/mono-debug.h>
80 #include <mono/metadata/mono-ptr-array.h>
81 #include <mono/metadata/verify-internals.h>
82 #include <mono/metadata/runtime.h>
83 #include <mono/metadata/file-mmap.h>
84 #include <mono/metadata/seq-points-data.h>
85 #include <mono/io-layer/io-layer.h>
86 #include <mono/utils/monobitset.h>
87 #include <mono/utils/mono-time.h>
88 #include <mono/utils/mono-proclib.h>
89 #include <mono/utils/mono-string.h>
90 #include <mono/utils/mono-error-internals.h>
91 #include <mono/utils/mono-mmap.h>
92 #include <mono/utils/mono-io-portability.h>
93 #include <mono/utils/mono-digest.h>
94 #include <mono/utils/bsearch.h>
95 #include <mono/utils/mono-os-mutex.h>
96 #include <mono/utils/mono-threads.h>
98 #if defined (HOST_WIN32)
102 #include "decimal-ms.h"
103 #include "number-ms.h"
105 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
106 #include <sys/utsname.h>
109 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
111 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
113 /* Lazy class loading functions */
114 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
115 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
116 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
119 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
122 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
124 static inline MonoBoolean
125 is_generic_parameter (MonoType *type)
127 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
131 mono_class_init_checked (MonoClass *klass, MonoError *error)
133 mono_error_init (error);
135 if (!mono_class_init (klass))
136 mono_error_set_for_class_failure (error, klass);
139 ICALL_EXPORT MonoObject *
140 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
146 MonoObject *result = NULL;
148 ac = (MonoClass *)arr->obj.vtable->klass;
150 esize = mono_array_element_size (ac);
151 ea = (gpointer*)((char*)arr->vector + (pos * esize));
153 if (ac->element_class->valuetype) {
154 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
155 mono_error_set_pending_exception (&error);
157 result = (MonoObject *)*ea;
161 ICALL_EXPORT MonoObject *
162 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
168 MONO_CHECK_ARG_NULL (idxs, NULL);
171 ic = (MonoClass *)io->obj.vtable->klass;
173 ac = (MonoClass *)arr->obj.vtable->klass;
175 g_assert (ic->rank == 1);
176 if (io->bounds != NULL || io->max_length != ac->rank) {
177 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
181 ind = (gint32 *)io->vector;
183 if (arr->bounds == NULL) {
184 if (*ind < 0 || *ind >= arr->max_length) {
185 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
189 return ves_icall_System_Array_GetValueImpl (arr, *ind);
192 for (i = 0; i < ac->rank; i++) {
193 if ((ind [i] < arr->bounds [i].lower_bound) ||
194 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
195 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
200 pos = ind [0] - arr->bounds [0].lower_bound;
201 for (i = 1; i < ac->rank; i++)
202 pos = pos * arr->bounds [i].length + ind [i] -
203 arr->bounds [i].lower_bound;
205 return ves_icall_System_Array_GetValueImpl (arr, pos);
209 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
212 MonoClass *ac, *vc, *ec;
221 mono_error_init (&error);
224 vc = value->vtable->klass;
228 ac = arr->obj.vtable->klass;
229 ec = ac->element_class;
231 esize = mono_array_element_size (ac);
232 ea = (gpointer*)((char*)arr->vector + (pos * esize));
233 va = (gpointer*)((char*)value + sizeof (MonoObject));
235 if (mono_class_is_nullable (ec)) {
236 mono_nullable_init ((guint8*)ea, value, ec);
241 mono_gc_bzero_atomic (ea, esize);
245 #define NO_WIDENING_CONVERSION G_STMT_START{\
246 mono_set_pending_exception (mono_get_exception_argument ( \
247 "value", "not a widening conversion")); \
251 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
252 if (esize < vsize + (extra)) { \
253 mono_set_pending_exception (mono_get_exception_argument ( \
254 "value", "not a widening conversion")); \
259 #define INVALID_CAST G_STMT_START{ \
260 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
261 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
265 /* Check element (destination) type. */
266 switch (ec->byval_arg.type) {
267 case MONO_TYPE_STRING:
268 switch (vc->byval_arg.type) {
269 case MONO_TYPE_STRING:
275 case MONO_TYPE_BOOLEAN:
276 switch (vc->byval_arg.type) {
277 case MONO_TYPE_BOOLEAN:
290 NO_WIDENING_CONVERSION;
299 if (!ec->valuetype) {
300 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
301 if (mono_error_set_pending_exception (&error))
305 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
309 if (mono_object_isinst_checked (value, ec, &error)) {
310 if (ec->has_references)
311 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
313 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
316 if (mono_error_set_pending_exception (&error))
322 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
324 et = ec->byval_arg.type;
325 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
326 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
328 vt = vc->byval_arg.type;
329 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
330 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
332 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
338 case MONO_TYPE_CHAR: \
339 CHECK_WIDENING_CONVERSION(0); \
340 *(etype *) ea = (etype) u64; \
342 /* You can't assign a signed value to an unsigned array. */ \
347 /* You can't assign a floating point number to an integer array. */ \
350 NO_WIDENING_CONVERSION; \
354 #define ASSIGN_SIGNED(etype) G_STMT_START{\
360 CHECK_WIDENING_CONVERSION(0); \
361 *(etype *) ea = (etype) i64; \
363 /* You can assign an unsigned value to a signed array if the array's */ \
364 /* element size is larger than the value size. */ \
369 case MONO_TYPE_CHAR: \
370 CHECK_WIDENING_CONVERSION(1); \
371 *(etype *) ea = (etype) u64; \
373 /* You can't assign a floating point number to an integer array. */ \
376 NO_WIDENING_CONVERSION; \
380 #define ASSIGN_REAL(etype) G_STMT_START{\
384 CHECK_WIDENING_CONVERSION(0); \
385 *(etype *) ea = (etype) r64; \
387 /* All integer values fit into a floating point array, so we don't */ \
388 /* need to CHECK_WIDENING_CONVERSION here. */ \
393 *(etype *) ea = (etype) i64; \
399 case MONO_TYPE_CHAR: \
400 *(etype *) ea = (etype) u64; \
407 u64 = *(guint8 *) va;
410 u64 = *(guint16 *) va;
413 u64 = *(guint32 *) va;
416 u64 = *(guint64 *) va;
422 i64 = *(gint16 *) va;
425 i64 = *(gint32 *) va;
428 i64 = *(gint64 *) va;
431 r64 = *(gfloat *) va;
434 r64 = *(gdouble *) va;
437 u64 = *(guint16 *) va;
439 case MONO_TYPE_BOOLEAN:
440 /* Boolean is only compatible with itself. */
453 NO_WIDENING_CONVERSION;
460 /* If we can't do a direct copy, let's try a widening conversion. */
463 ASSIGN_UNSIGNED (guint16);
465 ASSIGN_UNSIGNED (guint8);
467 ASSIGN_UNSIGNED (guint16);
469 ASSIGN_UNSIGNED (guint32);
471 ASSIGN_UNSIGNED (guint64);
473 ASSIGN_SIGNED (gint8);
475 ASSIGN_SIGNED (gint16);
477 ASSIGN_SIGNED (gint32);
479 ASSIGN_SIGNED (gint64);
481 ASSIGN_REAL (gfloat);
483 ASSIGN_REAL (gdouble);
487 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
491 #undef NO_WIDENING_CONVERSION
492 #undef CHECK_WIDENING_CONVERSION
493 #undef ASSIGN_UNSIGNED
499 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
505 MONO_CHECK_ARG_NULL (idxs,);
507 ic = idxs->obj.vtable->klass;
508 ac = arr->obj.vtable->klass;
510 g_assert (ic->rank == 1);
511 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
512 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
516 ind = (gint32 *)idxs->vector;
518 if (arr->bounds == NULL) {
519 if (*ind < 0 || *ind >= arr->max_length) {
520 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
524 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
528 for (i = 0; i < ac->rank; i++)
529 if ((ind [i] < arr->bounds [i].lower_bound) ||
530 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
531 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
535 pos = ind [0] - arr->bounds [0].lower_bound;
536 for (i = 1; i < ac->rank; i++)
537 pos = pos * arr->bounds [i].length + ind [i] -
538 arr->bounds [i].lower_bound;
540 ves_icall_System_Array_SetValueImpl (arr, value, pos);
543 ICALL_EXPORT MonoArray *
544 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
547 MonoClass *aklass, *klass;
550 gboolean bounded = FALSE;
552 MONO_CHECK_ARG_NULL (type, NULL);
553 MONO_CHECK_ARG_NULL (lengths, NULL);
555 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
557 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
559 for (i = 0; i < mono_array_length (lengths); i++) {
560 if (mono_array_get (lengths, gint32, i) < 0) {
561 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
566 klass = mono_class_from_mono_type (type->type);
567 mono_class_init_checked (klass, &error);
568 if (mono_error_set_pending_exception (&error))
571 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
572 /* vectors are not the same as one dimensional arrays with no-zero bounds */
577 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
579 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
580 for (i = 0; i < aklass->rank; ++i) {
581 sizes [i] = mono_array_get (lengths, guint32, i);
583 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
585 sizes [i + aklass->rank] = 0;
588 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
589 mono_error_set_pending_exception (&error);
594 ICALL_EXPORT MonoArray *
595 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
598 MonoClass *aklass, *klass;
601 gboolean bounded = FALSE;
603 MONO_CHECK_ARG_NULL (type, NULL);
604 MONO_CHECK_ARG_NULL (lengths, NULL);
606 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
608 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
610 for (i = 0; i < mono_array_length (lengths); i++) {
611 if ((mono_array_get (lengths, gint64, i) < 0) ||
612 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
613 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
618 klass = mono_class_from_mono_type (type->type);
619 mono_class_init_checked (klass, &error);
620 if (mono_error_set_pending_exception (&error))
623 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
624 /* vectors are not the same as one dimensional arrays with no-zero bounds */
629 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
631 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
632 for (i = 0; i < aklass->rank; ++i) {
633 sizes [i] = mono_array_get (lengths, guint64, i);
635 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
637 sizes [i + aklass->rank] = 0;
640 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
641 mono_error_set_pending_exception (&error);
647 ves_icall_System_Array_GetRank (MonoObject *arr)
649 return arr->vtable->klass->rank;
653 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
655 gint32 rank = arr->obj.vtable->klass->rank;
658 if ((dimension < 0) || (dimension >= rank)) {
659 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
663 if (arr->bounds == NULL)
664 length = arr->max_length;
666 length = arr->bounds [dimension].length;
668 #ifdef MONO_BIG_ARRAYS
669 if (length > G_MAXINT32) {
670 mono_set_pending_exception (mono_get_exception_overflow ());
678 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
680 gint32 rank = arr->obj.vtable->klass->rank;
682 if ((dimension < 0) || (dimension >= rank)) {
683 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
687 if (arr->bounds == NULL)
688 return arr->max_length;
690 return arr->bounds [dimension].length;
694 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
696 gint32 rank = arr->obj.vtable->klass->rank;
698 if ((dimension < 0) || (dimension >= rank)) {
699 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
703 if (arr->bounds == NULL)
706 return arr->bounds [dimension].lower_bound;
710 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
712 int sz = mono_array_element_size (mono_object_class (arr));
713 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
716 ICALL_EXPORT MonoArray*
717 ves_icall_System_Array_Clone (MonoArray *arr)
720 MonoArray *result = mono_array_clone_checked (arr, &error);
721 mono_error_set_pending_exception (&error);
725 ICALL_EXPORT gboolean
726 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
731 MonoVTable *src_vtable;
732 MonoVTable *dest_vtable;
733 MonoClass *src_class;
734 MonoClass *dest_class;
736 src_vtable = source->obj.vtable;
737 dest_vtable = dest->obj.vtable;
739 if (src_vtable->rank != dest_vtable->rank)
742 if (source->bounds || dest->bounds)
745 /* there's no integer overflow since mono_array_length returns an unsigned integer */
746 if ((dest_idx + length > mono_array_length_fast (dest)) ||
747 (source_idx + length > mono_array_length_fast (source)))
750 src_class = src_vtable->klass->element_class;
751 dest_class = dest_vtable->klass->element_class;
754 * Handle common cases.
757 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
758 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
760 if (src_class == mono_defaults.object_class && dest_class->valuetype)
763 /* Check if we're copying a char[] <==> (u)short[] */
764 if (src_class != dest_class) {
765 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
768 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
769 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
773 if (dest_class->valuetype) {
774 element_size = mono_array_element_size (source->obj.vtable->klass);
775 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
776 if (dest_class->has_references) {
777 mono_value_copy_array (dest, dest_idx, source_addr, length);
779 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
780 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
783 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
790 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
796 ac = (MonoClass *)arr->obj.vtable->klass;
798 esize = mono_array_element_size (ac);
799 ea = (gpointer*)((char*)arr->vector + (pos * esize));
801 mono_gc_memmove_atomic (value, ea, esize);
805 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
811 ac = (MonoClass *)arr->obj.vtable->klass;
812 ec = ac->element_class;
814 esize = mono_array_element_size (ac);
815 ea = (gpointer*)((char*)arr->vector + (pos * esize));
817 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
818 g_assert (esize == sizeof (gpointer));
819 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
821 g_assert (ec->inited);
822 g_assert (esize == mono_class_value_size (ec, NULL));
823 if (ec->has_references)
824 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
826 mono_gc_memmove_atomic (ea, value, esize);
831 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
833 MonoClass *klass = array->obj.vtable->klass;
834 guint32 size = mono_array_element_size (klass);
835 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
837 const char *field_data;
839 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
840 MonoException *exc = mono_get_exception_argument("array",
841 "Cannot initialize array of non-primitive type.");
842 mono_set_pending_exception (exc);
846 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
847 MonoException *exc = mono_get_exception_argument("field_handle",
848 "Field doesn't have an RVA");
849 mono_set_pending_exception (exc);
853 size *= array->max_length;
854 field_data = mono_field_get_data (field_handle);
856 if (size > mono_type_size (field_handle->type, &align)) {
857 MonoException *exc = mono_get_exception_argument("field_handle",
858 "Field not large enough to fill array");
859 mono_set_pending_exception (exc);
863 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
865 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
866 guint ## n *src = (guint ## n *) field_data; \
868 nEnt = (size / sizeof(guint ## n)); \
870 for (i = 0; i < nEnt; i++) { \
871 data[i] = read ## n (&src[i]); \
875 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
877 switch (type->type) {
894 memcpy (mono_array_addr (array, char, 0), field_data, size);
898 memcpy (mono_array_addr (array, char, 0), field_data, size);
903 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
905 return offsetof (MonoString, chars);
908 ICALL_EXPORT MonoObject *
909 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
911 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
915 MonoObject *ret = mono_object_clone_checked (obj, &error);
916 mono_error_set_pending_exception (&error);
923 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
929 MONO_CHECK_ARG_NULL (handle,);
931 klass = mono_class_from_mono_type (handle);
932 MONO_CHECK_ARG (handle, klass,);
934 if (klass->generic_container)
937 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
938 if (!is_ok (&error)) {
939 mono_error_set_pending_exception (&error);
943 /* This will call the type constructor */
944 if (!mono_runtime_class_init_full (vtable, &error))
945 mono_error_set_pending_exception (&error);
949 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
953 mono_image_check_for_module_cctor (image);
954 if (image->has_module_cctor) {
955 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
956 if (!mono_error_ok (&error)) {
957 mono_error_set_pending_exception (&error);
960 /*It's fine to raise the exception here*/
961 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
962 if (!is_ok (&error)) {
963 mono_error_set_pending_exception (&error);
966 if (!mono_runtime_class_init_full (vtable, &error))
967 mono_error_set_pending_exception (&error);
971 ICALL_EXPORT MonoBoolean
972 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
977 /* later make this configurable and per-arch */
978 int min_size = 4096 * 4 * sizeof (void*);
979 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
980 /* if we have no info we are optimistic and assume there is enough room */
984 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
988 current = (guint8 *)&stack_addr;
989 if (current > stack_addr) {
990 if ((current - stack_addr) < min_size)
993 if (current - (stack_addr - stack_size) < min_size)
999 ICALL_EXPORT MonoObject *
1000 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
1003 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
1004 mono_error_set_pending_exception (&error);
1010 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1014 MonoObject **values = NULL;
1017 gint32 result = (int)(gsize)mono_defaults.int32_class;
1018 MonoClassField* field;
1021 klass = mono_object_class (this_obj);
1023 if (mono_class_num_fields (klass) == 0)
1027 * Compute the starting value of the hashcode for fields of primitive
1028 * types, and return the remaining fields in an array to the managed side.
1029 * This way, we can avoid costly reflection operations in managed code.
1032 while ((field = mono_class_get_fields (klass, &iter))) {
1033 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1035 if (mono_field_is_deleted (field))
1037 /* FIXME: Add more types */
1038 switch (field->type->type) {
1040 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1042 case MONO_TYPE_STRING: {
1044 s = *(MonoString**)((guint8*)this_obj + field->offset);
1046 result ^= mono_string_hash (s);
1051 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1052 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1053 if (!is_ok (&error)) {
1054 mono_error_set_pending_exception (&error);
1057 values [count++] = o;
1063 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1064 if (mono_error_set_pending_exception (&error))
1066 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1067 for (i = 0; i < count; ++i)
1068 mono_array_setref (*fields, i, values [i]);
1075 ICALL_EXPORT MonoBoolean
1076 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1080 MonoObject **values = NULL;
1082 MonoClassField* field;
1086 MONO_CHECK_ARG_NULL (that, FALSE);
1088 if (this_obj->vtable != that->vtable)
1091 klass = mono_object_class (this_obj);
1093 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1094 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1097 * Do the comparison for fields of primitive type and return a result if
1098 * possible. Otherwise, return the remaining fields in an array to the
1099 * managed side. This way, we can avoid costly reflection operations in
1104 while ((field = mono_class_get_fields (klass, &iter))) {
1105 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1107 if (mono_field_is_deleted (field))
1109 /* FIXME: Add more types */
1110 switch (field->type->type) {
1113 case MONO_TYPE_BOOLEAN:
1114 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1119 case MONO_TYPE_CHAR:
1120 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1125 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1130 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1134 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1138 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1143 case MONO_TYPE_STRING: {
1144 MonoString *s1, *s2;
1145 guint32 s1len, s2len;
1146 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1147 s2 = *(MonoString**)((guint8*)that + field->offset);
1150 if ((s1 == NULL) || (s2 == NULL))
1152 s1len = mono_string_length (s1);
1153 s2len = mono_string_length (s2);
1157 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1163 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1164 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1165 if (!is_ok (&error)) {
1166 mono_error_set_pending_exception (&error);
1169 values [count++] = o;
1170 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1171 if (!is_ok (&error)) {
1172 mono_error_set_pending_exception (&error);
1175 values [count++] = o;
1178 if (klass->enumtype)
1179 /* enums only have one non-static field */
1185 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1186 if (mono_error_set_pending_exception (&error))
1188 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1189 for (i = 0; i < count; ++i)
1190 mono_array_setref_fast (*fields, i, values [i]);
1197 ICALL_EXPORT MonoReflectionType *
1198 ves_icall_System_Object_GetType (MonoObject *obj)
1201 MonoReflectionType *ret;
1202 #ifndef DISABLE_REMOTING
1203 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1204 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1207 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1209 mono_error_set_pending_exception (&error);
1214 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1216 MONO_CHECK_ARG_NULL (obj, 0);
1219 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1220 mono_error_set_pending_exception (&error);
1225 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1226 MonoReflectionMethod *method,
1227 MonoArray *opt_param_types)
1229 MONO_CHECK_ARG_NULL (method, 0);
1232 gint32 result = mono_image_create_method_token (
1233 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1234 mono_error_set_pending_exception (&error);
1239 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1242 mono_image_create_pefile (mb, file, &error);
1243 mono_error_set_pending_exception (&error);
1247 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1250 mono_image_build_metadata (mb, &error);
1251 mono_error_set_pending_exception (&error);
1255 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1257 mono_image_register_token (mb->dynamic_image, token, obj);
1260 ICALL_EXPORT MonoObject*
1261 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1265 mono_loader_lock ();
1266 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1267 mono_loader_unlock ();
1272 ICALL_EXPORT MonoReflectionModule*
1273 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1276 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1277 mono_error_set_pending_exception (&error);
1282 * ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class:
1283 * @tb: a TypeBuilder object
1286 * Creates the generic class after all generic parameters have been added.
1289 ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class (MonoReflectionTypeBuilder *tb)
1292 (void) mono_reflection_create_generic_class (tb, &error);
1293 mono_error_set_pending_exception (&error);
1296 #ifndef DISABLE_REFLECTION_EMIT
1297 ICALL_EXPORT MonoArray*
1298 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
1301 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
1302 mono_error_set_pending_exception (&error);
1308 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1310 MonoMethod **dest = (MonoMethod **)data;
1312 /* skip unmanaged frames */
1317 if (!strcmp (m->klass->name_space, "System.Reflection"))
1326 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1328 MonoMethod **dest = (MonoMethod **)data;
1330 /* skip unmanaged frames */
1334 if (m->wrapper_type != MONO_WRAPPER_NONE)
1342 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1353 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1355 MonoMethod **dest = (MonoMethod **)data;
1357 /* skip unmanaged frames */
1361 if (m->wrapper_type != MONO_WRAPPER_NONE)
1369 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1370 || (!strcmp (m->klass->name_space, "System"))))
1380 static MonoReflectionType *
1381 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1383 MonoMethod *m, *dest;
1385 MonoType *type = NULL;
1386 MonoAssembly *assembly = NULL;
1387 gboolean type_resolve = FALSE;
1388 MonoImage *rootimage = NULL;
1390 mono_error_init (error);
1393 * We must compute the calling assembly as type loading must happen under a metadata context.
1394 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1395 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1397 m = mono_method_get_last_managed ();
1399 if (m && m->klass->image != mono_defaults.corlib) {
1400 /* Happens with inlining */
1402 /* Ugly hack: type_from_parsed_name is called from
1403 * System.Type.internal_from_name, which is called most
1404 * directly from System.Type.GetType(string,bool,bool) but
1405 * also indirectly from places such as
1406 * System.Type.GetType(string,func,func) (via
1407 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1408 * so we need to skip over all of those to find the true caller.
1410 * It would be nice if we had stack marks.
1412 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1418 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1419 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1420 * to crash. This only seems to happen in some strange remoting
1421 * scenarios and I was unable to figure out what's happening there.
1422 * Dec 10, 2005 - Martin.
1426 assembly = dest->klass->image->assembly;
1427 type_resolve = TRUE;
1428 rootimage = assembly->image;
1430 g_warning (G_STRLOC);
1433 if (info->assembly.name)
1434 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1437 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1438 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1439 return_val_if_nok (error, NULL);
1443 // Say we're looking for System.Generic.Dict<int, Local>
1444 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1445 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1446 // is messed up when we go to construct the Local as the type arg...
1448 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1449 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1450 if (!info->assembly.name && !type) {
1452 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1453 return_val_if_nok (error, NULL);
1455 if (assembly && !type && type_resolve) {
1456 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1457 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1458 return_val_if_nok (error, NULL);
1464 return mono_type_get_object_checked (mono_domain_get (), type, error);
1467 ICALL_EXPORT MonoReflectionType*
1468 ves_icall_System_Type_internal_from_name (MonoString *name,
1469 MonoBoolean throwOnError,
1470 MonoBoolean ignoreCase)
1473 MonoTypeNameParse info;
1474 MonoReflectionType *type = NULL;
1477 char *str = mono_string_to_utf8_checked (name, &error);
1478 if (!is_ok (&error))
1481 parsedOk = mono_reflection_parse_type (str, &info);
1483 /* mono_reflection_parse_type() mangles the string */
1485 mono_reflection_free_type_info (&info);
1487 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1491 type = type_from_parsed_name (&info, ignoreCase, &error);
1493 mono_reflection_free_type_info (&info);
1495 if (!is_ok (&error))
1500 mono_error_set_type_load_name (&error, g_strdup (str), NULL, "");
1507 if (!is_ok (&error)) {
1509 mono_error_set_pending_exception (&error);
1511 mono_error_cleanup (&error);
1519 ICALL_EXPORT MonoReflectionType*
1520 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1523 MonoReflectionType *ret;
1524 MonoDomain *domain = mono_domain_get ();
1526 ret = mono_type_get_object_checked (domain, handle, &error);
1527 mono_error_set_pending_exception (&error);
1532 ICALL_EXPORT MonoType*
1533 ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass)
1535 return mono_class_get_type (klass);
1538 /* System.TypeCode */
1557 TYPECODE_STRING = 18
1560 ICALL_EXPORT guint32
1561 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1563 int t = type->type->type;
1565 if (type->type->byref)
1566 return TYPECODE_OBJECT;
1570 case MONO_TYPE_VOID:
1571 return TYPECODE_OBJECT;
1572 case MONO_TYPE_BOOLEAN:
1573 return TYPECODE_BOOLEAN;
1575 return TYPECODE_BYTE;
1577 return TYPECODE_SBYTE;
1579 return TYPECODE_UINT16;
1581 return TYPECODE_INT16;
1582 case MONO_TYPE_CHAR:
1583 return TYPECODE_CHAR;
1587 return TYPECODE_OBJECT;
1589 return TYPECODE_UINT32;
1591 return TYPECODE_INT32;
1593 return TYPECODE_UINT64;
1595 return TYPECODE_INT64;
1597 return TYPECODE_SINGLE;
1599 return TYPECODE_DOUBLE;
1600 case MONO_TYPE_VALUETYPE: {
1601 MonoClass *klass = type->type->data.klass;
1603 if (klass->enumtype) {
1604 t = mono_class_enum_basetype (klass)->type;
1606 } else if (mono_is_corlib_image (klass->image)) {
1607 if (strcmp (klass->name_space, "System") == 0) {
1608 if (strcmp (klass->name, "Decimal") == 0)
1609 return TYPECODE_DECIMAL;
1610 else if (strcmp (klass->name, "DateTime") == 0)
1611 return TYPECODE_DATETIME;
1614 return TYPECODE_OBJECT;
1616 case MONO_TYPE_STRING:
1617 return TYPECODE_STRING;
1618 case MONO_TYPE_SZARRAY:
1619 case MONO_TYPE_ARRAY:
1620 case MONO_TYPE_OBJECT:
1622 case MONO_TYPE_MVAR:
1623 case MONO_TYPE_TYPEDBYREF:
1624 return TYPECODE_OBJECT;
1625 case MONO_TYPE_CLASS:
1627 MonoClass *klass = type->type->data.klass;
1628 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1629 if (strcmp (klass->name, "DBNull") == 0)
1630 return TYPECODE_DBNULL;
1633 return TYPECODE_OBJECT;
1634 case MONO_TYPE_GENERICINST:
1635 return TYPECODE_OBJECT;
1637 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1643 mono_type_is_primitive (MonoType *type)
1645 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1646 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1650 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1652 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1653 return mono_class_enum_basetype (type->data.klass);
1654 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1655 return mono_class_enum_basetype (type->data.generic_class->container_class);
1659 ICALL_EXPORT guint32
1660 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1665 g_assert (type != NULL);
1667 klass = mono_class_from_mono_type (type->type);
1668 klassc = mono_class_from_mono_type (c->type);
1670 if (type->type->byref ^ c->type->byref)
1673 if (type->type->byref) {
1674 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1675 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1677 klass = mono_class_from_mono_type (t);
1678 klassc = mono_class_from_mono_type (ot);
1680 if (mono_type_is_primitive (t)) {
1681 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1682 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1683 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1684 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1685 return t->type == ot->type;
1687 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1690 if (klass->valuetype)
1691 return klass == klassc;
1692 return klass->valuetype == klassc->valuetype;
1695 return mono_class_is_assignable_from (klass, klassc);
1698 ICALL_EXPORT guint32
1699 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1702 MonoClass *klass = mono_class_from_mono_type (type->type);
1703 mono_class_init_checked (klass, &error);
1704 if (!is_ok (&error)) {
1705 mono_error_set_pending_exception (&error);
1708 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1709 mono_error_set_pending_exception (&error);
1713 ICALL_EXPORT guint32
1714 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1716 MonoClass *klass = mono_class_from_mono_type (type->type);
1717 return klass->flags;
1720 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1721 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1724 MonoClass *klass = field->field->parent;
1725 MonoMarshalType *info;
1729 if (klass->generic_container ||
1730 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1733 ftype = mono_field_get_type (field->field);
1734 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1737 info = mono_marshal_load_type_info (klass);
1739 for (i = 0; i < info->num_fields; ++i) {
1740 if (info->fields [i].field == field->field) {
1741 if (!info->fields [i].mspec)
1744 MonoReflectionMarshalAsAttribute* obj;
1745 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1746 if (!mono_error_ok (&error))
1747 mono_error_set_pending_exception (&error);
1756 ICALL_EXPORT MonoReflectionField*
1757 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1760 gboolean found = FALSE;
1767 klass = handle->parent;
1769 klass = mono_class_from_mono_type (type);
1771 /* Check that the field belongs to the class */
1772 for (k = klass; k; k = k->parent) {
1773 if (k == handle->parent) {
1780 /* The managed code will throw the exception */
1784 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1785 mono_error_set_pending_exception (&error);
1789 ICALL_EXPORT MonoArray*
1790 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1793 MonoType *type = mono_field_get_type_checked (field->field, &error);
1796 if (!mono_error_ok (&error)) {
1797 mono_error_set_pending_exception (&error);
1801 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1802 mono_error_set_pending_exception (&error);
1807 vell_icall_get_method_attributes (MonoMethod *method)
1809 return method->flags;
1813 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1816 MonoReflectionType *rt;
1817 MonoDomain *domain = mono_domain_get ();
1818 MonoMethodSignature* sig;
1820 sig = mono_method_signature_checked (method, &error);
1821 if (!mono_error_ok (&error)) {
1822 mono_error_set_pending_exception (&error);
1826 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1827 if (!mono_error_ok (&error)) {
1828 mono_error_set_pending_exception (&error);
1832 MONO_STRUCT_SETREF (info, parent, rt);
1834 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1835 if (!mono_error_ok (&error)) {
1836 mono_error_set_pending_exception (&error);
1840 MONO_STRUCT_SETREF (info, ret, rt);
1842 info->attrs = method->flags;
1843 info->implattrs = method->iflags;
1844 if (sig->call_convention == MONO_CALL_DEFAULT)
1845 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1847 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1852 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1855 ICALL_EXPORT MonoArray*
1856 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1859 MonoDomain *domain = mono_domain_get ();
1861 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1862 mono_error_set_pending_exception (&error);
1866 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1867 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1870 MonoDomain *domain = mono_domain_get ();
1871 MonoReflectionMarshalAsAttribute* res = NULL;
1872 MonoMarshalSpec **mspecs;
1875 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1876 mono_method_get_marshal_info (method, mspecs);
1879 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1880 if (!mono_error_ok (&error)) {
1881 mono_error_set_pending_exception (&error);
1886 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1888 mono_metadata_free_marshal_spec (mspecs [i]);
1895 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1897 MonoClass *parent = field->field->parent;
1898 if (!parent->size_inited)
1899 mono_class_init (parent);
1900 mono_class_setup_fields_locking (parent);
1902 return field->field->offset - sizeof (MonoObject);
1905 ICALL_EXPORT MonoReflectionType*
1906 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1909 MonoReflectionType *ret;
1912 parent = declaring? field->field->parent: field->klass;
1914 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1915 mono_error_set_pending_exception (&error);
1921 ICALL_EXPORT MonoObject *
1922 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1925 MonoClass *fklass = field->klass;
1926 MonoClassField *cf = field->field;
1927 MonoDomain *domain = mono_object_domain (field);
1929 if (fklass->image->assembly->ref_only) {
1930 mono_set_pending_exception (mono_get_exception_invalid_operation (
1931 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1935 if (mono_security_core_clr_enabled () &&
1936 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1937 mono_error_set_pending_exception (&error);
1941 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1942 mono_error_set_pending_exception (&error);
1947 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1950 MonoClassField *cf = field->field;
1954 if (field->klass->image->assembly->ref_only) {
1955 mono_set_pending_exception (mono_get_exception_invalid_operation (
1956 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1960 if (mono_security_core_clr_enabled () &&
1961 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1962 mono_error_set_pending_exception (&error);
1966 type = mono_field_get_type_checked (cf, &error);
1967 if (!mono_error_ok (&error)) {
1968 mono_error_set_pending_exception (&error);
1972 v = (gchar *) value;
1974 switch (type->type) {
1977 case MONO_TYPE_BOOLEAN:
1980 case MONO_TYPE_CHAR:
1989 case MONO_TYPE_VALUETYPE:
1992 v += sizeof (MonoObject);
1994 case MONO_TYPE_STRING:
1995 case MONO_TYPE_OBJECT:
1996 case MONO_TYPE_CLASS:
1997 case MONO_TYPE_ARRAY:
1998 case MONO_TYPE_SZARRAY:
2001 case MONO_TYPE_GENERICINST: {
2002 MonoGenericClass *gclass = type->data.generic_class;
2003 g_assert (!gclass->context.class_inst->is_open);
2005 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
2006 MonoClass *nklass = mono_class_from_mono_type (type);
2007 MonoObject *nullable;
2010 * Convert the boxed vtype into a Nullable structure.
2011 * This is complicated by the fact that Nullables have
2012 * a variable structure.
2014 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2015 if (!mono_error_ok (&error)) {
2016 mono_error_set_pending_exception (&error);
2020 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2022 v = (gchar *)mono_object_unbox (nullable);
2025 if (gclass->container_class->valuetype && (v != NULL))
2026 v += sizeof (MonoObject);
2030 g_error ("type 0x%x not handled in "
2031 "ves_icall_FieldInfo_SetValueInternal", type->type);
2036 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2037 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2038 if (!is_ok (&error)) {
2039 mono_error_set_pending_exception (&error);
2042 if (!vtable->initialized) {
2043 if (!mono_runtime_class_init_full (vtable, &error)) {
2044 mono_error_set_pending_exception (&error);
2048 mono_field_static_set_value (vtable, cf, v);
2050 mono_field_set_value (obj, cf, v);
2055 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2064 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2065 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2069 if (MONO_TYPE_IS_REFERENCE (f->type))
2070 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2072 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2075 ICALL_EXPORT MonoObject *
2076 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2078 MonoObject *o = NULL;
2079 MonoClassField *field = rfield->field;
2081 MonoDomain *domain = mono_object_domain (rfield);
2083 MonoTypeEnum def_type;
2084 const char *def_value;
2088 mono_class_init (field->parent);
2090 t = mono_field_get_type_checked (field, &error);
2091 if (!mono_error_ok (&error)) {
2092 mono_error_set_pending_exception (&error);
2096 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2097 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2101 if (image_is_dynamic (field->parent->image)) {
2102 MonoClass *klass = field->parent;
2103 int fidx = field - klass->fields;
2105 g_assert (fidx >= 0 && fidx < klass->field.count);
2106 g_assert (klass->ext);
2107 g_assert (klass->ext->field_def_values);
2108 def_type = klass->ext->field_def_values [fidx].def_type;
2109 def_value = klass->ext->field_def_values [fidx].data;
2110 if (def_type == MONO_TYPE_END) {
2111 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2115 def_value = mono_class_get_field_default_value (field, &def_type);
2116 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2118 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2123 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2127 case MONO_TYPE_BOOLEAN:
2130 case MONO_TYPE_CHAR:
2138 case MONO_TYPE_R8: {
2141 /* boxed value type */
2142 t = g_new0 (MonoType, 1);
2144 klass = mono_class_from_mono_type (t);
2146 o = mono_object_new_checked (domain, klass, &error);
2147 if (!mono_error_ok (&error)) {
2148 mono_error_set_pending_exception (&error);
2151 v = ((gchar *) o) + sizeof (MonoObject);
2152 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2153 if (mono_error_set_pending_exception (&error))
2157 case MONO_TYPE_STRING:
2158 case MONO_TYPE_CLASS:
2159 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2160 if (mono_error_set_pending_exception (&error))
2164 g_assert_not_reached ();
2170 ICALL_EXPORT MonoReflectionType*
2171 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2174 MonoReflectionType *ret;
2177 type = mono_field_get_type_checked (ref_field->field, &error);
2178 if (!mono_error_ok (&error)) {
2179 mono_error_set_pending_exception (&error);
2183 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2184 if (!mono_error_ok (&error)) {
2185 mono_error_set_pending_exception (&error);
2192 /* From MonoProperty.cs */
2194 PInfo_Attributes = 1,
2195 PInfo_GetMethod = 1 << 1,
2196 PInfo_SetMethod = 1 << 2,
2197 PInfo_ReflectedType = 1 << 3,
2198 PInfo_DeclaringType = 1 << 4,
2203 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2206 MonoReflectionType *rt;
2207 MonoReflectionMethod *rm;
2208 MonoDomain *domain = mono_object_domain (property);
2209 const MonoProperty *pproperty = property->property;
2211 if ((req_info & PInfo_ReflectedType) != 0) {
2212 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2213 if (mono_error_set_pending_exception (&error))
2216 MONO_STRUCT_SETREF (info, parent, rt);
2218 if ((req_info & PInfo_DeclaringType) != 0) {
2219 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2220 if (mono_error_set_pending_exception (&error))
2223 MONO_STRUCT_SETREF (info, declaring_type, rt);
2226 if ((req_info & PInfo_Name) != 0)
2227 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2229 if ((req_info & PInfo_Attributes) != 0)
2230 info->attrs = pproperty->attrs;
2232 if ((req_info & PInfo_GetMethod) != 0) {
2233 if (pproperty->get &&
2234 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2235 pproperty->get->klass == property->klass)) {
2236 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2237 if (mono_error_set_pending_exception (&error))
2243 MONO_STRUCT_SETREF (info, get, rm);
2245 if ((req_info & PInfo_SetMethod) != 0) {
2246 if (pproperty->set &&
2247 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2248 pproperty->set->klass == property->klass)) {
2249 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2250 if (mono_error_set_pending_exception (&error))
2256 MONO_STRUCT_SETREF (info, set, rm);
2259 * There may be other methods defined for properties, though, it seems they are not exposed
2260 * in the reflection API
2265 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2268 MonoReflectionType *rt;
2269 MonoReflectionMethod *rm;
2270 MonoDomain *domain = mono_object_domain (event);
2272 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2273 if (mono_error_set_pending_exception (&error))
2276 MONO_STRUCT_SETREF (info, reflected_type, rt);
2278 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2279 if (mono_error_set_pending_exception (&error))
2282 MONO_STRUCT_SETREF (info, declaring_type, rt);
2284 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2285 info->attrs = event->event->attrs;
2287 if (event->event->add) {
2288 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2289 if (mono_error_set_pending_exception (&error))
2295 MONO_STRUCT_SETREF (info, add_method, rm);
2297 if (event->event->remove) {
2298 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2299 if (mono_error_set_pending_exception (&error))
2305 MONO_STRUCT_SETREF (info, remove_method, rm);
2307 if (event->event->raise) {
2308 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2309 if (mono_error_set_pending_exception (&error))
2315 MONO_STRUCT_SETREF (info, raise_method, rm);
2317 #ifndef MONO_SMALL_CONFIG
2318 if (event->event->other) {
2320 while (event->event->other [n])
2322 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2323 if (mono_error_set_pending_exception (&error))
2325 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2327 for (i = 0; i < n; i++) {
2328 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2329 if (mono_error_set_pending_exception (&error))
2331 mono_array_setref (info->other_methods, i, rm);
2338 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2343 mono_class_setup_interfaces (klass, error);
2344 if (!mono_error_ok (error))
2347 for (i = 0; i < klass->interface_count; i++) {
2348 ic = klass->interfaces [i];
2349 g_hash_table_insert (ifaces, ic, ic);
2351 collect_interfaces (ic, ifaces, error);
2352 if (!mono_error_ok (error))
2358 MonoArray *iface_array;
2359 MonoGenericContext *context;
2363 } FillIfaceArrayData;
2366 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2368 MonoReflectionType *rt;
2369 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2370 MonoClass *ic = (MonoClass *)key;
2371 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2373 if (!mono_error_ok (data->error))
2376 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2377 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2378 if (!mono_error_ok (data->error))
2382 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2383 if (!mono_error_ok (data->error))
2386 mono_array_setref (data->iface_array, data->next_idx++, rt);
2389 mono_metadata_free_type (inflated);
2393 get_interfaces_hash (gconstpointer v1)
2395 MonoClass *k = (MonoClass*)v1;
2397 return k->type_token;
2400 ICALL_EXPORT MonoArray*
2401 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2404 MonoClass *klass = mono_class_from_mono_type (type->type);
2406 FillIfaceArrayData data = { 0 };
2409 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2411 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2412 data.context = mono_class_get_context (klass);
2413 klass = klass->generic_class->container_class;
2416 for (parent = klass; parent; parent = parent->parent) {
2417 mono_class_setup_interfaces (parent, &error);
2418 if (!mono_error_ok (&error))
2420 collect_interfaces (parent, iface_hash, &error);
2421 if (!mono_error_ok (&error))
2425 data.error = &error;
2426 data.domain = mono_object_domain (type);
2428 len = g_hash_table_size (iface_hash);
2430 g_hash_table_destroy (iface_hash);
2431 if (!data.domain->empty_types) {
2432 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2433 if (!is_ok (&error))
2436 return data.domain->empty_types;
2439 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2440 if (!is_ok (&error))
2442 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2443 if (!mono_error_ok (&error))
2446 g_hash_table_destroy (iface_hash);
2447 return data.iface_array;
2450 g_hash_table_destroy (iface_hash);
2451 mono_error_set_pending_exception (&error);
2456 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2458 gboolean variance_used;
2459 MonoClass *klass = mono_class_from_mono_type (type->type);
2460 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2461 MonoReflectionMethod *member;
2464 int i = 0, len, ioffset;
2468 mono_class_init_checked (klass, &error);
2469 if (mono_error_set_pending_exception (&error))
2471 mono_class_init_checked (iclass, &error);
2472 if (mono_error_set_pending_exception (&error))
2475 mono_class_setup_vtable (klass);
2477 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2481 len = mono_class_num_methods (iclass);
2482 domain = mono_object_domain (type);
2483 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2484 if (mono_error_set_pending_exception (&error))
2486 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2487 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2488 if (mono_error_set_pending_exception (&error))
2490 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2492 while ((method = mono_class_get_methods (iclass, &iter))) {
2493 member = mono_method_get_object_checked (domain, method, iclass, &error);
2494 if (mono_error_set_pending_exception (&error))
2496 mono_array_setref (*methods, i, member);
2497 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2498 if (mono_error_set_pending_exception (&error))
2500 mono_array_setref (*targets, i, member);
2507 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2510 MonoClass *klass = mono_class_from_mono_type (type->type);
2512 mono_class_init_checked (klass, &error);
2513 if (mono_error_set_pending_exception (&error))
2516 if (image_is_dynamic (klass->image)) {
2517 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2518 *packing = tb->packing_size;
2519 *size = tb->class_size;
2521 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2525 ICALL_EXPORT MonoReflectionType*
2526 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2529 MonoReflectionType *ret;
2532 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2533 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2534 mono_error_set_pending_exception (&error);
2538 klass = mono_class_from_mono_type (type->type);
2539 mono_class_init_checked (klass, &error);
2540 if (mono_error_set_pending_exception (&error))
2544 // GetElementType should only return a type for:
2545 // Array Pointer PassedByRef
2546 if (type->type->byref)
2547 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2548 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2549 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2550 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2551 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2555 mono_error_set_pending_exception (&error);
2560 ICALL_EXPORT MonoReflectionType*
2561 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2564 MonoReflectionType *ret;
2566 if (type->type->byref)
2569 MonoClass *klass = mono_class_from_mono_type (type->type);
2573 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2574 mono_error_set_pending_exception (&error);
2579 ICALL_EXPORT MonoBoolean
2580 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2582 return type->type->type == MONO_TYPE_PTR;
2585 ICALL_EXPORT MonoBoolean
2586 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2588 return (!type->type->byref && (((type->type->type >= MONO_TYPE_BOOLEAN) && (type->type->type <= MONO_TYPE_R8)) || (type->type->type == MONO_TYPE_I) || (type->type->type == MONO_TYPE_U)));
2591 ICALL_EXPORT MonoBoolean
2592 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2594 return type->type->byref;
2597 ICALL_EXPORT MonoBoolean
2598 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2601 MonoClass *klass = mono_class_from_mono_type (type->type);
2602 mono_class_init_checked (klass, &error);
2603 if (mono_error_set_pending_exception (&error))
2606 return mono_class_is_com_object (klass);
2609 ICALL_EXPORT guint32
2610 ves_icall_reflection_get_token (MonoObject* obj)
2613 guint32 result = mono_reflection_get_token_checked (obj, &error);
2614 mono_error_set_pending_exception (&error);
2618 ICALL_EXPORT MonoReflectionModule*
2619 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2622 MonoReflectionModule *result = NULL;
2623 MonoClass *klass = mono_class_from_mono_type (type->type);
2624 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2625 mono_error_set_pending_exception (&error);
2629 ICALL_EXPORT MonoReflectionAssembly*
2630 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2633 MonoDomain *domain = mono_domain_get ();
2634 MonoClass *klass = mono_class_from_mono_type (type->type);
2635 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2636 mono_error_set_pending_exception (&error);
2640 ICALL_EXPORT MonoReflectionType*
2641 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2644 MonoReflectionType *ret;
2645 MonoDomain *domain = mono_domain_get ();
2648 if (type->type->byref)
2650 if (type->type->type == MONO_TYPE_VAR) {
2651 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2652 klass = param ? param->owner.klass : NULL;
2653 } else if (type->type->type == MONO_TYPE_MVAR) {
2654 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2655 klass = param ? param->owner.method->klass : NULL;
2657 klass = mono_class_from_mono_type (type->type)->nested_in;
2663 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2664 mono_error_set_pending_exception (&error);
2669 ICALL_EXPORT MonoString*
2670 ves_icall_RuntimeType_get_Name (MonoReflectionType *type)
2672 MonoDomain *domain = mono_domain_get ();
2673 MonoClass *klass = mono_class_from_mono_type (type->type);
2675 if (type->type->byref) {
2676 char *n = g_strdup_printf ("%s&", klass->name);
2677 MonoString *res = mono_string_new (domain, n);
2683 return mono_string_new (domain, klass->name);
2687 ICALL_EXPORT MonoString*
2688 ves_icall_RuntimeType_get_Namespace (MonoReflectionType *type)
2690 MonoDomain *domain = mono_domain_get ();
2691 MonoClass *klass = mono_class_from_mono_type (type->type);
2693 while (klass->nested_in)
2694 klass = klass->nested_in;
2696 if (klass->name_space [0] == '\0')
2699 return mono_string_new (domain, klass->name_space);
2703 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2707 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2708 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2712 klass = mono_class_from_mono_type (type->type);
2718 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2720 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2723 ICALL_EXPORT MonoArray*
2724 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2727 MonoReflectionType *rt;
2729 MonoClass *klass, *pklass;
2730 MonoDomain *domain = mono_object_domain (type);
2733 klass = mono_class_from_mono_type (type->type);
2735 if (klass->generic_container) {
2736 MonoGenericContainer *container = klass->generic_container;
2737 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2738 if (mono_error_set_pending_exception (&error))
2740 for (i = 0; i < container->type_argc; ++i) {
2741 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2743 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2744 if (mono_error_set_pending_exception (&error))
2747 mono_array_setref (res, i, rt);
2749 } else if (klass->generic_class) {
2750 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2751 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2752 if (mono_error_set_pending_exception (&error))
2754 for (i = 0; i < inst->type_argc; ++i) {
2755 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2756 if (mono_error_set_pending_exception (&error))
2759 mono_array_setref (res, i, rt);
2767 ICALL_EXPORT gboolean
2768 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2772 if (!IS_MONOTYPE (type))
2775 if (type->type->byref)
2778 klass = mono_class_from_mono_type (type->type);
2779 return klass->generic_container != NULL;
2782 ICALL_EXPORT MonoReflectionType*
2783 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2786 MonoReflectionType *ret;
2789 if (type->type->byref)
2792 klass = mono_class_from_mono_type (type->type);
2794 if (klass->generic_container) {
2795 return type; /* check this one */
2797 if (klass->generic_class) {
2798 MonoClass *generic_class = klass->generic_class->container_class;
2801 tb = mono_class_get_ref_info (generic_class);
2803 if (generic_class->wastypebuilder && tb)
2804 return (MonoReflectionType *)tb;
2806 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2807 mono_error_set_pending_exception (&error);
2815 ICALL_EXPORT MonoReflectionType*
2816 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2819 MonoReflectionType *ret;
2821 MonoType *geninst, **types;
2824 g_assert (IS_MONOTYPE (type));
2825 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2826 if (mono_error_set_pending_exception (&error))
2829 count = mono_array_length (type_array);
2830 types = g_new0 (MonoType *, count);
2832 for (i = 0; i < count; i++) {
2833 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2834 types [i] = t->type;
2837 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2840 mono_error_set_pending_exception (&error);
2844 klass = mono_class_from_mono_type (geninst);
2846 /*we might inflate to the GTD*/
2847 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2848 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2852 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2853 mono_error_set_pending_exception (&error);
2858 ICALL_EXPORT gboolean
2859 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2863 if (!IS_MONOTYPE (type))
2866 if (type->type->byref)
2869 klass = mono_class_from_mono_type (type->type);
2870 return klass->generic_class != NULL || klass->generic_container != NULL;
2874 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2876 if (!IS_MONOTYPE (type))
2879 if (is_generic_parameter (type->type))
2880 return mono_type_get_generic_param_num (type->type);
2884 ICALL_EXPORT MonoGenericParamInfo *
2885 ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionType *type)
2887 return mono_generic_param_info (type->type->data.generic_param);
2890 ICALL_EXPORT MonoBoolean
2891 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2893 return is_generic_parameter (type->type);
2896 ICALL_EXPORT MonoBoolean
2897 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2899 return is_generic_parameter (tb->type.type);
2903 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2904 MonoReflectionType *t)
2906 enumtype->type = t->type;
2909 ICALL_EXPORT MonoReflectionMethod*
2910 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2911 MonoReflectionMethod* generic)
2918 MonoReflectionMethod *ret = NULL;
2920 domain = ((MonoObject *)type)->vtable->domain;
2922 klass = mono_class_from_mono_type (type->type);
2923 mono_class_init_checked (klass, &error);
2924 if (mono_error_set_pending_exception (&error))
2928 while ((method = mono_class_get_methods (klass, &iter))) {
2929 if (method->token == generic->method->token) {
2930 ret = mono_method_get_object_checked (domain, method, klass, &error);
2931 if (mono_error_set_pending_exception (&error))
2939 ICALL_EXPORT MonoReflectionMethod *
2940 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
2943 MonoType *type = ref_type->type;
2945 MonoReflectionMethod *ret = NULL;
2947 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2948 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2951 if (type->type == MONO_TYPE_VAR)
2954 method = mono_type_get_generic_param_owner (type)->owner.method;
2957 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2958 if (!mono_error_ok (&error))
2959 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2963 ICALL_EXPORT MonoBoolean
2964 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2966 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2970 ICALL_EXPORT MonoBoolean
2971 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2973 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2978 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2980 MonoDomain *domain = mono_domain_get ();
2981 MonoImage *image = method->method->klass->image;
2982 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2983 MonoTableInfo *tables = image->tables;
2984 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2985 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2986 guint32 im_cols [MONO_IMPLMAP_SIZE];
2987 guint32 scope_token;
2988 const char *import = NULL;
2989 const char *scope = NULL;
2991 if (image_is_dynamic (image)) {
2992 MonoReflectionMethodAux *method_aux =
2993 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2995 import = method_aux->dllentry;
2996 scope = method_aux->dll;
2999 if (!import || !scope) {
3000 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
3005 if (piinfo->implmap_idx) {
3006 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
3008 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
3009 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
3010 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
3011 scope = mono_metadata_string_heap (image, scope_token);
3015 *flags = piinfo->piflags;
3016 *entry_point = mono_string_new (domain, import);
3017 *dll_name = mono_string_new (domain, scope);
3020 ICALL_EXPORT MonoReflectionMethod *
3021 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3023 MonoMethodInflated *imethod;
3025 MonoReflectionMethod *ret = NULL;
3028 if (method->method->is_generic)
3031 if (!method->method->is_inflated)
3034 imethod = (MonoMethodInflated *) method->method;
3036 result = imethod->declaring;
3037 /* Not a generic method. */
3038 if (!result->is_generic)
3041 if (image_is_dynamic (method->method->klass->image)) {
3042 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3043 MonoReflectionMethod *res;
3046 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3047 * the dynamic case as well ?
3049 mono_image_lock ((MonoImage*)image);
3050 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3051 mono_image_unlock ((MonoImage*)image);
3057 if (imethod->context.class_inst) {
3058 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3059 /*Generic methods gets the context of the GTD.*/
3060 if (mono_class_get_context (klass)) {
3061 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3062 if (!mono_error_ok (&error))
3067 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3069 if (!mono_error_ok (&error))
3070 mono_error_set_pending_exception (&error);
3074 ICALL_EXPORT gboolean
3075 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3077 return mono_method_signature (method->method)->generic_param_count != 0;
3080 ICALL_EXPORT gboolean
3081 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3083 return method->method->is_generic;
3086 ICALL_EXPORT MonoArray*
3087 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3090 MonoReflectionType *rt;
3095 domain = mono_object_domain (method);
3097 if (method->method->is_inflated) {
3098 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3101 count = inst->type_argc;
3102 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3103 if (mono_error_set_pending_exception (&error))
3106 for (i = 0; i < count; i++) {
3107 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3108 if (mono_error_set_pending_exception (&error))
3111 mono_array_setref (res, i, rt);
3118 count = mono_method_signature (method->method)->generic_param_count;
3119 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3120 if (mono_error_set_pending_exception (&error))
3123 for (i = 0; i < count; i++) {
3124 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3125 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3126 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3128 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3129 if (mono_error_set_pending_exception (&error))
3132 mono_array_setref (res, i, rt);
3138 ICALL_EXPORT MonoObject *
3139 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3143 * Invoke from reflection is supposed to always be a virtual call (the API
3144 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3145 * greater flexibility.
3147 MonoMethod *m = method->method;
3148 MonoMethodSignature *sig = mono_method_signature (m);
3151 void *obj = this_arg;
3155 if (mono_security_core_clr_enabled () &&
3156 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3157 mono_error_set_pending_exception (&error);
3161 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3162 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3163 mono_error_cleanup (&error); /* FIXME does this make sense? */
3164 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3169 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3170 if (!is_ok (&error)) {
3171 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3174 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3175 char *target_name = mono_type_get_full_name (m->klass);
3176 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3177 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3179 g_free (target_name);
3183 m = mono_object_get_virtual_method (this_arg, m);
3184 /* must pass the pointer to the value for valuetype methods */
3185 if (m->klass->valuetype)
3186 obj = mono_object_unbox (this_arg);
3187 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3188 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3193 if (sig->ret->byref) {
3194 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"));
3198 pcount = params? mono_array_length (params): 0;
3199 if (pcount != sig->param_count) {
3200 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3204 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3205 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."));
3209 image = m->klass->image;
3210 if (image->assembly->ref_only) {
3211 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."));
3215 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3216 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3220 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3224 intptr_t *lower_bounds;
3225 pcount = mono_array_length (params);
3226 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3227 /* Note: the synthetized array .ctors have int32 as argument type */
3228 for (i = 0; i < pcount; ++i)
3229 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3231 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3232 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3233 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3234 if (!mono_error_ok (&error)) {
3235 mono_error_set_pending_exception (&error);
3239 for (i = 0; i < mono_array_length (arr); ++i) {
3240 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3241 if (!mono_error_ok (&error)) {
3242 mono_error_set_pending_exception (&error);
3245 mono_array_setref_fast (arr, i, subarray);
3247 return (MonoObject*)arr;
3250 if (m->klass->rank == pcount) {
3251 /* Only lengths provided. */
3252 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3253 if (!mono_error_ok (&error)) {
3254 mono_error_set_pending_exception (&error);
3258 return (MonoObject*)arr;
3260 g_assert (pcount == (m->klass->rank * 2));
3261 /* The arguments are lower-bound-length pairs */
3262 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3264 for (i = 0; i < pcount / 2; ++i) {
3265 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3266 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3269 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3270 if (!mono_error_ok (&error)) {
3271 mono_error_set_pending_exception (&error);
3275 return (MonoObject*)arr;
3278 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3279 mono_error_set_pending_exception (&error);
3283 #ifndef DISABLE_REMOTING
3284 ICALL_EXPORT MonoObject *
3285 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3288 MonoDomain *domain = mono_object_domain (method);
3289 MonoMethod *m = method->method;
3290 MonoMethodSignature *sig = mono_method_signature (m);
3291 MonoArray *out_args;
3293 int i, j, outarg_count = 0;
3295 if (m->klass == mono_defaults.object_class) {
3296 if (!strcmp (m->name, "FieldGetter")) {
3297 MonoClass *k = this_arg->vtable->klass;
3301 /* If this is a proxy, then it must be a CBO */
3302 if (k == mono_defaults.transparent_proxy_class) {
3303 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3304 this_arg = tp->rp->unwrapped_server;
3305 g_assert (this_arg);
3306 k = this_arg->vtable->klass;
3309 name = mono_array_get (params, MonoString *, 1);
3310 str = mono_string_to_utf8_checked (name, &error);
3311 if (mono_error_set_pending_exception (&error))
3315 MonoClassField* field = mono_class_get_field_from_name (k, str);
3318 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3319 if (field_klass->valuetype) {
3320 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3321 if (mono_error_set_pending_exception (&error))
3324 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3326 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3327 if (mono_error_set_pending_exception (&error))
3329 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3330 mono_array_setref (out_args, 0, result);
3337 g_assert_not_reached ();
3339 } else if (!strcmp (m->name, "FieldSetter")) {
3340 MonoClass *k = this_arg->vtable->klass;
3346 /* If this is a proxy, then it must be a CBO */
3347 if (k == mono_defaults.transparent_proxy_class) {
3348 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3349 this_arg = tp->rp->unwrapped_server;
3350 g_assert (this_arg);
3351 k = this_arg->vtable->klass;
3354 name = mono_array_get (params, MonoString *, 1);
3355 str = mono_string_to_utf8_checked (name, &error);
3356 if (mono_error_set_pending_exception (&error))
3360 MonoClassField* field = mono_class_get_field_from_name (k, str);
3363 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3364 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3366 if (field_klass->valuetype) {
3367 size = mono_type_size (field->type, &align);
3368 g_assert (size == mono_class_value_size (field_klass, NULL));
3369 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3371 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3374 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3375 if (mono_error_set_pending_exception (&error))
3377 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3386 g_assert_not_reached ();
3391 for (i = 0; i < mono_array_length (params); i++) {
3392 if (sig->params [i]->byref)
3396 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3397 if (mono_error_set_pending_exception (&error))
3400 /* handle constructors only for objects already allocated */
3401 if (!strcmp (method->method->name, ".ctor"))
3402 g_assert (this_arg);
3404 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3405 g_assert (!method->method->klass->valuetype);
3406 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3407 if (mono_error_set_pending_exception (&error))
3410 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3411 if (sig->params [i]->byref) {
3413 arg = mono_array_get (params, gpointer, i);
3414 mono_array_setref (out_args, j, arg);
3419 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3426 read_enum_value (const char *mem, int type)
3429 case MONO_TYPE_BOOLEAN:
3431 return *(guint8*)mem;
3433 return *(gint8*)mem;
3434 case MONO_TYPE_CHAR:
3436 return read16 (mem);
3438 return (gint16) read16 (mem);
3440 return read32 (mem);
3442 return (gint32) read32 (mem);
3445 return read64 (mem);
3447 g_assert_not_reached ();
3453 write_enum_value (char *mem, int type, guint64 value)
3457 case MONO_TYPE_I1: {
3458 guint8 *p = (guint8*)mem;
3464 case MONO_TYPE_CHAR: {
3465 guint16 *p = (guint16 *)mem;
3470 case MONO_TYPE_I4: {
3471 guint32 *p = (guint32 *)mem;
3476 case MONO_TYPE_I8: {
3477 guint64 *p = (guint64 *)mem;
3482 g_assert_not_reached ();
3487 ICALL_EXPORT MonoObject *
3488 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3496 domain = mono_object_domain (enumType);
3497 enumc = mono_class_from_mono_type (enumType->type);
3499 mono_class_init_checked (enumc, &error);
3500 if (mono_error_set_pending_exception (&error))
3503 etype = mono_class_enum_basetype (enumc);
3505 res = mono_object_new_checked (domain, enumc, &error);
3506 if (mono_error_set_pending_exception (&error))
3508 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3513 ICALL_EXPORT MonoBoolean
3514 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3516 int size = mono_class_value_size (a->vtable->klass, NULL);
3517 guint64 a_val = 0, b_val = 0;
3519 memcpy (&a_val, mono_object_unbox (a), size);
3520 memcpy (&b_val, mono_object_unbox (b), size);
3522 return (a_val & b_val) == b_val;
3525 ICALL_EXPORT MonoObject *
3526 ves_icall_System_Enum_get_value (MonoObject *eobj)
3538 g_assert (eobj->vtable->klass->enumtype);
3540 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3541 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3542 if (mono_error_set_pending_exception (&error))
3544 dst = (char *)res + sizeof (MonoObject);
3545 src = (char *)eobj + sizeof (MonoObject);
3546 size = mono_class_value_size (enumc, NULL);
3548 memcpy (dst, src, size);
3553 ICALL_EXPORT MonoReflectionType *
3554 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3557 MonoReflectionType *ret;
3561 klass = mono_class_from_mono_type (type->type);
3562 mono_class_init_checked (klass, &error);
3563 if (mono_error_set_pending_exception (&error))
3566 etype = mono_class_enum_basetype (klass);
3568 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3572 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3573 mono_error_set_pending_exception (&error);
3579 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3581 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3582 gpointer odata = (char *)other + sizeof (MonoObject);
3583 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3584 g_assert (basetype);
3589 if (eobj->vtable->klass != other->vtable->klass)
3592 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3593 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3594 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3597 return me > other ? 1 : -1; \
3600 switch (basetype->type) {
3602 COMPARE_ENUM_VALUES (guint8);
3604 COMPARE_ENUM_VALUES (gint8);
3605 case MONO_TYPE_CHAR:
3607 COMPARE_ENUM_VALUES (guint16);
3609 COMPARE_ENUM_VALUES (gint16);
3611 COMPARE_ENUM_VALUES (guint32);
3613 COMPARE_ENUM_VALUES (gint32);
3615 COMPARE_ENUM_VALUES (guint64);
3617 COMPARE_ENUM_VALUES (gint64);
3621 #undef COMPARE_ENUM_VALUES
3622 /* indicates that the enum was of an unsupported unerlying type */
3627 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3629 gpointer data = (char *)eobj + sizeof (MonoObject);
3630 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3631 g_assert (basetype);
3633 switch (basetype->type) {
3634 case MONO_TYPE_I1: {
3635 gint8 value = *((gint8*)data);
3636 return ((int)value ^ (int)value << 8);
3639 return *((guint8*)data);
3640 case MONO_TYPE_CHAR:
3642 return *((guint16*)data);
3644 case MONO_TYPE_I2: {
3645 gint16 value = *((gint16*)data);
3646 return ((int)(guint16)value | (((int)value) << 16));
3649 return *((guint32*)data);
3651 return *((gint32*)data);
3653 case MONO_TYPE_I8: {
3654 gint64 value = *((gint64*)data);
3655 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3658 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3663 ICALL_EXPORT MonoBoolean
3664 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3667 MonoDomain *domain = mono_object_domain (type);
3668 MonoClass *enumc = mono_class_from_mono_type (type->type);
3669 guint j = 0, nvalues;
3671 MonoClassField *field;
3673 guint64 field_value, previous_value = 0;
3674 gboolean sorted = TRUE;
3676 mono_class_init_checked (enumc, &error);
3677 if (mono_error_set_pending_exception (&error))
3681 if (!enumc->enumtype) {
3682 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3686 base_type = mono_class_enum_basetype (enumc)->type;
3688 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3689 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3690 if (mono_error_set_pending_exception (&error))
3692 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3693 if (mono_error_set_pending_exception (&error))
3697 while ((field = mono_class_get_fields (enumc, &iter))) {
3699 MonoTypeEnum def_type;
3701 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3703 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3705 if (mono_field_is_deleted (field))
3707 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3709 p = mono_class_get_field_default_value (field, &def_type);
3710 /* len = */ mono_metadata_decode_blob_size (p, &p);
3712 field_value = read_enum_value (p, base_type);
3713 mono_array_set (*values, guint64, j, field_value);
3715 if (previous_value > field_value)
3718 previous_value = field_value;
3726 BFLAGS_IgnoreCase = 1,
3727 BFLAGS_DeclaredOnly = 2,
3728 BFLAGS_Instance = 4,
3730 BFLAGS_Public = 0x10,
3731 BFLAGS_NonPublic = 0x20,
3732 BFLAGS_FlattenHierarchy = 0x40,
3733 BFLAGS_InvokeMethod = 0x100,
3734 BFLAGS_CreateInstance = 0x200,
3735 BFLAGS_GetField = 0x400,
3736 BFLAGS_SetField = 0x800,
3737 BFLAGS_GetProperty = 0x1000,
3738 BFLAGS_SetProperty = 0x2000,
3739 BFLAGS_ExactBinding = 0x10000,
3740 BFLAGS_SuppressChangeType = 0x20000,
3741 BFLAGS_OptionalParamBinding = 0x40000
3744 ICALL_EXPORT MonoArray*
3745 ves_icall_RuntimeType_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3749 MonoClass *startklass, *klass, *refklass;
3754 char *utf8_name = NULL;
3755 int (*compare_func) (const char *s1, const char *s2) = NULL;
3756 MonoClassField *field;
3757 MonoPtrArray tmp_array;
3759 domain = ((MonoObject *)type)->vtable->domain;
3760 if (type->type->byref) {
3761 MonoArray *result = mono_array_new_checked (domain, mono_defaults.field_info_class, 0, &error);
3762 mono_error_set_pending_exception (&error);
3766 klass = startklass = mono_class_from_mono_type (type->type);
3767 refklass = mono_class_from_mono_type (reftype->type);
3769 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3772 if (mono_class_has_failure (klass)) {
3773 mono_ptr_array_destroy (tmp_array);
3774 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3779 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3780 guint32 flags = mono_field_get_flags (field);
3782 if (mono_field_is_deleted_with_flags (field, flags))
3784 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3785 if (bflags & BFLAGS_Public)
3787 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3788 if (bflags & BFLAGS_NonPublic) {
3795 if (flags & FIELD_ATTRIBUTE_STATIC) {
3796 if (bflags & BFLAGS_Static)
3797 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3800 if (bflags & BFLAGS_Instance)
3808 if (utf8_name == NULL) {
3809 utf8_name = mono_string_to_utf8_checked (name, &error);
3810 if (!is_ok (&error))
3812 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3815 if (compare_func (mono_field_get_name (field), utf8_name))
3819 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3820 if (!mono_error_ok (&error))
3822 mono_ptr_array_append (tmp_array, member);
3824 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3827 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array), &error);
3828 if (!is_ok (&error))
3831 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3832 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3834 mono_ptr_array_destroy (tmp_array);
3836 if (utf8_name != NULL)
3841 mono_ptr_array_destroy (tmp_array);
3842 mono_error_set_pending_exception (&error);
3847 method_nonpublic (MonoMethod* method, gboolean start_klass)
3849 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3850 case METHOD_ATTRIBUTE_ASSEM:
3851 return (start_klass || mono_defaults.generic_ilist_class);
3852 case METHOD_ATTRIBUTE_PRIVATE:
3854 case METHOD_ATTRIBUTE_PUBLIC:
3862 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3865 MonoClass *startklass;
3869 /*FIXME, use MonoBitSet*/
3870 guint32 method_slots_default [8];
3871 guint32 *method_slots = NULL;
3872 int (*compare_func) (const char *s1, const char *s2) = NULL;
3874 array = g_ptr_array_new ();
3879 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3881 /* An optimization for calls made from Delegate:CreateDelegate () */
3882 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3883 method = mono_get_delegate_invoke (klass);
3886 g_ptr_array_add (array, method);
3890 mono_class_setup_methods (klass);
3891 mono_class_setup_vtable (klass);
3892 if (mono_class_has_failure (klass))
3895 if (is_generic_parameter (&klass->byval_arg))
3896 nslots = mono_class_get_vtable_size (klass->parent);
3898 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3899 if (nslots >= sizeof (method_slots_default) * 8) {
3900 method_slots = g_new0 (guint32, nslots / 32 + 1);
3902 method_slots = method_slots_default;
3903 memset (method_slots, 0, sizeof (method_slots_default));
3906 mono_class_setup_methods (klass);
3907 mono_class_setup_vtable (klass);
3908 if (mono_class_has_failure (klass))
3912 while ((method = mono_class_get_methods (klass, &iter))) {
3914 if (method->slot != -1) {
3915 g_assert (method->slot < nslots);
3916 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3918 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3919 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3922 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3924 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3925 if (bflags & BFLAGS_Public)
3927 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3933 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3934 if (bflags & BFLAGS_Static)
3935 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3938 if (bflags & BFLAGS_Instance)
3946 if (compare_func (name, method->name))
3951 g_ptr_array_add (array, method);
3953 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3955 if (method_slots != method_slots_default)
3956 g_free (method_slots);
3961 if (method_slots != method_slots_default)
3962 g_free (method_slots);
3963 g_ptr_array_free (array, TRUE);
3965 if (mono_class_has_failure (klass)) {
3966 *ex = mono_class_get_exception_for_failure (klass);
3968 *ex = mono_get_exception_execution_engine ("Unknown error");
3973 ICALL_EXPORT MonoArray*
3974 ves_icall_RuntimeType_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3976 static MonoClass *MethodInfo_array;
3980 MonoVTable *array_vtable;
3981 MonoException *ex = NULL;
3982 const char *mname = NULL;
3983 GPtrArray *method_array;
3984 MonoClass *klass, *refklass;
3987 mono_error_init (&error);
3989 if (!MethodInfo_array) {
3990 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3991 mono_memory_barrier ();
3992 MethodInfo_array = klass;
3995 klass = mono_class_from_mono_type (type->type);
3996 refklass = mono_class_from_mono_type (reftype->type);
3997 domain = ((MonoObject *)type)->vtable->domain;
3998 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3999 if (!is_ok (&error)) {
4000 mono_error_set_pending_exception (&error);
4003 if (type->type->byref) {
4004 res = mono_array_new_specific_checked (array_vtable, 0, &error);
4005 mono_error_set_pending_exception (&error);
4011 mname = mono_string_to_utf8_checked (name, &error);
4012 if (mono_error_set_pending_exception (&error))
4016 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
4017 g_free ((char*)mname);
4019 mono_set_pending_exception (ex);
4023 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
4024 if (!mono_error_ok (&error)) {
4025 mono_error_set_pending_exception (&error);
4029 for (i = 0; i < method_array->len; ++i) {
4030 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
4031 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
4032 if (!mono_error_ok (&error))
4034 mono_array_setref (res, i, rm);
4038 g_ptr_array_free (method_array, TRUE);
4039 if (!mono_error_ok (&error))
4040 mono_set_pending_exception (mono_error_convert_to_exception (&error));
4044 ICALL_EXPORT MonoArray*
4045 ves_icall_RuntimeType_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4048 MonoClass *startklass, *klass, *refklass;
4049 MonoArray *res = NULL;
4053 gpointer iter = NULL;
4054 MonoPtrArray tmp_array;
4057 domain = ((MonoObject *)type)->vtable->domain;
4058 if (type->type->byref) {
4059 res = mono_array_new_cached (domain, mono_defaults.method_info_class, 0, &error);
4060 mono_error_set_pending_exception (&error);
4064 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
4067 klass = startklass = mono_class_from_mono_type (type->type);
4068 refklass = mono_class_from_mono_type (reftype->type);
4070 mono_class_setup_methods (klass);
4071 if (mono_class_has_failure (klass)) {
4072 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
4077 while ((method = mono_class_get_methods (klass, &iter))) {
4079 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
4081 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4082 if (bflags & BFLAGS_Public)
4085 if (bflags & BFLAGS_NonPublic)
4091 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4092 if (bflags & BFLAGS_Static)
4093 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4096 if (bflags & BFLAGS_Instance)
4102 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
4103 if (mono_error_set_pending_exception (&error))
4106 mono_ptr_array_append (tmp_array, member);
4109 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array), &error);
4110 if (mono_error_set_pending_exception (&error))
4113 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4114 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4117 mono_ptr_array_destroy (tmp_array);
4123 property_hash (gconstpointer data)
4125 MonoProperty *prop = (MonoProperty*)data;
4127 return g_str_hash (prop->name);
4131 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
4133 if (method1->slot != -1 && method1->slot == method2->slot)
4136 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
4137 if (method1->is_inflated)
4138 method1 = ((MonoMethodInflated*) method1)->declaring;
4139 if (method2->is_inflated)
4140 method2 = ((MonoMethodInflated*) method2)->declaring;
4143 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4147 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4149 // Properties are hide-by-name-and-signature
4150 if (!g_str_equal (prop1->name, prop2->name))
4153 /* If we see a property in a generic method, we want to
4154 compare the generic signatures, not the inflated signatures
4155 because we might conflate two properties that were
4159 public T this[T t] { getter { return t; } } // method 1
4160 public U this[U u] { getter { return u; } } // method 2
4163 If we see int Foo<int,int>::Item[int] we need to know if
4164 the indexer came from method 1 or from method 2, and we
4165 shouldn't conflate them. (Bugzilla 36283)
4167 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4170 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4177 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4182 return method_nonpublic (accessor, start_klass);
4185 ICALL_EXPORT MonoArray*
4186 ves_icall_RuntimeType_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4190 MonoClass *startklass, *klass;
4196 gchar *propname = NULL;
4197 int (*compare_func) (const char *s1, const char *s2) = NULL;
4199 GHashTable *properties = NULL;
4200 MonoPtrArray tmp_array;
4202 mono_error_init (&error);
4204 domain = ((MonoObject *)type)->vtable->domain;
4205 if (type->type->byref) {
4206 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), 0, &error);
4207 mono_error_set_pending_exception (&error);
4211 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4213 klass = startklass = mono_class_from_mono_type (type->type);
4216 propname = mono_string_to_utf8_checked (name, &error);
4217 if (mono_error_set_pending_exception (&error))
4219 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4222 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4224 mono_class_setup_methods (klass);
4225 mono_class_setup_vtable (klass);
4226 if (mono_class_has_failure (klass))
4230 while ((prop = mono_class_get_properties (klass, &iter))) {
4236 flags = method->flags;
4239 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4240 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4241 if (bflags & BFLAGS_Public)
4243 } else if (bflags & BFLAGS_NonPublic) {
4244 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4245 property_accessor_nonpublic(prop->set, startklass == klass)) {
4252 if (flags & METHOD_ATTRIBUTE_STATIC) {
4253 if (bflags & BFLAGS_Static)
4254 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4257 if (bflags & BFLAGS_Instance)
4266 if (compare_func (propname, prop->name))
4270 if (g_hash_table_lookup (properties, prop))
4273 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4276 mono_ptr_array_append (tmp_array, pr);
4278 g_hash_table_insert (properties, prop, prop);
4280 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4283 g_hash_table_destroy (properties);
4286 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array), &error);
4287 if (!is_ok (&error))
4289 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4290 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4292 mono_ptr_array_destroy (tmp_array);
4299 if (mono_class_has_failure (klass))
4300 mono_error_set_for_class_failure (&error, klass);
4304 g_hash_table_destroy (properties);
4307 mono_ptr_array_destroy (tmp_array);
4309 mono_error_set_pending_exception (&error);
4315 event_hash (gconstpointer data)
4317 MonoEvent *event = (MonoEvent*)data;
4319 return g_str_hash (event->name);
4323 event_equal (MonoEvent *event1, MonoEvent *event2)
4325 // Events are hide-by-name
4326 return g_str_equal (event1->name, event2->name);
4329 ICALL_EXPORT MonoArray*
4330 ves_icall_RuntimeType_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4334 MonoClass *startklass, *klass;
4340 char *utf8_name = NULL;
4341 int (*compare_func) (const char *s1, const char *s2) = NULL;
4342 GHashTable *events = NULL;
4343 MonoPtrArray tmp_array;
4345 mono_error_init (&error);
4347 domain = mono_object_domain (type);
4348 if (type->type->byref) {
4349 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), 0, &error);
4350 mono_error_set_pending_exception (&error);
4354 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4356 klass = startklass = mono_class_from_mono_type (type->type);
4358 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4360 mono_class_setup_methods (klass);
4361 mono_class_setup_vtable (klass);
4362 if (mono_class_has_failure (klass))
4366 while ((event = mono_class_get_events (klass, &iter))) {
4368 method = event->add;
4370 method = event->remove;
4372 method = event->raise;
4374 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4375 if (bflags & BFLAGS_Public)
4377 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4378 if (bflags & BFLAGS_NonPublic)
4383 if (bflags & BFLAGS_NonPublic)
4389 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4390 if (bflags & BFLAGS_Static)
4391 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4394 if (bflags & BFLAGS_Instance)
4399 if (bflags & BFLAGS_Instance)
4405 if (utf8_name == NULL) {
4406 utf8_name = mono_string_to_utf8_checked (name, &error);
4407 if (!is_ok (&error))
4409 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4412 if (compare_func (event->name, utf8_name))
4416 if (g_hash_table_lookup (events, event))
4419 MonoReflectionEvent *ev_obj;
4420 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4423 mono_ptr_array_append (tmp_array, ev_obj);
4425 g_hash_table_insert (events, event, event);
4427 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4430 g_hash_table_destroy (events);
4432 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array), &error);
4433 if (!is_ok (&error))
4436 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4437 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4439 mono_ptr_array_destroy (tmp_array);
4441 if (utf8_name != NULL)
4447 if (mono_class_has_failure (klass))
4448 mono_error_set_for_class_failure (&error, klass);
4453 g_hash_table_destroy (events);
4454 if (utf8_name != NULL)
4457 mono_ptr_array_destroy (tmp_array);
4459 mono_error_set_pending_exception (&error);
4463 ICALL_EXPORT MonoArray*
4464 ves_icall_RuntimeType_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4467 MonoReflectionType *rt;
4470 MonoArray *res = NULL;
4475 MonoPtrArray tmp_array;
4477 mono_error_init (&error);
4479 domain = ((MonoObject *)type)->vtable->domain;
4480 if (type->type->byref) {
4481 MonoArray *result = mono_array_new_cached (domain, mono_defaults.runtimetype_class, 0, &error);
4482 mono_error_set_pending_exception (&error);
4485 klass = mono_class_from_mono_type (type->type);
4488 * If a nested type is generic, return its generic type definition.
4489 * Note that this means that the return value is essentially the set
4490 * of nested types of the generic type definition of @klass.
4492 * A note in MSDN claims that a generic type definition can have
4493 * nested types that aren't generic. In any case, the container of that
4494 * nested type would be the generic type definition.
4496 if (klass->generic_class)
4497 klass = klass->generic_class->container_class;
4499 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4501 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4503 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4504 if (bflags & BFLAGS_Public)
4507 if (bflags & BFLAGS_NonPublic)
4515 str = mono_string_to_utf8_checked (name, &error);
4516 if (!is_ok (&error))
4518 mono_identifier_unescape_type_name_chars (str);
4521 if (strcmp (nested->name, str))
4525 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4526 if (!is_ok (&error))
4529 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4532 res = mono_array_new_cached (domain, mono_defaults.runtimetype_class, mono_ptr_array_size (tmp_array), &error);
4533 if (!is_ok (&error))
4536 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4537 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4540 mono_ptr_array_destroy (tmp_array);
4544 mono_error_set_pending_exception (&error);
4548 ICALL_EXPORT MonoReflectionType*
4549 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4552 MonoReflectionType *ret;
4554 MonoType *type = NULL;
4555 MonoTypeNameParse info;
4556 gboolean type_resolve;
4558 /* On MS.NET, this does not fire a TypeResolve event */
4559 type_resolve = TRUE;
4560 str = mono_string_to_utf8_checked (name, &error);
4561 if (mono_error_set_pending_exception (&error))
4563 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4564 if (!mono_reflection_parse_type (str, &info)) {
4566 mono_reflection_free_type_info (&info);
4568 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4571 /*g_print ("failed parse\n");*/
4575 if (info.assembly.name) {
4577 mono_reflection_free_type_info (&info);
4579 /* 1.0 and 2.0 throw different exceptions */
4580 if (mono_defaults.generic_ilist_class)
4581 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4583 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4589 if (module != NULL) {
4590 if (module->image) {
4591 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4592 if (!is_ok (&error)) {
4594 mono_reflection_free_type_info (&info);
4595 mono_error_set_pending_exception (&error);
4602 if (assembly_is_dynamic (assembly->assembly)) {
4603 /* Enumerate all modules */
4604 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4608 if (abuilder->modules) {
4609 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4610 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4611 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4612 if (!is_ok (&error)) {
4614 mono_reflection_free_type_info (&info);
4615 mono_error_set_pending_exception (&error);
4623 if (!type && abuilder->loaded_modules) {
4624 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4625 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4626 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4627 if (!is_ok (&error)) {
4629 mono_reflection_free_type_info (&info);
4630 mono_error_set_pending_exception (&error);
4639 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4640 if (!is_ok (&error)) {
4642 mono_reflection_free_type_info (&info);
4643 mono_error_set_pending_exception (&error);
4648 mono_reflection_free_type_info (&info);
4650 MonoException *e = NULL;
4653 e = mono_get_exception_type_load (name, NULL);
4656 mono_set_pending_exception (e);
4660 if (type->type == MONO_TYPE_CLASS) {
4661 MonoClass *klass = mono_type_get_class (type);
4663 /* need to report exceptions ? */
4664 if (throwOnError && mono_class_has_failure (klass)) {
4665 /* report SecurityException (or others) that occured when loading the assembly */
4666 MonoException *exc = mono_class_get_exception_for_failure (klass);
4667 mono_set_pending_exception (exc);
4672 /* g_print ("got it\n"); */
4673 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4674 mono_error_set_pending_exception (&error);
4680 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4683 gchar *shadow_ini_file;
4686 /* Check for shadow-copied assembly */
4687 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4688 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4690 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4691 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4697 g_free (shadow_ini_file);
4698 if (content != NULL) {
4701 *filename = content;
4708 ICALL_EXPORT MonoString *
4709 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4711 MonoDomain *domain = mono_object_domain (assembly);
4712 MonoAssembly *mass = assembly->assembly;
4713 MonoString *res = NULL;
4718 if (g_path_is_absolute (mass->image->name)) {
4719 absolute = g_strdup (mass->image->name);
4720 dirname = g_path_get_dirname (absolute);
4722 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4723 dirname = g_strdup (mass->basedir);
4726 replace_shadow_path (domain, dirname, &absolute);
4731 for (i = strlen (absolute) - 1; i >= 0; i--)
4732 if (absolute [i] == '\\')
4737 uri = g_filename_to_uri (absolute, NULL, NULL);
4739 const char *prepend = "file://";
4741 if (*absolute == '/' && *(absolute + 1) == '/') {
4744 prepend = "file:///";
4747 uri = g_strconcat (prepend, absolute, NULL);
4751 res = mono_string_new (domain, uri);
4758 ICALL_EXPORT MonoBoolean
4759 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4761 MonoAssembly *mass = assembly->assembly;
4763 return mass->in_gac;
4766 ICALL_EXPORT MonoReflectionAssembly*
4767 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4772 MonoImageOpenStatus status;
4773 MonoReflectionAssembly* result = NULL;
4775 name = mono_string_to_utf8_checked (mname, &error);
4776 if (mono_error_set_pending_exception (&error))
4778 res = mono_assembly_load_with_partial_name (name, &status);
4784 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4786 mono_error_set_pending_exception (&error);
4790 ICALL_EXPORT MonoString *
4791 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4793 MonoDomain *domain = mono_object_domain (assembly);
4796 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4801 ICALL_EXPORT MonoBoolean
4802 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4804 return assembly->assembly->ref_only;
4807 ICALL_EXPORT MonoString *
4808 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4810 MonoDomain *domain = mono_object_domain (assembly);
4812 return mono_string_new (domain, assembly->assembly->image->version);
4815 ICALL_EXPORT MonoReflectionMethod*
4816 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4819 MonoReflectionMethod *res = NULL;
4822 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4826 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4827 if (!mono_error_ok (&error))
4830 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4833 if (!mono_error_ok (&error))
4834 mono_error_set_pending_exception (&error);
4838 ICALL_EXPORT MonoReflectionModule*
4839 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4842 MonoReflectionModule *result = NULL;
4843 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4844 if (!mono_error_ok (&error))
4845 mono_error_set_pending_exception (&error);
4849 ICALL_EXPORT MonoArray*
4850 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4853 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4854 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4855 if (mono_error_set_pending_exception (&error))
4860 for (i = 0; i < table->rows; ++i) {
4861 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4862 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4867 ICALL_EXPORT MonoString*
4868 ves_icall_System_Reflection_Assembly_GetAotId ()
4871 guint8 aotid_sum = 0;
4872 MonoDomain* domain = mono_domain_get ();
4874 if (!domain->entry_assembly || !domain->entry_assembly->image)
4877 guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
4879 for (i = 0; i < 16; ++i)
4880 aotid_sum |= (*aotid)[i];
4885 return mono_string_new (domain, mono_guid_to_string((guint8*) aotid));
4889 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4891 static MonoMethod *create_version = NULL;
4895 mono_error_init (error);
4898 if (!create_version) {
4899 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4900 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4901 g_assert (create_version);
4902 mono_method_desc_free (desc);
4908 args [3] = &revision;
4909 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4910 return_val_if_nok (error, NULL);
4912 mono_runtime_invoke_checked (create_version, result, args, error);
4913 return_val_if_nok (error, NULL);
4918 ICALL_EXPORT MonoArray*
4919 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4923 MonoDomain *domain = mono_object_domain (assembly);
4925 static MonoMethod *create_culture = NULL;
4926 MonoImage *image = assembly->assembly->image;
4930 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4933 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4934 if (mono_error_set_pending_exception (&error))
4938 if (count > 0 && !create_culture) {
4939 MonoMethodDesc *desc = mono_method_desc_new (
4940 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4941 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4942 g_assert (create_culture);
4943 mono_method_desc_free (desc);
4946 for (i = 0; i < count; i++) {
4947 MonoObject *version;
4948 MonoReflectionAssemblyName *aname;
4949 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4951 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4953 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4954 domain, mono_class_get_assembly_name_class (), &error);
4955 if (mono_error_set_pending_exception (&error))
4958 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4960 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4961 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4962 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4963 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4964 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4965 aname->versioncompat = 1; /* SameMachine (default) */
4966 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4968 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4969 if (mono_error_set_pending_exception (&error))
4972 MONO_OBJECT_SETREF (aname, version, version);
4974 if (create_culture) {
4976 MonoBoolean assembly_ref = 1;
4977 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4978 args [1] = &assembly_ref;
4980 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4981 if (mono_error_set_pending_exception (&error))
4984 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4987 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4988 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4989 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4991 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4992 /* public key token isn't copied - the class library will
4993 automatically generate it from the public key if required */
4994 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4995 if (mono_error_set_pending_exception (&error))
4998 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4999 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
5001 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
5002 if (mono_error_set_pending_exception (&error))
5005 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5006 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
5009 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
5010 if (mono_error_set_pending_exception (&error))
5013 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5016 /* note: this function doesn't return the codebase on purpose (i.e. it can
5017 be used under partial trust as path information isn't present). */
5019 mono_array_setref (result, i, aname);
5024 /* move this in some file in mono/util/ */
5026 g_concat_dir_and_file (const char *dir, const char *file)
5028 g_return_val_if_fail (dir != NULL, NULL);
5029 g_return_val_if_fail (file != NULL, NULL);
5032 * If the directory name doesn't have a / on the end, we need
5033 * to add one so we get a proper path to the file
5035 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
5036 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
5038 return g_strconcat (dir, file, NULL);
5042 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
5045 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5047 guint32 cols [MONO_MANIFEST_SIZE];
5048 guint32 impl, file_idx;
5052 char *n = mono_string_to_utf8_checked (name, &error);
5053 if (mono_error_set_pending_exception (&error))
5056 for (i = 0; i < table->rows; ++i) {
5057 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5058 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5059 if (strcmp (val, n) == 0)
5063 if (i == table->rows)
5066 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
5069 * this code should only be called after obtaining the
5070 * ResourceInfo and handling the other cases.
5072 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
5073 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
5075 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
5080 module = assembly->assembly->image;
5083 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
5084 if (mono_error_set_pending_exception (&error))
5086 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
5088 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
5091 ICALL_EXPORT gboolean
5092 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
5095 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5097 guint32 cols [MONO_MANIFEST_SIZE];
5098 guint32 file_cols [MONO_FILE_SIZE];
5102 n = mono_string_to_utf8_checked (name, &error);
5103 if (mono_error_set_pending_exception (&error))
5105 for (i = 0; i < table->rows; ++i) {
5106 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5107 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5108 if (strcmp (val, n) == 0)
5112 if (i == table->rows)
5115 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
5116 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
5119 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
5120 case MONO_IMPLEMENTATION_FILE:
5121 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5122 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5123 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
5124 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
5125 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
5126 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
5129 info->location = RESOURCE_LOCATION_EMBEDDED;
5132 case MONO_IMPLEMENTATION_ASSEMBLYREF:
5133 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5134 mono_assembly_load_reference (assembly->assembly->image, i - 1);
5135 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
5136 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
5137 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
5139 mono_set_pending_exception (ex);
5142 MonoReflectionAssembly *assm_obj;
5143 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5145 mono_error_set_pending_exception (&error);
5148 MONO_OBJECT_SETREF (info, assembly, assm_obj);
5150 /* Obtain info recursively */
5151 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5152 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5155 case MONO_IMPLEMENTATION_EXP_TYPE:
5156 g_assert_not_reached ();
5164 ICALL_EXPORT MonoObject*
5165 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
5168 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5169 MonoArray *result = NULL;
5174 /* check hash if needed */
5176 n = mono_string_to_utf8_checked (name, &error);
5177 if (mono_error_set_pending_exception (&error))
5180 for (i = 0; i < table->rows; ++i) {
5181 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5182 if (strcmp (val, n) == 0) {
5185 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5186 fn = mono_string_new (mono_object_domain (assembly), n);
5188 return (MonoObject*)fn;
5196 for (i = 0; i < table->rows; ++i) {
5197 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5201 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
5202 if (mono_error_set_pending_exception (&error))
5207 for (i = 0; i < table->rows; ++i) {
5208 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5209 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5210 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5211 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5216 return (MonoObject*)result;
5219 ICALL_EXPORT MonoArray*
5220 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5223 MonoDomain *domain = mono_domain_get();
5226 int i, j, file_count = 0;
5227 MonoImage **modules;
5228 guint32 module_count, real_module_count;
5229 MonoTableInfo *table;
5230 guint32 cols [MONO_FILE_SIZE];
5231 MonoImage *image = assembly->assembly->image;
5233 g_assert (image != NULL);
5234 g_assert (!assembly_is_dynamic (assembly->assembly));
5236 table = &image->tables [MONO_TABLE_FILE];
5237 file_count = table->rows;
5239 modules = image->modules;
5240 module_count = image->module_count;
5242 real_module_count = 0;
5243 for (i = 0; i < module_count; ++i)
5245 real_module_count ++;
5247 klass = mono_class_get_module_class ();
5248 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5249 if (mono_error_set_pending_exception (&error))
5252 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5253 if (mono_error_set_pending_exception (&error))
5256 mono_array_setref (res, 0, image_obj);
5258 for (i = 0; i < module_count; ++i)
5260 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5261 if (mono_error_set_pending_exception (&error))
5263 mono_array_setref (res, j, rm);
5267 for (i = 0; i < file_count; ++i, ++j) {
5268 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5269 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5270 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5271 if (mono_error_set_pending_exception (&error))
5273 mono_array_setref (res, j, rm);
5276 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5278 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5279 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5282 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5283 if (mono_error_set_pending_exception (&error))
5285 mono_array_setref (res, j, rm);
5292 ICALL_EXPORT MonoReflectionMethod*
5293 ves_icall_GetCurrentMethod (void)
5295 MonoReflectionMethod *res = NULL;
5298 MonoMethod *m = mono_method_get_last_managed ();
5301 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5305 while (m->is_inflated)
5306 m = ((MonoMethodInflated*)m)->declaring;
5308 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5309 mono_error_set_pending_exception (&error);
5315 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5318 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5321 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5322 //method is inflated, we should inflate it on the other class
5323 MonoGenericContext ctx;
5324 ctx.method_inst = inflated->context.method_inst;
5325 ctx.class_inst = inflated->context.class_inst;
5326 if (klass->generic_class)
5327 ctx.class_inst = klass->generic_class->context.class_inst;
5328 else if (klass->generic_container)
5329 ctx.class_inst = klass->generic_container->context.class_inst;
5330 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5331 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5335 mono_class_setup_methods (method->klass);
5336 if (mono_class_has_failure (method->klass))
5338 for (i = 0; i < method->klass->method.count; ++i) {
5339 if (method->klass->methods [i] == method) {
5344 mono_class_setup_methods (klass);
5345 if (mono_class_has_failure (klass))
5347 g_assert (offset >= 0 && offset < klass->method.count);
5348 return klass->methods [offset];
5351 ICALL_EXPORT MonoReflectionMethod*
5352 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5354 MonoReflectionMethod *res = NULL;
5358 klass = mono_class_from_mono_type (type);
5359 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5361 if (method->klass != klass) {
5362 method = mono_method_get_equivalent_method (method, klass);
5367 klass = method->klass;
5368 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5369 mono_error_set_pending_exception (&error);
5373 ICALL_EXPORT MonoReflectionMethodBody*
5374 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5377 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5378 mono_error_set_pending_exception (&error);
5382 ICALL_EXPORT MonoReflectionAssembly*
5383 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5386 MonoReflectionAssembly *result;
5387 MonoMethod *dest = NULL;
5389 mono_stack_walk_no_il (get_executing, &dest);
5391 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5393 mono_error_set_pending_exception (&error);
5398 ICALL_EXPORT MonoReflectionAssembly*
5399 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5402 MonoReflectionAssembly *result;
5403 MonoDomain* domain = mono_domain_get ();
5405 if (!domain->entry_assembly)
5408 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5410 mono_error_set_pending_exception (&error);
5414 ICALL_EXPORT MonoReflectionAssembly*
5415 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5420 MonoReflectionAssembly *result;
5423 mono_stack_walk_no_il (get_executing, &dest);
5425 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5429 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5432 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5434 mono_error_set_pending_exception (&error);
5438 ICALL_EXPORT MonoString *
5439 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5440 gboolean assembly_qualified)
5442 MonoDomain *domain = mono_object_domain (object);
5443 MonoTypeNameFormat format;
5448 format = assembly_qualified ?
5449 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5450 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5452 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5454 name = mono_type_get_name_full (object->type, format);
5458 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5463 res = mono_string_new (domain, name);
5470 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5473 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5475 mono_class_init_checked (klass, &error);
5476 mono_error_set_pending_exception (&error);
5477 return mono_security_core_clr_class_level (klass);
5481 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5483 MonoClassField *field = rfield->field;
5484 return mono_security_core_clr_field_level (field, TRUE);
5488 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5490 MonoMethod *method = rfield->method;
5491 return mono_security_core_clr_method_level (method, TRUE);
5495 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)
5497 static MonoMethod *create_culture = NULL;
5501 const char *pkey_ptr;
5503 MonoBoolean assembly_ref = 0;
5505 mono_error_init (error);
5507 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5508 aname->major = name->major;
5509 aname->minor = name->minor;
5510 aname->build = name->build;
5511 aname->flags = name->flags;
5512 aname->revision = name->revision;
5513 aname->hashalg = name->hash_alg;
5514 aname->versioncompat = 1; /* SameMachine (default) */
5515 aname->processor_architecture = name->arch;
5517 if (by_default_version) {
5518 MonoObject *version;
5520 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5521 return_if_nok (error);
5523 MONO_OBJECT_SETREF (aname, version, version);
5527 if (absolute != NULL && *absolute != '\0') {
5528 const gchar *prepend = "file://";
5531 codebase = g_strdup (absolute);
5536 for (i = strlen (codebase) - 1; i >= 0; i--)
5537 if (codebase [i] == '\\')
5540 if (*codebase == '/' && *(codebase + 1) == '/') {
5543 prepend = "file:///";
5547 result = g_strconcat (prepend, codebase, NULL);
5553 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5557 if (!create_culture) {
5558 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5559 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5560 g_assert (create_culture);
5561 mono_method_desc_free (desc);
5564 if (name->culture) {
5565 args [0] = mono_string_new (domain, name->culture);
5566 args [1] = &assembly_ref;
5568 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5569 return_if_nok (error);
5571 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5574 if (name->public_key) {
5575 pkey_ptr = (char*)name->public_key;
5576 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5578 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5579 return_if_nok (error);
5580 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5581 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5582 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5583 } else if (default_publickey) {
5584 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5585 return_if_nok (error);
5586 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5587 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5590 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5591 if (name->public_key_token [0]) {
5595 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5596 return_if_nok (error);
5598 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5599 p = mono_array_addr (keyToken, char, 0);
5601 for (i = 0, j = 0; i < 8; i++) {
5602 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5603 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5606 } else if (default_token) {
5607 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5608 return_if_nok (error);
5609 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5613 ICALL_EXPORT MonoString *
5614 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5616 MonoDomain *domain = mono_object_domain (assembly);
5617 MonoAssembly *mass = assembly->assembly;
5621 name = mono_stringify_assembly_name (&mass->aname);
5622 res = mono_string_new (domain, name);
5629 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5632 gchar *absolute, *dirname;
5633 MonoAssembly *mass = assembly->assembly;
5635 /* XXX this is duplicated code to compute the codebase URI, unify it */
5636 if (g_path_is_absolute (mass->image->name)) {
5637 absolute = g_strdup (mass->image->name);
5638 dirname = g_path_get_dirname (absolute);
5640 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5641 dirname = g_strdup (mass->basedir);
5644 replace_shadow_path (mono_object_domain (assembly), dirname, &absolute);
5647 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5648 mono_error_set_pending_exception (&error);
5654 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5658 MonoImageOpenStatus status = MONO_IMAGE_OK;
5661 MonoAssemblyName name;
5664 filename = mono_string_to_utf8_checked (fname, &error);
5665 if (mono_error_set_pending_exception (&error))
5668 dirname = g_path_get_dirname (filename);
5669 replace_shadow_path (mono_domain_get (), dirname, &filename);
5672 image = mono_image_open (filename, &status);
5678 if (status == MONO_IMAGE_IMAGE_INVALID)
5679 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5681 exc = mono_get_exception_file_not_found2 (NULL, fname);
5682 mono_set_pending_exception (exc);
5686 res = mono_assembly_fill_assembly_name (image, &name);
5688 mono_image_close (image);
5690 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5694 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5695 mono_error_set_pending_exception (&error);
5697 mono_image_close (image);
5701 ICALL_EXPORT MonoBoolean
5702 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5703 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5705 MonoBoolean result = FALSE;
5706 MonoDeclSecurityEntry entry;
5708 /* SecurityAction.RequestMinimum */
5709 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5710 *minimum = entry.blob;
5711 *minLength = entry.size;
5714 /* SecurityAction.RequestOptional */
5715 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5716 *optional = entry.blob;
5717 *optLength = entry.size;
5720 /* SecurityAction.RequestRefuse */
5721 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5722 *refused = entry.blob;
5723 *refLength = entry.size;
5731 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5733 guint32 attrs, visibility;
5735 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5736 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5737 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5740 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5746 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5748 MonoReflectionType *rt;
5751 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5754 mono_error_init (error);
5756 /* we start the count from 1 because we skip the special type <Module> */
5759 for (i = 1; i < tdef->rows; ++i) {
5760 if (mono_module_type_is_visible (tdef, image, i + 1))
5764 count = tdef->rows - 1;
5766 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5767 return_val_if_nok (error, NULL);
5768 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5769 return_val_if_nok (error, NULL);
5771 for (i = 1; i < tdef->rows; ++i) {
5772 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5773 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5776 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5777 return_val_if_nok (error, NULL);
5779 mono_array_setref (res, count, rt);
5781 MonoException *ex = mono_error_convert_to_exception (error);
5782 mono_array_setref (*exceptions, count, ex);
5791 ICALL_EXPORT MonoArray*
5792 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5795 MonoArray *res = NULL;
5796 MonoArray *exceptions = NULL;
5797 MonoImage *image = NULL;
5798 MonoTableInfo *table = NULL;
5801 int i, len, ex_count;
5803 domain = mono_object_domain (assembly);
5805 g_assert (!assembly_is_dynamic (assembly->assembly));
5806 image = assembly->assembly->image;
5807 table = &image->tables [MONO_TABLE_FILE];
5808 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5809 if (mono_error_set_pending_exception (&error))
5812 /* Append data from all modules in the assembly */
5813 for (i = 0; i < table->rows; ++i) {
5814 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5815 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5820 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5821 if (mono_error_set_pending_exception (&error))
5825 /* Append the new types to the end of the array */
5826 if (mono_array_length (res2) > 0) {
5828 MonoArray *res3, *ex3;
5830 len1 = mono_array_length (res);
5831 len2 = mono_array_length (res2);
5833 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5834 if (mono_error_set_pending_exception (&error))
5836 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5837 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5840 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5841 if (mono_error_set_pending_exception (&error))
5843 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5844 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5851 /* the ReflectionTypeLoadException must have all the types (Types property),
5852 * NULL replacing types which throws an exception. The LoaderException must
5853 * contain all exceptions for NULL items.
5856 len = mono_array_length (res);
5859 for (i = 0; i < len; i++) {
5860 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5864 klass = mono_type_get_class (t->type);
5865 if ((klass != NULL) && mono_class_has_failure (klass)) {
5866 /* keep the class in the list */
5867 list = g_list_append (list, klass);
5868 /* and replace Type with NULL */
5869 mono_array_setref (res, i, NULL);
5876 if (list || ex_count) {
5878 MonoException *exc = NULL;
5879 MonoArray *exl = NULL;
5880 int j, length = g_list_length (list) + ex_count;
5882 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5883 if (mono_error_set_pending_exception (&error)) {
5887 /* Types for which mono_class_get_checked () succeeded */
5888 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5889 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5890 mono_array_setref (exl, i, exc);
5892 /* Types for which it don't */
5893 for (j = 0; j < mono_array_length (exceptions); ++j) {
5894 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5896 g_assert (i < length);
5897 mono_array_setref (exl, i, exc);
5904 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5905 if (!is_ok (&error)) {
5906 mono_error_set_pending_exception (&error);
5909 mono_set_pending_exception (exc);
5916 ICALL_EXPORT gboolean
5917 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5920 MonoAssemblyName aname;
5921 MonoDomain *domain = mono_object_domain (name);
5923 gboolean is_version_defined;
5924 gboolean is_token_defined;
5926 aname.public_key = NULL;
5927 val = mono_string_to_utf8_checked (assname, &error);
5928 if (mono_error_set_pending_exception (&error))
5931 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5932 g_free ((guint8*) aname.public_key);
5937 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5938 mono_error_set_pending_exception (&error);
5940 mono_assembly_name_free (&aname);
5941 g_free ((guint8*) aname.public_key);
5947 ICALL_EXPORT MonoReflectionType*
5948 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5951 MonoReflectionType *ret;
5952 MonoDomain *domain = mono_object_domain (module);
5955 g_assert (module->image);
5957 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5958 /* These images do not have a global type */
5961 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5962 if (!mono_error_ok (&error)) {
5963 mono_error_set_pending_exception (&error);
5967 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5968 if (!mono_error_ok (&error)) {
5969 mono_error_set_pending_exception (&error);
5977 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5979 /*if (module->image)
5980 mono_image_close (module->image);*/
5983 ICALL_EXPORT MonoString*
5984 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5986 MonoDomain *domain = mono_object_domain (module);
5988 g_assert (module->image);
5989 return mono_string_new (domain, module->image->guid);
5992 ICALL_EXPORT gpointer
5993 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5996 if (module->image && module->image->is_module_handle)
5997 return module->image->raw_data;
6000 return (gpointer) (-1);
6004 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
6006 if (image_is_dynamic (image)) {
6007 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
6008 *pe_kind = dyn->pe_kind;
6009 *machine = dyn->machine;
6012 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
6013 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
6018 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
6020 return (image->md_version_major << 16) | (image->md_version_minor);
6023 ICALL_EXPORT MonoArray*
6024 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
6027 MonoArray *exceptions;
6030 if (!module->image) {
6031 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
6032 mono_error_set_pending_exception (&error);
6037 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
6038 if (mono_error_set_pending_exception (&error))
6041 for (i = 0; i < mono_array_length (exceptions); ++i) {
6042 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
6044 mono_set_pending_exception (ex);
6053 mono_memberref_is_method (MonoImage *image, guint32 token)
6055 if (!image_is_dynamic (image)) {
6056 guint32 cols [MONO_MEMBERREF_SIZE];
6058 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
6059 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
6060 mono_metadata_decode_blob_size (sig, &sig);
6061 return (*sig != 0x6);
6064 MonoClass *handle_class;
6066 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
6067 mono_error_cleanup (&error); /* just probing, ignore error */
6071 return mono_defaults.methodhandle_class == handle_class;
6076 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
6079 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
6080 mono_array_addr (type_args, MonoType*, 0));
6082 context->class_inst = NULL;
6084 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
6085 mono_array_addr (method_args, MonoType*, 0));
6087 context->method_inst = NULL;
6090 ICALL_EXPORT MonoType*
6091 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6094 int table = mono_metadata_token_table (token);
6095 int index = mono_metadata_token_index (token);
6096 MonoGenericContext context;
6099 *resolve_error = ResolveTokenError_Other;
6101 /* Validate token */
6102 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
6103 (table != MONO_TABLE_TYPESPEC)) {
6104 *resolve_error = ResolveTokenError_BadTable;
6108 if (image_is_dynamic (image)) {
6109 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
6110 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6111 mono_error_cleanup (&error);
6112 return klass ? &klass->byval_arg : NULL;
6115 init_generic_context_from_args (&context, type_args, method_args);
6116 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6117 mono_error_cleanup (&error);
6118 return klass ? &klass->byval_arg : NULL;
6121 if ((index <= 0) || (index > image->tables [table].rows)) {
6122 *resolve_error = ResolveTokenError_OutOfRange;
6126 init_generic_context_from_args (&context, type_args, method_args);
6127 klass = mono_class_get_checked (image, token, &error);
6129 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
6130 if (!mono_error_ok (&error)) {
6131 mono_error_set_pending_exception (&error);
6136 return &klass->byval_arg;
6141 ICALL_EXPORT MonoMethod*
6142 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6145 int table = mono_metadata_token_table (token);
6146 int index = mono_metadata_token_index (token);
6147 MonoGenericContext context;
6150 *resolve_error = ResolveTokenError_Other;
6152 /* Validate token */
6153 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
6154 (table != MONO_TABLE_MEMBERREF)) {
6155 *resolve_error = ResolveTokenError_BadTable;
6159 if (image_is_dynamic (image)) {
6160 if (table == MONO_TABLE_METHOD) {
6161 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6162 mono_error_cleanup (&error);
6166 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
6167 *resolve_error = ResolveTokenError_BadTable;
6171 init_generic_context_from_args (&context, type_args, method_args);
6172 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6173 mono_error_cleanup (&error);
6177 if ((index <= 0) || (index > image->tables [table].rows)) {
6178 *resolve_error = ResolveTokenError_OutOfRange;
6181 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6182 *resolve_error = ResolveTokenError_BadTable;
6186 init_generic_context_from_args (&context, type_args, method_args);
6187 method = mono_get_method_checked (image, token, NULL, &context, &error);
6188 mono_error_set_pending_exception (&error);
6193 ICALL_EXPORT MonoString*
6194 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6197 int index = mono_metadata_token_index (token);
6199 *resolve_error = ResolveTokenError_Other;
6201 /* Validate token */
6202 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6203 *resolve_error = ResolveTokenError_BadTable;
6207 if (image_is_dynamic (image)) {
6208 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6209 mono_error_cleanup (&error);
6213 if ((index <= 0) || (index >= image->heap_us.size)) {
6214 *resolve_error = ResolveTokenError_OutOfRange;
6218 /* FIXME: What to do if the index points into the middle of a string ? */
6220 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
6221 mono_error_set_pending_exception (&error);
6225 ICALL_EXPORT MonoClassField*
6226 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6230 int table = mono_metadata_token_table (token);
6231 int index = mono_metadata_token_index (token);
6232 MonoGenericContext context;
6233 MonoClassField *field;
6235 *resolve_error = ResolveTokenError_Other;
6237 /* Validate token */
6238 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6239 *resolve_error = ResolveTokenError_BadTable;
6243 if (image_is_dynamic (image)) {
6244 if (table == MONO_TABLE_FIELD) {
6245 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6246 mono_error_cleanup (&error);
6250 if (mono_memberref_is_method (image, token)) {
6251 *resolve_error = ResolveTokenError_BadTable;
6255 init_generic_context_from_args (&context, type_args, method_args);
6256 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6257 mono_error_cleanup (&error);
6261 if ((index <= 0) || (index > image->tables [table].rows)) {
6262 *resolve_error = ResolveTokenError_OutOfRange;
6265 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6266 *resolve_error = ResolveTokenError_BadTable;
6270 init_generic_context_from_args (&context, type_args, method_args);
6271 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6272 mono_error_set_pending_exception (&error);
6278 ICALL_EXPORT MonoObject*
6279 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6283 int table = mono_metadata_token_table (token);
6285 *error = ResolveTokenError_Other;
6288 case MONO_TABLE_TYPEDEF:
6289 case MONO_TABLE_TYPEREF:
6290 case MONO_TABLE_TYPESPEC: {
6291 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6293 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6294 mono_error_set_pending_exception (&merror);
6301 case MONO_TABLE_METHOD:
6302 case MONO_TABLE_METHODSPEC: {
6303 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6305 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6306 mono_error_set_pending_exception (&merror);
6312 case MONO_TABLE_FIELD: {
6313 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6315 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6316 mono_error_set_pending_exception (&merror);
6322 case MONO_TABLE_MEMBERREF:
6323 if (mono_memberref_is_method (image, token)) {
6324 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6326 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6327 mono_error_set_pending_exception (&merror);
6334 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6336 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6337 mono_error_set_pending_exception (&merror);
6346 *error = ResolveTokenError_BadTable;
6352 ICALL_EXPORT MonoArray*
6353 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6356 int table = mono_metadata_token_table (token);
6357 int idx = mono_metadata_token_index (token);
6358 MonoTableInfo *tables = image->tables;
6363 *resolve_error = ResolveTokenError_OutOfRange;
6365 /* FIXME: Support other tables ? */
6366 if (table != MONO_TABLE_STANDALONESIG)
6369 if (image_is_dynamic (image))
6372 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6375 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6377 ptr = mono_metadata_blob_heap (image, sig);
6378 len = mono_metadata_decode_blob_size (ptr, &ptr);
6380 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6381 if (mono_error_set_pending_exception (&error))
6383 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6387 ICALL_EXPORT MonoReflectionType*
6388 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6391 MonoReflectionType *ret;
6393 int isbyref = 0, rank;
6395 char *str = mono_string_to_utf8_checked (smodifiers, &error);
6396 if (mono_error_set_pending_exception (&error))
6399 klass = mono_class_from_mono_type (tb->type.type);
6401 /* logic taken from mono_reflection_parse_type(): keep in sync */
6405 if (isbyref) { /* only one level allowed by the spec */
6414 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6415 mono_error_set_pending_exception (&error);
6419 klass = mono_ptr_class_get (&klass->byval_arg);
6420 mono_class_init (klass);
6431 else if (*p != '*') { /* '*' means unknown lower bound */
6442 klass = mono_array_class_get (klass, rank);
6443 mono_class_init (klass);
6452 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6453 mono_error_set_pending_exception (&error);
6458 ICALL_EXPORT MonoBoolean
6459 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6465 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6471 check_for_invalid_type (MonoClass *klass, MonoError *error)
6476 mono_error_init (error);
6478 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6481 name = mono_type_get_full_name (klass);
6482 str = mono_string_new (mono_domain_get (), name);
6484 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6487 ICALL_EXPORT MonoReflectionType *
6488 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6491 MonoReflectionType *ret;
6492 MonoClass *klass, *aklass;
6494 klass = mono_class_from_mono_type (type->type);
6495 check_for_invalid_type (klass, &error);
6496 mono_error_set_pending_exception (&error);
6498 if (rank == 0) //single dimentional array
6499 aklass = mono_array_class_get (klass, 1);
6501 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6503 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6504 mono_error_set_pending_exception (&error);
6509 ICALL_EXPORT MonoReflectionType *
6510 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6513 MonoReflectionType *ret;
6516 klass = mono_class_from_mono_type (type->type);
6517 mono_class_init_checked (klass, &error);
6518 if (mono_error_set_pending_exception (&error))
6521 check_for_invalid_type (klass, &error);
6522 if (mono_error_set_pending_exception (&error))
6525 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6526 mono_error_set_pending_exception (&error);
6531 ICALL_EXPORT MonoReflectionType *
6532 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6535 MonoReflectionType *ret;
6536 MonoClass *klass, *pklass;
6538 klass = mono_class_from_mono_type (type->type);
6539 mono_class_init_checked (klass, &error);
6540 if (mono_error_set_pending_exception (&error))
6542 check_for_invalid_type (klass, &error);
6543 if (mono_error_set_pending_exception (&error))
6546 pklass = mono_ptr_class_get (type->type);
6548 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6549 mono_error_set_pending_exception (&error);
6554 ICALL_EXPORT MonoObject *
6555 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6556 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6559 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6560 MonoObject *delegate;
6562 MonoMethod *method = info->method;
6564 mono_class_init_checked (delegate_class, &error);
6565 if (mono_error_set_pending_exception (&error))
6568 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6569 /* FIXME improve this exception message */
6570 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6572 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6573 mono_error_set_pending_exception (&error);
6577 if (mono_security_core_clr_enabled ()) {
6578 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6579 if (throwOnBindFailure)
6580 mono_error_set_pending_exception (&error);
6582 mono_error_cleanup (&error);
6587 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6588 if (mono_error_set_pending_exception (&error))
6591 if (method_is_dynamic (method)) {
6592 /* Creating a trampoline would leak memory */
6593 func = mono_compile_method_checked (method, &error);
6594 if (mono_error_set_pending_exception (&error))
6597 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6598 method = mono_object_get_virtual_method (target, method);
6599 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6600 if (mono_error_set_pending_exception (&error))
6602 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6605 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6606 if (mono_error_set_pending_exception (&error))
6611 ICALL_EXPORT MonoMulticastDelegate *
6612 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6615 MonoMulticastDelegate *ret;
6617 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6619 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6620 if (mono_error_set_pending_exception (&error))
6623 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6628 ICALL_EXPORT MonoReflectionMethod*
6629 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6631 MonoReflectionMethod *ret = NULL;
6633 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6634 mono_error_set_pending_exception (&error);
6640 static inline gint32
6641 mono_array_get_byte_length (MonoArray *array)
6647 klass = array->obj.vtable->klass;
6649 if (array->bounds == NULL)
6650 length = array->max_length;
6653 for (i = 0; i < klass->rank; ++ i)
6654 length *= array->bounds [i].length;
6657 switch (klass->element_class->byval_arg.type) {
6660 case MONO_TYPE_BOOLEAN:
6664 case MONO_TYPE_CHAR:
6672 return length * sizeof (gpointer);
6683 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6685 return mono_array_get_byte_length (array);
6689 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6691 return mono_array_get (array, gint8, idx);
6695 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6697 mono_array_set (array, gint8, idx, value);
6700 ICALL_EXPORT MonoBoolean
6701 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6703 guint8 *src_buf, *dest_buf;
6706 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6710 g_assert (count >= 0);
6712 /* This is called directly from the class libraries without going through the managed wrapper */
6713 MONO_CHECK_ARG_NULL (src, FALSE);
6714 MONO_CHECK_ARG_NULL (dest, FALSE);
6716 /* watch out for integer overflow */
6717 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6720 src_buf = (guint8 *)src->vector + src_offset;
6721 dest_buf = (guint8 *)dest->vector + dest_offset;
6724 memcpy (dest_buf, src_buf, count);
6726 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6731 #ifndef DISABLE_REMOTING
6732 ICALL_EXPORT MonoObject *
6733 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6736 MonoDomain *domain = mono_object_domain (this_obj);
6738 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6739 MonoTransparentProxy *tp;
6743 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6744 if (mono_error_set_pending_exception (&error))
6747 tp = (MonoTransparentProxy*) res;
6749 MONO_OBJECT_SETREF (tp, rp, rp);
6750 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6751 klass = mono_class_from_mono_type (type);
6753 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6754 mono_class_setup_vtable (klass);
6755 if (mono_class_has_failure (klass)) {
6756 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6760 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6761 if (mono_error_set_pending_exception (&error))
6763 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6764 if (mono_error_set_pending_exception (&error))
6767 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6768 if (mono_error_set_pending_exception (&error))
6773 ICALL_EXPORT MonoReflectionType *
6774 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6777 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6778 mono_error_set_pending_exception (&error);
6784 /* System.Environment */
6787 ves_icall_System_Environment_get_UserName (void)
6789 /* using glib is more portable */
6790 return mono_string_new (mono_domain_get (), g_get_user_name ());
6794 ICALL_EXPORT MonoString *
6795 ves_icall_System_Environment_get_MachineName (void)
6797 #if defined (HOST_WIN32)
6802 len = MAX_COMPUTERNAME_LENGTH + 1;
6803 buf = g_new (gunichar2, len);
6806 if (GetComputerName (buf, (PDWORD) &len)) {
6808 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6809 mono_error_set_pending_exception (&error);
6814 #elif !defined(DISABLE_SOCKETS)
6818 #if defined _SC_HOST_NAME_MAX
6819 n = sysconf (_SC_HOST_NAME_MAX);
6823 buf = g_malloc (n+1);
6825 if (gethostname (buf, n) == 0){
6827 result = mono_string_new (mono_domain_get (), buf);
6834 return mono_string_new (mono_domain_get (), "mono");
6839 ves_icall_System_Environment_get_Platform (void)
6841 #if defined (TARGET_WIN32)
6844 #elif defined(__MACH__)
6847 // Notice that the value is hidden from user code, and only exposed
6848 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6849 // define and making assumptions based on Unix/128/4 values before there
6850 // was a MacOS define. Lots of code would assume that not-Unix meant
6851 // Windows, but in this case, it would be OSX.
6860 ICALL_EXPORT MonoString *
6861 ves_icall_System_Environment_get_NewLine (void)
6863 #if defined (HOST_WIN32)
6864 return mono_string_new (mono_domain_get (), "\r\n");
6866 return mono_string_new (mono_domain_get (), "\n");
6870 ICALL_EXPORT MonoBoolean
6871 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6873 #if SIZEOF_VOID_P == 8
6877 gboolean isWow64Process = FALSE;
6878 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6879 return (MonoBoolean)isWow64Process;
6881 #elif defined(HAVE_SYS_UTSNAME_H)
6882 struct utsname name;
6884 if (uname (&name) >= 0) {
6885 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6892 ICALL_EXPORT MonoString *
6893 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6902 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6903 if (mono_error_set_pending_exception (&error))
6905 value = g_getenv (utf8_name);
6912 return mono_string_new (mono_domain_get (), value);
6916 * There is no standard way to get at environ.
6919 #ifndef __MINGW32_VERSION
6920 #if defined(__APPLE__)
6921 #if defined (TARGET_OSX)
6922 /* Apple defines this in crt_externs.h but doesn't provide that header for
6923 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6924 * in fact exist on all implementations (so far)
6926 gchar ***_NSGetEnviron(void);
6927 #define environ (*_NSGetEnviron())
6929 static char *mono_environ[1] = { NULL };
6930 #define environ mono_environ
6931 #endif /* defined (TARGET_OSX) */
6939 ICALL_EXPORT MonoArray *
6940 ves_icall_System_Environment_GetCoomandLineArgs (void)
6943 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6944 mono_error_set_pending_exception (&error);
6948 ICALL_EXPORT MonoArray *
6949 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6961 env_strings = GetEnvironmentStrings();
6964 env_string = env_strings;
6965 while (*env_string != '\0') {
6966 /* weird case that MS seems to skip */
6967 if (*env_string != '=')
6969 while (*env_string != '\0')
6975 domain = mono_domain_get ();
6976 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6977 if (mono_error_set_pending_exception (&error))
6982 env_string = env_strings;
6983 while (*env_string != '\0') {
6984 /* weird case that MS seems to skip */
6985 if (*env_string != '=') {
6986 equal_str = wcschr(env_string, '=');
6987 g_assert(equal_str);
6989 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6990 if (mono_error_set_pending_exception (&error))
6993 mono_array_setref (names, n, str);
6996 while (*env_string != '\0')
7001 FreeEnvironmentStrings (env_strings);
7015 for (e = environ; *e != 0; ++ e)
7018 domain = mono_domain_get ();
7019 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
7020 if (mono_error_set_pending_exception (&error))
7024 for (e = environ; *e != 0; ++ e) {
7025 parts = g_strsplit (*e, "=", 2);
7027 str = mono_string_new (domain, *parts);
7028 mono_array_setref (names, n, str);
7041 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
7044 gunichar2 *utf16_name, *utf16_value;
7046 gchar *utf8_name, *utf8_value;
7051 utf16_name = mono_string_to_utf16 (name);
7052 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7053 SetEnvironmentVariable (utf16_name, NULL);
7054 g_free (utf16_name);
7058 utf16_value = mono_string_to_utf16 (value);
7060 SetEnvironmentVariable (utf16_name, utf16_value);
7062 g_free (utf16_name);
7063 g_free (utf16_value);
7065 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
7066 if (mono_error_set_pending_exception (&error))
7069 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7070 g_unsetenv (utf8_name);
7075 utf8_value = mono_string_to_utf8_checked (value, &error);
7076 if (!mono_error_ok (&error)) {
7078 mono_error_set_pending_exception (&error);
7081 g_setenv (utf8_name, utf8_value, TRUE);
7084 g_free (utf8_value);
7089 ves_icall_System_Environment_Exit (int result)
7091 mono_environment_exitcode_set (result);
7093 /* FIXME: There are some cleanup hangs that should be worked out, but
7094 * if the program is going to exit, everything will be cleaned up when
7095 * NaCl exits anyway.
7097 #ifndef __native_client__
7098 if (!mono_runtime_try_shutdown ())
7099 mono_thread_exit ();
7101 /* Suspend all managed threads since the runtime is going away */
7102 mono_thread_suspend_all_other_threads ();
7104 mono_runtime_quit ();
7107 /* we may need to do some cleanup here... */
7111 ICALL_EXPORT MonoString*
7112 ves_icall_System_Environment_GetGacPath (void)
7114 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
7117 ICALL_EXPORT MonoString*
7118 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
7120 #if defined (HOST_WIN32)
7121 #ifndef CSIDL_FLAG_CREATE
7122 #define CSIDL_FLAG_CREATE 0x8000
7125 WCHAR path [MAX_PATH];
7126 /* Create directory if no existing */
7127 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
7132 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
7133 mono_error_set_pending_exception (&error);
7137 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7139 return mono_string_new (mono_domain_get (), "");
7142 ICALL_EXPORT MonoArray *
7143 ves_icall_System_Environment_GetLogicalDrives (void)
7146 gunichar2 buf [256], *ptr, *dname;
7148 guint initial_size = 127, size = 128;
7151 MonoString *drivestr;
7152 MonoDomain *domain = mono_domain_get ();
7158 while (size > initial_size) {
7159 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
7160 if (size > initial_size) {
7163 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7164 initial_size = size;
7178 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7179 if (mono_error_set_pending_exception (&error))
7186 while (*u16) { u16++; len ++; }
7187 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7188 if (mono_error_set_pending_exception (&error))
7191 mono_array_setref (result, ndrives++, drivestr);
7202 ICALL_EXPORT MonoString *
7203 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7206 gunichar2 volume_name [MAX_PATH + 1];
7208 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7210 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
7211 mono_error_set_pending_exception (&error);
7215 ICALL_EXPORT MonoString *
7216 ves_icall_System_Environment_InternalGetHome (void)
7218 return mono_string_new (mono_domain_get (), g_get_home_dir ());
7221 static const char *encodings [] = {
7223 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7224 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7225 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7227 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7228 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7229 "x_unicode_2_0_utf_7",
7231 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7232 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7234 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7237 "unicodefffe", "utf_16be",
7244 * Returns the internal codepage, if the value of "int_code_page" is
7245 * 1 at entry, and we can not compute a suitable code page number,
7246 * returns the code page as a string
7248 ICALL_EXPORT MonoString*
7249 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
7254 char *codepage = NULL;
7256 int want_name = *int_code_page;
7259 *int_code_page = -1;
7261 g_get_charset (&cset);
7262 c = codepage = strdup (cset);
7263 for (c = codepage; *c; c++){
7264 if (isascii (*c) && isalpha (*c))
7269 /* g_print ("charset: %s\n", cset); */
7271 /* handle some common aliases */
7274 for (i = 0; p != 0; ){
7277 p = encodings [++i];
7280 if (strcmp (p, codepage) == 0){
7281 *int_code_page = code;
7284 p = encodings [++i];
7287 if (strstr (codepage, "utf_8") != NULL)
7288 *int_code_page |= 0x10000000;
7291 if (want_name && *int_code_page == -1)
7292 return mono_string_new (mono_domain_get (), cset);
7297 ICALL_EXPORT MonoBoolean
7298 ves_icall_System_Environment_get_HasShutdownStarted (void)
7300 if (mono_runtime_is_shutting_down ())
7303 if (mono_domain_is_unloading (mono_domain_get ()))
7310 ves_icall_System_Environment_BroadcastSettingChange (void)
7313 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7319 ves_icall_System_Environment_get_TickCount (void)
7321 /* this will overflow after ~24 days */
7322 return (gint32) (mono_msec_boottime () & 0xffffffff);
7326 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7331 #ifndef DISABLE_REMOTING
7332 ICALL_EXPORT MonoBoolean
7333 ves_icall_IsTransparentProxy (MonoObject *proxy)
7338 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7344 ICALL_EXPORT MonoReflectionMethod *
7345 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7346 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7348 MonoReflectionMethod *ret = NULL;
7353 MonoMethod **vtable;
7354 MonoMethod *res = NULL;
7356 MONO_CHECK_ARG_NULL (rtype, NULL);
7357 MONO_CHECK_ARG_NULL (rmethod, NULL);
7359 method = rmethod->method;
7360 klass = mono_class_from_mono_type (rtype->type);
7361 mono_class_init_checked (klass, &error);
7362 if (mono_error_set_pending_exception (&error))
7365 if (MONO_CLASS_IS_INTERFACE (klass))
7368 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7371 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7372 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7378 mono_class_setup_vtable (klass);
7379 vtable = klass->vtable;
7381 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7382 gboolean variance_used = FALSE;
7383 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7384 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7386 res = vtable [offs + method->slot];
7388 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7391 if (method->slot != -1)
7392 res = vtable [method->slot];
7398 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7399 mono_error_set_pending_exception (&error);
7404 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7410 klass = mono_class_from_mono_type (type->type);
7411 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7412 if (!is_ok (&error)) {
7413 mono_error_set_pending_exception (&error);
7417 mono_vtable_set_is_remote (vtable, enable);
7420 #else /* DISABLE_REMOTING */
7423 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7425 g_assert_not_reached ();
7430 ICALL_EXPORT MonoObject *
7431 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7438 domain = mono_object_domain (type);
7439 klass = mono_class_from_mono_type (type->type);
7440 mono_class_init_checked (klass, &error);
7441 if (mono_error_set_pending_exception (&error))
7444 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7445 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7449 if (klass->rank >= 1) {
7450 g_assert (klass->rank == 1);
7451 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7452 mono_error_set_pending_exception (&error);
7455 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7456 if (!is_ok (&error)) {
7457 mono_error_set_pending_exception (&error);
7460 /* Bypass remoting object creation check */
7461 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7462 mono_error_set_pending_exception (&error);
7468 ICALL_EXPORT MonoString *
7469 ves_icall_System_IO_get_temp_path (void)
7471 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7474 #ifndef PLATFORM_NO_DRIVEINFO
7475 ICALL_EXPORT MonoBoolean
7476 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7477 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7481 ULARGE_INTEGER wapi_free_bytes_avail;
7482 ULARGE_INTEGER wapi_total_number_of_bytes;
7483 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7485 *error = ERROR_SUCCESS;
7486 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7487 &wapi_total_number_of_free_bytes);
7490 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7491 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7492 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7494 *free_bytes_avail = 0;
7495 *total_number_of_bytes = 0;
7496 *total_number_of_free_bytes = 0;
7497 *error = GetLastError ();
7503 ICALL_EXPORT guint32
7504 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7506 return GetDriveType (mono_string_chars (root_path_name));
7510 ICALL_EXPORT gpointer
7511 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7514 gpointer result = mono_compile_method_checked (method, &error);
7515 mono_error_set_pending_exception (&error);
7519 ICALL_EXPORT MonoString *
7520 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7525 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7527 #if defined (HOST_WIN32)
7528 /* Avoid mixing '/' and '\\' */
7531 for (i = strlen (path) - 1; i >= 0; i--)
7532 if (path [i] == '/')
7536 mcpath = mono_string_new (mono_domain_get (), path);
7542 /* this is an icall */
7544 get_bundled_app_config (void)
7547 const gchar *app_config;
7550 gchar *config_file_name, *config_file_path;
7551 gsize len, config_file_path_length, config_ext_length;
7554 domain = mono_domain_get ();
7555 file = domain->setup->configuration_file;
7556 if (!file || file->length == 0)
7559 // Retrieve config file and remove the extension
7560 config_file_name = mono_string_to_utf8_checked (file, &error);
7561 if (mono_error_set_pending_exception (&error))
7563 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7564 if (!config_file_path)
7565 config_file_path = config_file_name;
7567 config_file_path_length = strlen (config_file_path);
7568 config_ext_length = strlen (".config");
7569 if (config_file_path_length <= config_ext_length)
7572 len = config_file_path_length - config_ext_length;
7573 module = (gchar *)g_malloc0 (len + 1);
7574 memcpy (module, config_file_path, len);
7575 // Get the config file from the module name
7576 app_config = mono_config_string_for_assembly_file (module);
7579 if (config_file_name != config_file_path)
7580 g_free (config_file_name);
7581 g_free (config_file_path);
7586 return mono_string_new (mono_domain_get (), app_config);
7590 get_bundled_machine_config (void)
7592 const gchar *machine_config;
7594 machine_config = mono_get_machine_config ();
7596 if (!machine_config)
7599 return mono_string_new (mono_domain_get (), machine_config);
7602 ICALL_EXPORT MonoString *
7603 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7608 path = g_path_get_dirname (mono_get_config_dir ());
7610 #if defined (HOST_WIN32)
7611 /* Avoid mixing '/' and '\\' */
7614 for (i = strlen (path) - 1; i >= 0; i--)
7615 if (path [i] == '/')
7619 ipath = mono_string_new (mono_domain_get (), path);
7625 ICALL_EXPORT gboolean
7626 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7628 MonoPEResourceDataEntry *entry;
7631 if (!assembly || !result || !size)
7636 image = assembly->assembly->image;
7637 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7641 *result = mono_image_rva_map (image, entry->rde_data_offset);
7646 *size = entry->rde_size;
7651 ICALL_EXPORT MonoBoolean
7652 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7654 return mono_is_debugger_attached ();
7657 ICALL_EXPORT MonoBoolean
7658 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7660 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7661 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7667 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7669 if (mono_get_runtime_callbacks ()->debug_log)
7670 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7674 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7676 #if defined (HOST_WIN32)
7677 OutputDebugString (mono_string_chars (message));
7679 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7683 /* Only used for value types */
7684 ICALL_EXPORT MonoObject *
7685 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7692 domain = mono_object_domain (type);
7693 klass = mono_class_from_mono_type (type->type);
7694 mono_class_init_checked (klass, &error);
7695 if (mono_error_set_pending_exception (&error))
7698 if (mono_class_is_nullable (klass))
7699 /* No arguments -> null */
7702 result = mono_object_new_checked (domain, klass, &error);
7703 mono_error_set_pending_exception (&error);
7707 ICALL_EXPORT MonoReflectionMethod *
7708 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7710 MonoReflectionMethod *ret = NULL;
7713 MonoClass *klass, *parent;
7714 MonoGenericContext *generic_inst = NULL;
7715 MonoMethod *method = m->method;
7716 MonoMethod *result = NULL;
7719 if (method->klass == NULL)
7722 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7723 MONO_CLASS_IS_INTERFACE (method->klass) ||
7724 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7727 slot = mono_method_get_vtable_slot (method);
7731 klass = method->klass;
7732 if (klass->generic_class) {
7733 generic_inst = mono_class_get_context (klass);
7734 klass = klass->generic_class->container_class;
7738 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7739 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7740 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7741 or klass is the generic container class and generic_inst is the instantiation.
7743 when we go to the parent, if the parent is an open constructed type, we need to
7744 replace the type parameters by the definitions from the generic_inst, and then take it
7745 apart again into the klass and the generic_inst.
7747 For cases like this:
7748 class C<T> : B<T, int> {
7749 public override void Foo () { ... }
7751 class B<U,V> : A<HashMap<U,V>> {
7752 public override void Foo () { ... }
7755 public virtual void Foo () { ... }
7758 if at each iteration the parent isn't open, we can skip inflating it. if at some
7759 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7762 MonoGenericContext *parent_inst = NULL;
7763 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7764 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7765 if (!mono_error_ok (&error)) {
7766 mono_error_set_pending_exception (&error);
7770 if (parent->generic_class) {
7771 parent_inst = mono_class_get_context (parent);
7772 parent = parent->generic_class->container_class;
7775 mono_class_setup_vtable (parent);
7776 if (parent->vtable_size <= slot)
7779 generic_inst = parent_inst;
7782 klass = klass->parent;
7785 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7786 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7787 if (!mono_error_ok (&error)) {
7788 mono_error_set_pending_exception (&error);
7792 generic_inst = NULL;
7794 if (klass->generic_class) {
7795 generic_inst = mono_class_get_context (klass);
7796 klass = klass->generic_class->container_class;
7802 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7803 if (!mono_error_ok (&error)) {
7804 mono_error_set_pending_exception (&error);
7809 if (klass == method->klass)
7812 /*This is possible if definition == FALSE.
7813 * Do it here to be really sure we don't read invalid memory.
7815 if (slot >= klass->vtable_size)
7818 mono_class_setup_vtable (klass);
7820 result = klass->vtable [slot];
7821 if (result == NULL) {
7822 /* It is an abstract method */
7823 gpointer iter = NULL;
7824 while ((result = mono_class_get_methods (klass, &iter)))
7825 if (result->slot == slot)
7832 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7833 mono_error_set_pending_exception (&error);
7837 ICALL_EXPORT MonoString*
7838 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7840 MonoMethod *method = m->method;
7842 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7847 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7849 iter->sig = *(MonoMethodSignature**)argsp;
7851 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7852 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7855 /* FIXME: it's not documented what start is exactly... */
7859 iter->args = argsp + sizeof (gpointer);
7861 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7863 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7866 ICALL_EXPORT MonoTypedRef
7867 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7869 guint32 i, arg_size;
7873 i = iter->sig->sentinelpos + iter->next_arg;
7875 g_assert (i < iter->sig->param_count);
7877 res.type = iter->sig->params [i];
7878 res.klass = mono_class_from_mono_type (res.type);
7879 arg_size = mono_type_stack_size (res.type, &align);
7880 #if defined(__arm__) || defined(__mips__)
7881 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7883 res.value = iter->args;
7884 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7885 /* Values are stored as 8 byte register sized objects, but 'value'
7886 * is dereferenced as a pointer in other routines.
7888 res.value = (char*)res.value + 4;
7890 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7891 if (arg_size <= sizeof (gpointer)) {
7893 int padding = arg_size - mono_type_size (res.type, &dummy);
7894 res.value = (guint8*)res.value + padding;
7897 iter->args = (char*)iter->args + arg_size;
7900 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7905 ICALL_EXPORT MonoTypedRef
7906 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7908 guint32 i, arg_size;
7912 i = iter->sig->sentinelpos + iter->next_arg;
7914 g_assert (i < iter->sig->param_count);
7916 while (i < iter->sig->param_count) {
7917 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7919 res.type = iter->sig->params [i];
7920 res.klass = mono_class_from_mono_type (res.type);
7921 /* FIXME: endianess issue... */
7922 arg_size = mono_type_stack_size (res.type, &align);
7923 #if defined(__arm__) || defined(__mips__)
7924 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7926 res.value = iter->args;
7927 iter->args = (char*)iter->args + arg_size;
7929 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7932 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7940 ICALL_EXPORT MonoType*
7941 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7945 i = iter->sig->sentinelpos + iter->next_arg;
7947 g_assert (i < iter->sig->param_count);
7949 return iter->sig->params [i];
7952 ICALL_EXPORT MonoObject*
7953 mono_TypedReference_ToObject (MonoTypedRef* tref)
7956 MonoObject *result = NULL;
7957 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7958 MonoObject** objp = (MonoObject **)tref->value;
7962 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7963 mono_error_set_pending_exception (&error);
7967 ICALL_EXPORT MonoTypedRef
7968 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7971 MonoReflectionField *f;
7973 MonoType *ftype = NULL;
7977 memset (&res, 0, sizeof (res));
7980 g_assert (mono_array_length (fields) > 0);
7982 klass = target->vtable->klass;
7984 for (i = 0; i < mono_array_length (fields); ++i) {
7985 f = mono_array_get (fields, MonoReflectionField*, i);
7987 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7990 if (f->field->parent != klass) {
7991 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7995 p = (guint8*)target + f->field->offset;
7997 p += f->field->offset - sizeof (MonoObject);
7998 klass = mono_class_from_mono_type (f->field->type);
7999 ftype = f->field->type;
8003 res.klass = mono_class_from_mono_type (ftype);
8010 prelink_method (MonoMethod *method, MonoError *error)
8012 const char *exc_class, *exc_arg;
8014 mono_error_init (error);
8015 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
8017 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
8019 mono_error_set_exception_instance (error,
8020 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
8023 /* create the wrapper, too? */
8027 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
8031 prelink_method (method->method, &error);
8032 mono_error_set_pending_exception (&error);
8036 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
8039 MonoClass *klass = mono_class_from_mono_type (type->type);
8041 gpointer iter = NULL;
8043 mono_class_init_checked (klass, &error);
8044 if (mono_error_set_pending_exception (&error))
8047 while ((m = mono_class_get_methods (klass, &iter))) {
8048 prelink_method (m, &error);
8049 if (mono_error_set_pending_exception (&error))
8054 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
8056 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
8057 gint32 const **exponents,
8058 gunichar2 const **digitLowerTable,
8059 gunichar2 const **digitUpperTable,
8060 gint64 const **tenPowersList,
8061 gint32 const **decHexDigits)
8063 *mantissas = Formatter_MantissaBitsTable;
8064 *exponents = Formatter_TensExponentTable;
8065 *digitLowerTable = Formatter_DigitLowerTable;
8066 *digitUpperTable = Formatter_DigitUpperTable;
8067 *tenPowersList = Formatter_TenPowersList;
8068 *decHexDigits = Formatter_DecHexDigits;
8072 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
8073 * and avoid useless allocations.
8076 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
8078 MonoReflectionType *rt;
8082 mono_error_init (error);
8083 for (i = 0; i < type->num_mods; ++i) {
8084 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
8089 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
8090 return_val_if_nok (error, NULL);
8092 for (i = 0; i < type->num_mods; ++i) {
8093 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
8094 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
8095 return_val_if_nok (error, NULL);
8097 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8098 return_val_if_nok (error, NULL);
8100 mono_array_setref (res, count, rt);
8107 ICALL_EXPORT MonoArray*
8108 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
8111 MonoType *type = param->ClassImpl->type;
8112 MonoClass *member_class = mono_object_class (param->MemberImpl);
8113 MonoMethod *method = NULL;
8116 MonoMethodSignature *sig;
8119 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8120 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8121 method = rmethod->method;
8122 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
8123 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8124 if (!(method = prop->property->get))
8125 method = prop->property->set;
8128 char *type_name = mono_type_get_full_name (member_class);
8129 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
8130 MonoException *ex = mono_get_exception_not_supported (msg);
8133 mono_set_pending_exception (ex);
8137 image = method->klass->image;
8138 pos = param->PositionImpl;
8139 sig = mono_method_signature (method);
8143 type = sig->params [pos];
8145 res = type_array_from_modifiers (image, type, optional, &error);
8146 mono_error_set_pending_exception (&error);
8151 get_property_type (MonoProperty *prop)
8153 MonoMethodSignature *sig;
8155 sig = mono_method_signature (prop->get);
8157 } else if (prop->set) {
8158 sig = mono_method_signature (prop->set);
8159 return sig->params [sig->param_count - 1];
8164 ICALL_EXPORT MonoArray*
8165 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
8168 MonoType *type = get_property_type (property->property);
8169 MonoImage *image = property->klass->image;
8174 res = type_array_from_modifiers (image, type, optional, &error);
8175 mono_error_set_pending_exception (&error);
8180 *Construct a MonoType suited to be used to decode a constant blob object.
8182 * @type is the target type which will be constructed
8183 * @blob_type is the blob type, for example, that comes from the constant table
8184 * @real_type is the expected constructed type.
8187 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8189 type->type = blob_type;
8190 type->data.klass = NULL;
8191 if (blob_type == MONO_TYPE_CLASS)
8192 type->data.klass = mono_defaults.object_class;
8193 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8194 /* For enums, we need to use the base type */
8195 type->type = MONO_TYPE_VALUETYPE;
8196 type->data.klass = mono_class_from_mono_type (real_type);
8198 type->data.klass = mono_class_from_mono_type (real_type);
8201 ICALL_EXPORT MonoObject*
8202 property_info_get_default_value (MonoReflectionProperty *property)
8206 MonoProperty *prop = property->property;
8207 MonoType *type = get_property_type (prop);
8208 MonoDomain *domain = mono_object_domain (property);
8209 MonoTypeEnum def_type;
8210 const char *def_value;
8213 mono_class_init (prop->parent);
8215 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8216 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8220 def_value = mono_class_get_property_default_value (prop, &def_type);
8222 mono_type_from_blob_type (&blob_type, def_type, type);
8223 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8225 mono_error_set_pending_exception (&error);
8229 ICALL_EXPORT MonoBoolean
8230 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8233 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8234 MonoCustomAttrInfo *cinfo;
8237 mono_class_init_checked (attr_class, &error);
8238 if (mono_error_set_pending_exception (&error))
8241 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8242 if (!is_ok (&error)) {
8243 mono_error_set_pending_exception (&error);
8248 found = mono_custom_attrs_has_attr (cinfo, attr_class);
8250 mono_custom_attrs_free (cinfo);
8254 ICALL_EXPORT MonoArray*
8255 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8257 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8262 mono_class_init_checked (attr_class, &error);
8263 if (mono_error_set_pending_exception (&error))
8267 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8268 if (!mono_error_ok (&error)) {
8269 mono_error_set_pending_exception (&error);
8276 ICALL_EXPORT MonoArray*
8277 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8281 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8282 mono_error_set_pending_exception (&error);
8287 ICALL_EXPORT MonoString*
8288 ves_icall_Mono_Runtime_GetDisplayName (void)
8291 MonoString *display_name;
8293 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8294 display_name = mono_string_new (mono_domain_get (), info);
8296 return display_name;
8299 ICALL_EXPORT MonoString*
8300 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8303 MonoString *message;
8307 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8308 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8311 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8313 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8314 if (mono_error_set_pending_exception (&error))
8321 ICALL_EXPORT gpointer
8322 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8324 return GetCurrentProcess ();
8327 ICALL_EXPORT MonoBoolean
8328 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8330 return GetExitCodeProcess (handle, (guint32*) exitcode);
8333 ICALL_EXPORT MonoBoolean
8334 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8336 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8337 return CloseHandle (handle);
8339 return CloseProcess (handle);
8343 ICALL_EXPORT MonoBoolean
8344 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8346 return TerminateProcess (handle, exitcode);
8350 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8352 return WaitForInputIdle (handle, milliseconds);
8355 ICALL_EXPORT MonoBoolean
8356 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8358 return GetProcessWorkingSetSize (handle, min, max);
8361 ICALL_EXPORT MonoBoolean
8362 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8364 return SetProcessWorkingSetSize (handle, min, max);
8367 ICALL_EXPORT MonoBoolean
8368 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8370 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8374 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8376 return mono_process_current_pid ();
8380 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8382 return GetPriorityClass (handle);
8385 ICALL_EXPORT MonoBoolean
8386 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8388 return SetPriorityClass (handle, priorityClass);
8391 #ifndef DISABLE_ICALL_TABLES
8393 #define ICALL_TYPE(id,name,first)
8394 #define ICALL(id,name,func) Icall_ ## id,
8397 #include "metadata/icall-def.h"
8403 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8404 #define ICALL(id,name,func)
8406 #include "metadata/icall-def.h"
8412 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8413 #define ICALL(id,name,func)
8415 guint16 first_icall;
8418 static const IcallTypeDesc
8419 icall_type_descs [] = {
8420 #include "metadata/icall-def.h"
8424 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8427 #define ICALL_TYPE(id,name,first)
8430 #ifdef HAVE_ARRAY_ELEM_INIT
8431 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8432 #define MSGSTRFIELD1(line) str##line
8434 static const struct msgstrtn_t {
8435 #define ICALL(id,name,func)
8437 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8438 #include "metadata/icall-def.h"
8440 } icall_type_names_str = {
8441 #define ICALL_TYPE(id,name,first) (name),
8442 #include "metadata/icall-def.h"
8445 static const guint16 icall_type_names_idx [] = {
8446 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8447 #include "metadata/icall-def.h"
8450 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8452 static const struct msgstr_t {
8454 #define ICALL_TYPE(id,name,first)
8455 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8456 #include "metadata/icall-def.h"
8458 } icall_names_str = {
8459 #define ICALL(id,name,func) (name),
8460 #include "metadata/icall-def.h"
8463 static const guint16 icall_names_idx [] = {
8464 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8465 #include "metadata/icall-def.h"
8468 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8474 #define ICALL_TYPE(id,name,first) name,
8475 #define ICALL(id,name,func)
8476 static const char* const
8477 icall_type_names [] = {
8478 #include "metadata/icall-def.h"
8482 #define icall_type_name_get(id) (icall_type_names [(id)])
8486 #define ICALL_TYPE(id,name,first)
8487 #define ICALL(id,name,func) name,
8488 static const char* const
8490 #include "metadata/icall-def.h"
8493 #define icall_name_get(id) icall_names [(id)]
8495 #endif /* !HAVE_ARRAY_ELEM_INIT */
8499 #define ICALL_TYPE(id,name,first)
8500 #define ICALL(id,name,func) func,
8501 static const gconstpointer
8502 icall_functions [] = {
8503 #include "metadata/icall-def.h"
8507 #ifdef ENABLE_ICALL_SYMBOL_MAP
8510 #define ICALL_TYPE(id,name,first)
8511 #define ICALL(id,name,func) #func,
8512 static const gconstpointer
8513 icall_symbols [] = {
8514 #include "metadata/icall-def.h"
8519 #endif /* DISABLE_ICALL_TABLES */
8521 static mono_mutex_t icall_mutex;
8522 static GHashTable *icall_hash = NULL;
8523 static GHashTable *jit_icall_hash_name = NULL;
8524 static GHashTable *jit_icall_hash_addr = NULL;
8527 mono_icall_init (void)
8529 #ifndef DISABLE_ICALL_TABLES
8532 /* check that tables are sorted: disable in release */
8535 const char *prev_class = NULL;
8536 const char *prev_method;
8538 for (i = 0; i < Icall_type_num; ++i) {
8539 const IcallTypeDesc *desc;
8542 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8543 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8544 prev_class = icall_type_name_get (i);
8545 desc = &icall_type_descs [i];
8546 num_icalls = icall_desc_num_icalls (desc);
8547 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8548 for (j = 0; j < num_icalls; ++j) {
8549 const char *methodn = icall_name_get (desc->first_icall + j);
8550 if (prev_method && strcmp (prev_method, methodn) >= 0)
8551 g_print ("method %s should come before method %s\n", methodn, prev_method);
8552 prev_method = methodn;
8558 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8559 mono_os_mutex_init (&icall_mutex);
8563 mono_icall_lock (void)
8565 mono_locks_os_acquire (&icall_mutex, IcallLock);
8569 mono_icall_unlock (void)
8571 mono_locks_os_release (&icall_mutex, IcallLock);
8575 mono_icall_cleanup (void)
8577 g_hash_table_destroy (icall_hash);
8578 g_hash_table_destroy (jit_icall_hash_name);
8579 g_hash_table_destroy (jit_icall_hash_addr);
8580 mono_os_mutex_destroy (&icall_mutex);
8584 * mono_add_internal_call:
8585 * @name: method specification to surface to the managed world
8586 * @method: pointer to a C method to invoke when the method is called
8588 * This method surfaces the C function pointed by @method as a method
8589 * that has been surfaced in managed code with the method specified in
8590 * @name as an internal call.
8592 * Internal calls are surfaced to all app domains loaded and they are
8593 * accessibly by a type with the specified name.
8595 * You must provide a fully qualified type name, that is namespaces
8596 * and type name, followed by a colon and the method name, with an
8597 * optional signature to bind.
8599 * For example, the following are all valid declarations:
8601 * "MyApp.Services.ScriptService:Accelerate"
8602 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8604 * You use method parameters in cases where there might be more than
8605 * one surface method to managed code. That way you can register different
8606 * internal calls for different method overloads.
8608 * The internal calls are invoked with no marshalling. This means that .NET
8609 * types like System.String are exposed as `MonoString *` parameters. This is
8610 * different than the way that strings are surfaced in P/Invoke.
8612 * For more information on how the parameters are marshalled, see the
8613 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8616 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8617 * reference for more information on the format of method descriptions.
8620 mono_add_internal_call (const char *name, gconstpointer method)
8624 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8626 mono_icall_unlock ();
8629 #ifndef DISABLE_ICALL_TABLES
8631 #ifdef HAVE_ARRAY_ELEM_INIT
8633 compare_method_imap (const void *key, const void *elem)
8635 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8636 return strcmp (key, method_name);
8640 find_method_icall (const IcallTypeDesc *imap, const char *name)
8642 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);
8645 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8649 compare_class_imap (const void *key, const void *elem)
8651 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8652 return strcmp (key, class_name);
8655 static const IcallTypeDesc*
8656 find_class_icalls (const char *name)
8658 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);
8661 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8664 #else /* HAVE_ARRAY_ELEM_INIT */
8667 compare_method_imap (const void *key, const void *elem)
8669 const char** method_name = (const char**)elem;
8670 return strcmp (key, *method_name);
8674 find_method_icall (const IcallTypeDesc *imap, const char *name)
8676 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8679 return (gpointer)icall_functions [(nameslot - icall_names)];
8683 compare_class_imap (const void *key, const void *elem)
8685 const char** class_name = (const char**)elem;
8686 return strcmp (key, *class_name);
8689 static const IcallTypeDesc*
8690 find_class_icalls (const char *name)
8692 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8695 return &icall_type_descs [nameslot - icall_type_names];
8698 #endif /* HAVE_ARRAY_ELEM_INIT */
8700 #endif /* DISABLE_ICALL_TABLES */
8703 * we should probably export this as an helper (handle nested types).
8704 * Returns the number of chars written in buf.
8707 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8709 int nspacelen, cnamelen;
8710 nspacelen = strlen (klass->name_space);
8711 cnamelen = strlen (klass->name);
8712 if (nspacelen + cnamelen + 2 > bufsize)
8715 memcpy (buf, klass->name_space, nspacelen);
8716 buf [nspacelen ++] = '.';
8718 memcpy (buf + nspacelen, klass->name, cnamelen);
8719 buf [nspacelen + cnamelen] = 0;
8720 return nspacelen + cnamelen;
8723 #ifdef DISABLE_ICALL_TABLES
8725 no_icall_table (void)
8727 g_assert_not_reached ();
8732 mono_lookup_internal_call (MonoMethod *method)
8737 int typelen = 0, mlen, siglen;
8739 #ifndef DISABLE_ICALL_TABLES
8740 const IcallTypeDesc *imap = NULL;
8743 g_assert (method != NULL);
8745 if (method->is_inflated)
8746 method = ((MonoMethodInflated *) method)->declaring;
8748 if (method->klass->nested_in) {
8749 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8753 mname [pos++] = '/';
8756 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8762 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8767 #ifndef DISABLE_ICALL_TABLES
8768 imap = find_class_icalls (mname);
8771 mname [typelen] = ':';
8772 mname [typelen + 1] = ':';
8774 mlen = strlen (method->name);
8775 memcpy (mname + typelen + 2, method->name, mlen);
8776 sigstart = mname + typelen + 2 + mlen;
8779 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8780 siglen = strlen (tmpsig);
8781 if (typelen + mlen + siglen + 6 > sizeof (mname))
8784 memcpy (sigstart + 1, tmpsig, siglen);
8785 sigstart [siglen + 1] = ')';
8786 sigstart [siglen + 2] = 0;
8791 res = g_hash_table_lookup (icall_hash, mname);
8793 mono_icall_unlock ();;
8796 /* try without signature */
8798 res = g_hash_table_lookup (icall_hash, mname);
8800 mono_icall_unlock ();
8804 #ifdef DISABLE_ICALL_TABLES
8805 mono_icall_unlock ();
8806 /* Fail only when the result is actually used */
8807 /* mono_marshal_get_native_wrapper () depends on this */
8808 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8809 return ves_icall_System_String_ctor_RedirectToCreateString;
8811 return no_icall_table;
8813 /* it wasn't found in the static call tables */
8815 mono_icall_unlock ();
8818 res = find_method_icall (imap, sigstart - mlen);
8820 mono_icall_unlock ();
8823 /* try _with_ signature */
8825 res = find_method_icall (imap, sigstart - mlen);
8827 mono_icall_unlock ();
8831 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8832 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8833 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8834 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8835 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");
8836 g_print ("If you see other errors or faults after this message they are probably related\n");
8837 g_print ("and you need to fix your mono install first.\n");
8839 mono_icall_unlock ();
8845 #ifdef ENABLE_ICALL_SYMBOL_MAP
8847 func_cmp (gconstpointer key, gconstpointer p)
8849 return (gsize)key - (gsize)*(gsize*)p;
8854 * mono_lookup_icall_symbol:
8856 * Given the icall METHOD, returns its C symbol.
8859 mono_lookup_icall_symbol (MonoMethod *m)
8861 #ifdef DISABLE_ICALL_TABLES
8862 g_assert_not_reached ();
8865 #ifdef ENABLE_ICALL_SYMBOL_MAP
8869 static gconstpointer *functions_sorted;
8870 static const char**symbols_sorted;
8871 static gboolean inited;
8876 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8877 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8878 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8879 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8880 /* Bubble sort the two arrays */
8884 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8885 if (functions_sorted [i] > functions_sorted [i + 1]) {
8888 tmp = functions_sorted [i];
8889 functions_sorted [i] = functions_sorted [i + 1];
8890 functions_sorted [i + 1] = tmp;
8891 tmp = symbols_sorted [i];
8892 symbols_sorted [i] = symbols_sorted [i + 1];
8893 symbols_sorted [i + 1] = tmp;
8900 func = mono_lookup_internal_call (m);
8903 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8907 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8909 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8910 g_assert_not_reached ();
8917 type_from_typename (char *type_name)
8919 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8921 if (!strcmp (type_name, "int"))
8922 klass = mono_defaults.int_class;
8923 else if (!strcmp (type_name, "ptr"))
8924 klass = mono_defaults.int_class;
8925 else if (!strcmp (type_name, "void"))
8926 klass = mono_defaults.void_class;
8927 else if (!strcmp (type_name, "int32"))
8928 klass = mono_defaults.int32_class;
8929 else if (!strcmp (type_name, "uint32"))
8930 klass = mono_defaults.uint32_class;
8931 else if (!strcmp (type_name, "int8"))
8932 klass = mono_defaults.sbyte_class;
8933 else if (!strcmp (type_name, "uint8"))
8934 klass = mono_defaults.byte_class;
8935 else if (!strcmp (type_name, "int16"))
8936 klass = mono_defaults.int16_class;
8937 else if (!strcmp (type_name, "uint16"))
8938 klass = mono_defaults.uint16_class;
8939 else if (!strcmp (type_name, "long"))
8940 klass = mono_defaults.int64_class;
8941 else if (!strcmp (type_name, "ulong"))
8942 klass = mono_defaults.uint64_class;
8943 else if (!strcmp (type_name, "float"))
8944 klass = mono_defaults.single_class;
8945 else if (!strcmp (type_name, "double"))
8946 klass = mono_defaults.double_class;
8947 else if (!strcmp (type_name, "object"))
8948 klass = mono_defaults.object_class;
8949 else if (!strcmp (type_name, "obj"))
8950 klass = mono_defaults.object_class;
8951 else if (!strcmp (type_name, "string"))
8952 klass = mono_defaults.string_class;
8953 else if (!strcmp (type_name, "bool"))
8954 klass = mono_defaults.boolean_class;
8955 else if (!strcmp (type_name, "boolean"))
8956 klass = mono_defaults.boolean_class;
8958 g_error ("%s", type_name);
8959 g_assert_not_reached ();
8961 return &klass->byval_arg;
8965 * LOCKING: Take the corlib image lock.
8967 MonoMethodSignature*
8968 mono_create_icall_signature (const char *sigstr)
8973 MonoMethodSignature *res, *res2;
8974 MonoImage *corlib = mono_defaults.corlib;
8976 mono_image_lock (corlib);
8977 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8978 mono_image_unlock (corlib);
8983 parts = g_strsplit (sigstr, " ", 256);
8992 res = mono_metadata_signature_alloc (corlib, len - 1);
8997 * Under windows, the default pinvoke calling convention is STDCALL but
9000 res->call_convention = MONO_CALL_C;
9003 res->ret = type_from_typename (parts [0]);
9004 for (i = 1; i < len; ++i) {
9005 res->params [i - 1] = type_from_typename (parts [i]);
9010 mono_image_lock (corlib);
9011 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
9013 res = res2; /*Value is allocated in the image pool*/
9015 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
9016 mono_image_unlock (corlib);
9022 mono_find_jit_icall_by_name (const char *name)
9024 MonoJitICallInfo *info;
9025 g_assert (jit_icall_hash_name);
9028 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9029 mono_icall_unlock ();
9034 mono_find_jit_icall_by_addr (gconstpointer addr)
9036 MonoJitICallInfo *info;
9037 g_assert (jit_icall_hash_addr);
9040 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
9041 mono_icall_unlock ();
9047 * mono_get_jit_icall_info:
9049 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
9050 * caller should access it while holding the icall lock.
9053 mono_get_jit_icall_info (void)
9055 return jit_icall_hash_name;
9059 * mono_lookup_jit_icall_symbol:
9061 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
9064 mono_lookup_jit_icall_symbol (const char *name)
9066 MonoJitICallInfo *info;
9067 const char *res = NULL;
9070 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9072 res = info->c_symbol;
9073 mono_icall_unlock ();
9078 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
9081 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
9082 mono_icall_unlock ();
9086 * 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
9087 * icalls without wrappers in some cases.
9090 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
9092 MonoJitICallInfo *info;
9099 if (!jit_icall_hash_name) {
9100 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
9101 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
9104 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
9105 g_warning ("jit icall already defined \"%s\"\n", name);
9106 g_assert_not_reached ();
9109 info = g_new0 (MonoJitICallInfo, 1);
9114 info->c_symbol = c_symbol;
9115 info->no_raise = no_raise;
9118 info->wrapper = func;
9120 info->wrapper = NULL;
9123 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
9124 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
9126 mono_icall_unlock ();
9131 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
9133 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);