5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
9 * Aleksey Kliger (aleksey@xamarin.com)
11 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
12 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
14 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
25 #ifdef HAVE_SYS_TIME_H
31 #if defined (HOST_WIN32)
34 #if defined (HAVE_WCHAR_H)
38 #include "mono/utils/mono-membar.h"
39 #include <mono/metadata/object.h>
40 #include <mono/metadata/threads.h>
41 #include <mono/metadata/threads-types.h>
42 #include <mono/metadata/threadpool-ms.h>
43 #include <mono/metadata/threadpool-ms-io.h>
44 #include <mono/metadata/monitor.h>
45 #include <mono/metadata/reflection.h>
46 #include <mono/metadata/assembly.h>
47 #include <mono/metadata/tabledefs.h>
48 #include <mono/metadata/exception.h>
49 #include <mono/metadata/exception-internals.h>
50 #include <mono/metadata/file-io.h>
51 #include <mono/metadata/console-io.h>
52 #include <mono/metadata/mono-route.h>
53 #include <mono/metadata/socket-io.h>
54 #include <mono/metadata/mono-endian.h>
55 #include <mono/metadata/tokentype.h>
56 #include <mono/metadata/domain-internals.h>
57 #include <mono/metadata/metadata-internals.h>
58 #include <mono/metadata/class-internals.h>
59 #include <mono/metadata/reflection-internals.h>
60 #include <mono/metadata/marshal.h>
61 #include <mono/metadata/gc-internals.h>
62 #include <mono/metadata/mono-gc.h>
63 #include <mono/metadata/rand.h>
64 #include <mono/metadata/sysmath.h>
65 #include <mono/metadata/string-icalls.h>
66 #include <mono/metadata/debug-helpers.h>
67 #include <mono/metadata/process.h>
68 #include <mono/metadata/environment.h>
69 #include <mono/metadata/profiler-private.h>
70 #include <mono/metadata/locales.h>
71 #include <mono/metadata/filewatcher.h>
72 #include <mono/metadata/security.h>
73 #include <mono/metadata/mono-config.h>
74 #include <mono/metadata/cil-coff.h>
75 #include <mono/metadata/number-formatter.h>
76 #include <mono/metadata/security-manager.h>
77 #include <mono/metadata/security-core-clr.h>
78 #include <mono/metadata/mono-perfcounters.h>
79 #include <mono/metadata/mono-debug.h>
80 #include <mono/metadata/mono-ptr-array.h>
81 #include <mono/metadata/verify-internals.h>
82 #include <mono/metadata/runtime.h>
83 #include <mono/metadata/file-mmap.h>
84 #include <mono/metadata/seq-points-data.h>
85 #include <mono/io-layer/io-layer.h>
86 #include <mono/utils/monobitset.h>
87 #include <mono/utils/mono-time.h>
88 #include <mono/utils/mono-proclib.h>
89 #include <mono/utils/mono-string.h>
90 #include <mono/utils/mono-error-internals.h>
91 #include <mono/utils/mono-mmap.h>
92 #include <mono/utils/mono-io-portability.h>
93 #include <mono/utils/mono-digest.h>
94 #include <mono/utils/bsearch.h>
95 #include <mono/utils/mono-os-mutex.h>
96 #include <mono/utils/mono-threads.h>
98 #if defined (HOST_WIN32)
102 #include "decimal-ms.h"
103 #include "number-ms.h"
105 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
106 #include <sys/utsname.h>
109 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
111 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
113 /* Lazy class loading functions */
114 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
115 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
116 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
119 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
122 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
124 static inline MonoBoolean
125 is_generic_parameter (MonoType *type)
127 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
131 mono_class_init_checked (MonoClass *klass, MonoError *error)
133 mono_error_init (error);
135 if (!mono_class_init (klass))
136 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
139 ICALL_EXPORT MonoObject *
140 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
146 MonoObject *result = NULL;
148 ac = (MonoClass *)arr->obj.vtable->klass;
150 esize = mono_array_element_size (ac);
151 ea = (gpointer*)((char*)arr->vector + (pos * esize));
153 if (ac->element_class->valuetype) {
154 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
155 mono_error_set_pending_exception (&error);
157 result = (MonoObject *)*ea;
161 ICALL_EXPORT MonoObject *
162 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
168 MONO_CHECK_ARG_NULL (idxs, NULL);
171 ic = (MonoClass *)io->obj.vtable->klass;
173 ac = (MonoClass *)arr->obj.vtable->klass;
175 g_assert (ic->rank == 1);
176 if (io->bounds != NULL || io->max_length != ac->rank) {
177 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
181 ind = (gint32 *)io->vector;
183 if (arr->bounds == NULL) {
184 if (*ind < 0 || *ind >= arr->max_length) {
185 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
189 return ves_icall_System_Array_GetValueImpl (arr, *ind);
192 for (i = 0; i < ac->rank; i++) {
193 if ((ind [i] < arr->bounds [i].lower_bound) ||
194 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
195 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
200 pos = ind [0] - arr->bounds [0].lower_bound;
201 for (i = 1; i < ac->rank; i++)
202 pos = pos * arr->bounds [i].length + ind [i] -
203 arr->bounds [i].lower_bound;
205 return ves_icall_System_Array_GetValueImpl (arr, pos);
209 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
212 MonoClass *ac, *vc, *ec;
221 mono_error_init (&error);
224 vc = value->vtable->klass;
228 ac = arr->obj.vtable->klass;
229 ec = ac->element_class;
231 esize = mono_array_element_size (ac);
232 ea = (gpointer*)((char*)arr->vector + (pos * esize));
233 va = (gpointer*)((char*)value + sizeof (MonoObject));
235 if (mono_class_is_nullable (ec)) {
236 mono_nullable_init ((guint8*)ea, value, ec);
241 mono_gc_bzero_atomic (ea, esize);
245 #define NO_WIDENING_CONVERSION G_STMT_START{\
246 mono_set_pending_exception (mono_get_exception_argument ( \
247 "value", "not a widening conversion")); \
251 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
252 if (esize < vsize + (extra)) { \
253 mono_set_pending_exception (mono_get_exception_argument ( \
254 "value", "not a widening conversion")); \
259 #define INVALID_CAST G_STMT_START{ \
260 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
261 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
265 /* Check element (destination) type. */
266 switch (ec->byval_arg.type) {
267 case MONO_TYPE_STRING:
268 switch (vc->byval_arg.type) {
269 case MONO_TYPE_STRING:
275 case MONO_TYPE_BOOLEAN:
276 switch (vc->byval_arg.type) {
277 case MONO_TYPE_BOOLEAN:
290 NO_WIDENING_CONVERSION;
299 if (!ec->valuetype) {
300 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
301 if (mono_error_set_pending_exception (&error))
305 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
309 if (mono_object_isinst_checked (value, ec, &error)) {
310 if (ec->has_references)
311 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
313 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
316 if (mono_error_set_pending_exception (&error))
322 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
324 et = ec->byval_arg.type;
325 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
326 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
328 vt = vc->byval_arg.type;
329 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
330 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
332 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
338 case MONO_TYPE_CHAR: \
339 CHECK_WIDENING_CONVERSION(0); \
340 *(etype *) ea = (etype) u64; \
342 /* You can't assign a signed value to an unsigned array. */ \
347 /* You can't assign a floating point number to an integer array. */ \
350 NO_WIDENING_CONVERSION; \
354 #define ASSIGN_SIGNED(etype) G_STMT_START{\
360 CHECK_WIDENING_CONVERSION(0); \
361 *(etype *) ea = (etype) i64; \
363 /* You can assign an unsigned value to a signed array if the array's */ \
364 /* element size is larger than the value size. */ \
369 case MONO_TYPE_CHAR: \
370 CHECK_WIDENING_CONVERSION(1); \
371 *(etype *) ea = (etype) u64; \
373 /* You can't assign a floating point number to an integer array. */ \
376 NO_WIDENING_CONVERSION; \
380 #define ASSIGN_REAL(etype) G_STMT_START{\
384 CHECK_WIDENING_CONVERSION(0); \
385 *(etype *) ea = (etype) r64; \
387 /* All integer values fit into a floating point array, so we don't */ \
388 /* need to CHECK_WIDENING_CONVERSION here. */ \
393 *(etype *) ea = (etype) i64; \
399 case MONO_TYPE_CHAR: \
400 *(etype *) ea = (etype) u64; \
407 u64 = *(guint8 *) va;
410 u64 = *(guint16 *) va;
413 u64 = *(guint32 *) va;
416 u64 = *(guint64 *) va;
422 i64 = *(gint16 *) va;
425 i64 = *(gint32 *) va;
428 i64 = *(gint64 *) va;
431 r64 = *(gfloat *) va;
434 r64 = *(gdouble *) va;
437 u64 = *(guint16 *) va;
439 case MONO_TYPE_BOOLEAN:
440 /* Boolean is only compatible with itself. */
453 NO_WIDENING_CONVERSION;
460 /* If we can't do a direct copy, let's try a widening conversion. */
463 ASSIGN_UNSIGNED (guint16);
465 ASSIGN_UNSIGNED (guint8);
467 ASSIGN_UNSIGNED (guint16);
469 ASSIGN_UNSIGNED (guint32);
471 ASSIGN_UNSIGNED (guint64);
473 ASSIGN_SIGNED (gint8);
475 ASSIGN_SIGNED (gint16);
477 ASSIGN_SIGNED (gint32);
479 ASSIGN_SIGNED (gint64);
481 ASSIGN_REAL (gfloat);
483 ASSIGN_REAL (gdouble);
487 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
491 #undef NO_WIDENING_CONVERSION
492 #undef CHECK_WIDENING_CONVERSION
493 #undef ASSIGN_UNSIGNED
499 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
505 MONO_CHECK_ARG_NULL (idxs,);
507 ic = idxs->obj.vtable->klass;
508 ac = arr->obj.vtable->klass;
510 g_assert (ic->rank == 1);
511 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
512 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
516 ind = (gint32 *)idxs->vector;
518 if (arr->bounds == NULL) {
519 if (*ind < 0 || *ind >= arr->max_length) {
520 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
524 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
528 for (i = 0; i < ac->rank; i++)
529 if ((ind [i] < arr->bounds [i].lower_bound) ||
530 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
531 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
535 pos = ind [0] - arr->bounds [0].lower_bound;
536 for (i = 1; i < ac->rank; i++)
537 pos = pos * arr->bounds [i].length + ind [i] -
538 arr->bounds [i].lower_bound;
540 ves_icall_System_Array_SetValueImpl (arr, value, pos);
543 ICALL_EXPORT MonoArray *
544 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
547 MonoClass *aklass, *klass;
550 gboolean bounded = FALSE;
552 MONO_CHECK_ARG_NULL (type, NULL);
553 MONO_CHECK_ARG_NULL (lengths, NULL);
555 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
557 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
559 for (i = 0; i < mono_array_length (lengths); i++) {
560 if (mono_array_get (lengths, gint32, i) < 0) {
561 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
566 klass = mono_class_from_mono_type (type->type);
567 mono_class_init_checked (klass, &error);
568 if (mono_error_set_pending_exception (&error))
571 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
572 /* vectors are not the same as one dimensional arrays with no-zero bounds */
577 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
579 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
580 for (i = 0; i < aklass->rank; ++i) {
581 sizes [i] = mono_array_get (lengths, guint32, i);
583 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
585 sizes [i + aklass->rank] = 0;
588 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
589 mono_error_set_pending_exception (&error);
594 ICALL_EXPORT MonoArray *
595 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
598 MonoClass *aklass, *klass;
601 gboolean bounded = FALSE;
603 MONO_CHECK_ARG_NULL (type, NULL);
604 MONO_CHECK_ARG_NULL (lengths, NULL);
606 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
608 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
610 for (i = 0; i < mono_array_length (lengths); i++) {
611 if ((mono_array_get (lengths, gint64, i) < 0) ||
612 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
613 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
618 klass = mono_class_from_mono_type (type->type);
619 mono_class_init_checked (klass, &error);
620 if (mono_error_set_pending_exception (&error))
623 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
624 /* vectors are not the same as one dimensional arrays with no-zero bounds */
629 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
631 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
632 for (i = 0; i < aklass->rank; ++i) {
633 sizes [i] = mono_array_get (lengths, guint64, i);
635 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
637 sizes [i + aklass->rank] = 0;
640 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
641 mono_error_set_pending_exception (&error);
647 ves_icall_System_Array_GetRank (MonoObject *arr)
649 return arr->vtable->klass->rank;
653 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
655 gint32 rank = arr->obj.vtable->klass->rank;
658 if ((dimension < 0) || (dimension >= rank)) {
659 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
663 if (arr->bounds == NULL)
664 length = arr->max_length;
666 length = arr->bounds [dimension].length;
668 #ifdef MONO_BIG_ARRAYS
669 if (length > G_MAXINT32) {
670 mono_set_pending_exception (mono_get_exception_overflow ());
678 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
680 gint32 rank = arr->obj.vtable->klass->rank;
682 if ((dimension < 0) || (dimension >= rank)) {
683 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
687 if (arr->bounds == NULL)
688 return arr->max_length;
690 return arr->bounds [dimension].length;
694 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
696 gint32 rank = arr->obj.vtable->klass->rank;
698 if ((dimension < 0) || (dimension >= rank)) {
699 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
703 if (arr->bounds == NULL)
706 return arr->bounds [dimension].lower_bound;
710 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
712 int sz = mono_array_element_size (mono_object_class (arr));
713 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
716 ICALL_EXPORT MonoArray*
717 ves_icall_System_Array_Clone (MonoArray *arr)
720 MonoArray *result = mono_array_clone_checked (arr, &error);
721 mono_error_set_pending_exception (&error);
725 ICALL_EXPORT gboolean
726 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
731 MonoVTable *src_vtable;
732 MonoVTable *dest_vtable;
733 MonoClass *src_class;
734 MonoClass *dest_class;
736 src_vtable = source->obj.vtable;
737 dest_vtable = dest->obj.vtable;
739 if (src_vtable->rank != dest_vtable->rank)
742 if (source->bounds || dest->bounds)
745 /* there's no integer overflow since mono_array_length returns an unsigned integer */
746 if ((dest_idx + length > mono_array_length_fast (dest)) ||
747 (source_idx + length > mono_array_length_fast (source)))
750 src_class = src_vtable->klass->element_class;
751 dest_class = dest_vtable->klass->element_class;
754 * Handle common cases.
757 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
758 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
760 if (src_class == mono_defaults.object_class && dest_class->valuetype)
763 /* Check if we're copying a char[] <==> (u)short[] */
764 if (src_class != dest_class) {
765 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
768 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
769 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
773 if (dest_class->valuetype) {
774 element_size = mono_array_element_size (source->obj.vtable->klass);
775 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
776 if (dest_class->has_references) {
777 mono_value_copy_array (dest, dest_idx, source_addr, length);
779 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
780 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
783 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
790 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
796 ac = (MonoClass *)arr->obj.vtable->klass;
798 esize = mono_array_element_size (ac);
799 ea = (gpointer*)((char*)arr->vector + (pos * esize));
801 mono_gc_memmove_atomic (value, ea, esize);
805 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
811 ac = (MonoClass *)arr->obj.vtable->klass;
812 ec = ac->element_class;
814 esize = mono_array_element_size (ac);
815 ea = (gpointer*)((char*)arr->vector + (pos * esize));
817 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
818 g_assert (esize == sizeof (gpointer));
819 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
821 g_assert (ec->inited);
822 g_assert (esize == mono_class_value_size (ec, NULL));
823 if (ec->has_references)
824 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
826 mono_gc_memmove_atomic (ea, value, esize);
831 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
833 MonoClass *klass = array->obj.vtable->klass;
834 guint32 size = mono_array_element_size (klass);
835 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
837 const char *field_data;
839 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
840 MonoException *exc = mono_get_exception_argument("array",
841 "Cannot initialize array of non-primitive type.");
842 mono_set_pending_exception (exc);
846 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
847 MonoException *exc = mono_get_exception_argument("field_handle",
848 "Field doesn't have an RVA");
849 mono_set_pending_exception (exc);
853 size *= array->max_length;
854 field_data = mono_field_get_data (field_handle);
856 if (size > mono_type_size (field_handle->type, &align)) {
857 MonoException *exc = mono_get_exception_argument("field_handle",
858 "Field not large enough to fill array");
859 mono_set_pending_exception (exc);
863 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
865 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
866 guint ## n *src = (guint ## n *) field_data; \
868 nEnt = (size / sizeof(guint ## n)); \
870 for (i = 0; i < nEnt; i++) { \
871 data[i] = read ## n (&src[i]); \
875 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
877 switch (type->type) {
894 memcpy (mono_array_addr (array, char, 0), field_data, size);
898 memcpy (mono_array_addr (array, char, 0), field_data, size);
903 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
905 return offsetof (MonoString, chars);
908 ICALL_EXPORT MonoObject *
909 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
911 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
915 MonoObject *ret = mono_object_clone_checked (obj, &error);
916 mono_error_set_pending_exception (&error);
923 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
929 MONO_CHECK_ARG_NULL (handle,);
931 klass = mono_class_from_mono_type (handle);
932 MONO_CHECK_ARG (handle, klass,);
934 if (klass->generic_container)
937 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
938 if (!is_ok (&error)) {
939 mono_error_set_pending_exception (&error);
943 /* This will call the type constructor */
944 if (!mono_runtime_class_init_full (vtable, &error))
945 mono_error_set_pending_exception (&error);
949 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
953 mono_image_check_for_module_cctor (image);
954 if (image->has_module_cctor) {
955 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
956 if (!mono_error_ok (&error)) {
957 mono_error_set_pending_exception (&error);
960 /*It's fine to raise the exception here*/
961 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
962 if (!is_ok (&error)) {
963 mono_error_set_pending_exception (&error);
966 if (!mono_runtime_class_init_full (vtable, &error))
967 mono_error_set_pending_exception (&error);
971 ICALL_EXPORT MonoBoolean
972 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
977 /* later make this configurable and per-arch */
978 int min_size = 4096 * 4 * sizeof (void*);
979 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
980 /* if we have no info we are optimistic and assume there is enough room */
984 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
988 current = (guint8 *)&stack_addr;
989 if (current > stack_addr) {
990 if ((current - stack_addr) < min_size)
993 if (current - (stack_addr - stack_size) < min_size)
999 ICALL_EXPORT MonoObject *
1000 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
1003 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
1004 mono_error_set_pending_exception (&error);
1010 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1014 MonoObject **values = NULL;
1017 gint32 result = (int)(gsize)mono_defaults.int32_class;
1018 MonoClassField* field;
1021 klass = mono_object_class (this_obj);
1023 if (mono_class_num_fields (klass) == 0)
1027 * Compute the starting value of the hashcode for fields of primitive
1028 * types, and return the remaining fields in an array to the managed side.
1029 * This way, we can avoid costly reflection operations in managed code.
1032 while ((field = mono_class_get_fields (klass, &iter))) {
1033 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1035 if (mono_field_is_deleted (field))
1037 /* FIXME: Add more types */
1038 switch (field->type->type) {
1040 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1042 case MONO_TYPE_STRING: {
1044 s = *(MonoString**)((guint8*)this_obj + field->offset);
1046 result ^= mono_string_hash (s);
1051 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1052 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1053 if (!is_ok (&error)) {
1054 mono_error_set_pending_exception (&error);
1057 values [count++] = o;
1063 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1064 if (mono_error_set_pending_exception (&error))
1066 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1067 for (i = 0; i < count; ++i)
1068 mono_array_setref (*fields, i, values [i]);
1075 ICALL_EXPORT MonoBoolean
1076 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1080 MonoObject **values = NULL;
1082 MonoClassField* field;
1086 MONO_CHECK_ARG_NULL (that, FALSE);
1088 if (this_obj->vtable != that->vtable)
1091 klass = mono_object_class (this_obj);
1093 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1094 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1097 * Do the comparison for fields of primitive type and return a result if
1098 * possible. Otherwise, return the remaining fields in an array to the
1099 * managed side. This way, we can avoid costly reflection operations in
1104 while ((field = mono_class_get_fields (klass, &iter))) {
1105 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1107 if (mono_field_is_deleted (field))
1109 /* FIXME: Add more types */
1110 switch (field->type->type) {
1113 case MONO_TYPE_BOOLEAN:
1114 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1119 case MONO_TYPE_CHAR:
1120 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1125 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1130 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1134 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1138 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1143 case MONO_TYPE_STRING: {
1144 MonoString *s1, *s2;
1145 guint32 s1len, s2len;
1146 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1147 s2 = *(MonoString**)((guint8*)that + field->offset);
1150 if ((s1 == NULL) || (s2 == NULL))
1152 s1len = mono_string_length (s1);
1153 s2len = mono_string_length (s2);
1157 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1163 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1164 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1165 if (!is_ok (&error)) {
1166 mono_error_set_pending_exception (&error);
1169 values [count++] = o;
1170 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1171 if (!is_ok (&error)) {
1172 mono_error_set_pending_exception (&error);
1175 values [count++] = o;
1178 if (klass->enumtype)
1179 /* enums only have one non-static field */
1185 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1186 if (mono_error_set_pending_exception (&error))
1188 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1189 for (i = 0; i < count; ++i)
1190 mono_array_setref_fast (*fields, i, values [i]);
1197 ICALL_EXPORT MonoReflectionType *
1198 ves_icall_System_Object_GetType (MonoObject *obj)
1201 MonoReflectionType *ret;
1202 #ifndef DISABLE_REMOTING
1203 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1204 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1207 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1209 mono_error_set_pending_exception (&error);
1214 ves_icall_MonoType_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1216 mtype->type = &obj->vtable->klass->byval_arg;
1217 g_assert (mtype->type->type);
1221 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1223 MONO_CHECK_ARG_NULL (obj, 0);
1226 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1227 mono_error_set_pending_exception (&error);
1232 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1233 MonoReflectionMethod *method,
1234 MonoArray *opt_param_types)
1236 MONO_CHECK_ARG_NULL (method, 0);
1239 gint32 result = mono_image_create_method_token (
1240 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1241 mono_error_set_pending_exception (&error);
1246 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1249 mono_image_create_pefile (mb, file, &error);
1250 mono_error_set_pending_exception (&error);
1254 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1257 mono_image_build_metadata (mb, &error);
1258 mono_error_set_pending_exception (&error);
1262 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1264 mono_image_register_token (mb->dynamic_image, token, obj);
1267 ICALL_EXPORT MonoObject*
1268 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1272 mono_loader_lock ();
1273 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1274 mono_loader_unlock ();
1279 ICALL_EXPORT MonoReflectionModule*
1280 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1283 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1284 mono_error_set_pending_exception (&error);
1289 * ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class:
1290 * @tb: a TypeBuilder object
1293 * Creates the generic class after all generic parameters have been added.
1296 ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class (MonoReflectionTypeBuilder *tb)
1299 (void) mono_reflection_create_generic_class (tb, &error);
1300 mono_error_set_pending_exception (&error);
1303 #ifndef DISABLE_REFLECTION_EMIT
1304 ICALL_EXPORT MonoArray*
1305 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
1308 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
1309 mono_error_set_pending_exception (&error);
1315 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1317 MonoMethod **dest = (MonoMethod **)data;
1319 /* skip unmanaged frames */
1324 if (!strcmp (m->klass->name_space, "System.Reflection"))
1333 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1335 MonoMethod **dest = (MonoMethod **)data;
1337 /* skip unmanaged frames */
1341 if (m->wrapper_type != MONO_WRAPPER_NONE)
1349 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1360 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1362 MonoMethod **dest = (MonoMethod **)data;
1364 /* skip unmanaged frames */
1368 if (m->wrapper_type != MONO_WRAPPER_NONE)
1376 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1377 || (!strcmp (m->klass->name_space, "System"))))
1387 static MonoReflectionType *
1388 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1390 MonoMethod *m, *dest;
1392 MonoType *type = NULL;
1393 MonoAssembly *assembly = NULL;
1394 gboolean type_resolve = FALSE;
1395 MonoImage *rootimage = NULL;
1397 mono_error_init (error);
1400 * We must compute the calling assembly as type loading must happen under a metadata context.
1401 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1402 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1404 m = mono_method_get_last_managed ();
1406 if (m && m->klass->image != mono_defaults.corlib) {
1407 /* Happens with inlining */
1409 /* Ugly hack: type_from_parsed_name is called from
1410 * System.Type.internal_from_name, which is called most
1411 * directly from System.Type.GetType(string,bool,bool) but
1412 * also indirectly from places such as
1413 * System.Type.GetType(string,func,func) (via
1414 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1415 * so we need to skip over all of those to find the true caller.
1417 * It would be nice if we had stack marks.
1419 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1425 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1426 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1427 * to crash. This only seems to happen in some strange remoting
1428 * scenarios and I was unable to figure out what's happening there.
1429 * Dec 10, 2005 - Martin.
1433 assembly = dest->klass->image->assembly;
1434 type_resolve = TRUE;
1435 rootimage = assembly->image;
1437 g_warning (G_STRLOC);
1440 if (info->assembly.name)
1441 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1444 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1445 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1446 return_val_if_nok (error, NULL);
1450 // Say we're looking for System.Generic.Dict<int, Local>
1451 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1452 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1453 // is messed up when we go to construct the Local as the type arg...
1455 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1456 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1457 if (!info->assembly.name && !type) {
1459 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1460 return_val_if_nok (error, NULL);
1462 if (assembly && !type && type_resolve) {
1463 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1464 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1465 return_val_if_nok (error, NULL);
1471 return mono_type_get_object_checked (mono_domain_get (), type, error);
1474 ICALL_EXPORT MonoReflectionType*
1475 ves_icall_System_Type_internal_from_name (MonoString *name,
1476 MonoBoolean throwOnError,
1477 MonoBoolean ignoreCase)
1480 char *str = mono_string_to_utf8 (name);
1481 MonoTypeNameParse info;
1482 MonoReflectionType *type;
1485 parsedOk = mono_reflection_parse_type (str, &info);
1487 /* mono_reflection_parse_type() mangles the string */
1489 mono_reflection_free_type_info (&info);
1491 mono_error_init (&error);
1492 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1493 mono_error_set_pending_exception (&error);
1499 type = type_from_parsed_name (&info, ignoreCase, &error);
1501 mono_reflection_free_type_info (&info);
1504 if (!mono_error_ok (&error)) {
1506 mono_error_set_pending_exception (&error);
1508 mono_error_cleanup (&error);
1513 MonoException *e = NULL;
1516 e = mono_get_exception_type_load (name, NULL);
1519 mono_set_pending_exception (e);
1528 ICALL_EXPORT MonoReflectionType*
1529 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1532 MonoReflectionType *ret;
1533 MonoDomain *domain = mono_domain_get ();
1535 ret = mono_type_get_object_checked (domain, handle, &error);
1536 mono_error_set_pending_exception (&error);
1541 /* System.TypeCode */
1560 TYPECODE_STRING = 18
1563 ICALL_EXPORT guint32
1564 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1566 int t = type->type->type;
1568 if (type->type->byref)
1569 return TYPECODE_OBJECT;
1573 case MONO_TYPE_VOID:
1574 return TYPECODE_OBJECT;
1575 case MONO_TYPE_BOOLEAN:
1576 return TYPECODE_BOOLEAN;
1578 return TYPECODE_BYTE;
1580 return TYPECODE_SBYTE;
1582 return TYPECODE_UINT16;
1584 return TYPECODE_INT16;
1585 case MONO_TYPE_CHAR:
1586 return TYPECODE_CHAR;
1590 return TYPECODE_OBJECT;
1592 return TYPECODE_UINT32;
1594 return TYPECODE_INT32;
1596 return TYPECODE_UINT64;
1598 return TYPECODE_INT64;
1600 return TYPECODE_SINGLE;
1602 return TYPECODE_DOUBLE;
1603 case MONO_TYPE_VALUETYPE: {
1604 MonoClass *klass = type->type->data.klass;
1606 if (klass->enumtype) {
1607 t = mono_class_enum_basetype (klass)->type;
1609 } else if (mono_is_corlib_image (klass->image)) {
1610 if (strcmp (klass->name_space, "System") == 0) {
1611 if (strcmp (klass->name, "Decimal") == 0)
1612 return TYPECODE_DECIMAL;
1613 else if (strcmp (klass->name, "DateTime") == 0)
1614 return TYPECODE_DATETIME;
1617 return TYPECODE_OBJECT;
1619 case MONO_TYPE_STRING:
1620 return TYPECODE_STRING;
1621 case MONO_TYPE_SZARRAY:
1622 case MONO_TYPE_ARRAY:
1623 case MONO_TYPE_OBJECT:
1625 case MONO_TYPE_MVAR:
1626 case MONO_TYPE_TYPEDBYREF:
1627 return TYPECODE_OBJECT;
1628 case MONO_TYPE_CLASS:
1630 MonoClass *klass = type->type->data.klass;
1631 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1632 if (strcmp (klass->name, "DBNull") == 0)
1633 return TYPECODE_DBNULL;
1636 return TYPECODE_OBJECT;
1637 case MONO_TYPE_GENERICINST:
1638 return TYPECODE_OBJECT;
1640 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1646 mono_type_is_primitive (MonoType *type)
1648 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1649 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1653 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1655 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1656 return mono_class_enum_basetype (type->data.klass);
1657 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1658 return mono_class_enum_basetype (type->data.generic_class->container_class);
1662 ICALL_EXPORT guint32
1663 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1668 g_assert (type != NULL);
1670 klass = mono_class_from_mono_type (type->type);
1671 klassc = mono_class_from_mono_type (c->type);
1673 if (type->type->byref ^ c->type->byref)
1676 if (type->type->byref) {
1677 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1678 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1680 klass = mono_class_from_mono_type (t);
1681 klassc = mono_class_from_mono_type (ot);
1683 if (mono_type_is_primitive (t)) {
1684 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1685 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1686 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1687 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1688 return t->type == ot->type;
1690 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1693 if (klass->valuetype)
1694 return klass == klassc;
1695 return klass->valuetype == klassc->valuetype;
1698 return mono_class_is_assignable_from (klass, klassc);
1701 ICALL_EXPORT guint32
1702 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1705 MonoClass *klass = mono_class_from_mono_type (type->type);
1706 mono_class_init_checked (klass, &error);
1707 if (!is_ok (&error)) {
1708 mono_error_set_pending_exception (&error);
1711 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1712 mono_error_set_pending_exception (&error);
1716 ICALL_EXPORT guint32
1717 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1719 MonoClass *klass = mono_class_from_mono_type (type->type);
1720 return klass->flags;
1723 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1724 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1727 MonoClass *klass = field->field->parent;
1728 MonoMarshalType *info;
1732 if (klass->generic_container ||
1733 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1736 ftype = mono_field_get_type (field->field);
1737 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1740 info = mono_marshal_load_type_info (klass);
1742 for (i = 0; i < info->num_fields; ++i) {
1743 if (info->fields [i].field == field->field) {
1744 if (!info->fields [i].mspec)
1747 MonoReflectionMarshalAsAttribute* obj;
1748 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1749 if (!mono_error_ok (&error))
1750 mono_error_set_pending_exception (&error);
1759 ICALL_EXPORT MonoReflectionField*
1760 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1763 gboolean found = FALSE;
1770 klass = handle->parent;
1772 klass = mono_class_from_mono_type (type);
1774 /* Check that the field belongs to the class */
1775 for (k = klass; k; k = k->parent) {
1776 if (k == handle->parent) {
1783 /* The managed code will throw the exception */
1787 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1788 mono_error_set_pending_exception (&error);
1792 ICALL_EXPORT MonoArray*
1793 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1796 MonoType *type = mono_field_get_type_checked (field->field, &error);
1799 if (!mono_error_ok (&error)) {
1800 mono_error_set_pending_exception (&error);
1804 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1805 mono_error_set_pending_exception (&error);
1810 vell_icall_get_method_attributes (MonoMethod *method)
1812 return method->flags;
1816 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1819 MonoReflectionType *rt;
1820 MonoDomain *domain = mono_domain_get ();
1821 MonoMethodSignature* sig;
1823 sig = mono_method_signature_checked (method, &error);
1824 if (!mono_error_ok (&error)) {
1825 mono_error_set_pending_exception (&error);
1829 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1830 if (!mono_error_ok (&error)) {
1831 mono_error_set_pending_exception (&error);
1835 MONO_STRUCT_SETREF (info, parent, rt);
1837 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1838 if (!mono_error_ok (&error)) {
1839 mono_error_set_pending_exception (&error);
1843 MONO_STRUCT_SETREF (info, ret, rt);
1845 info->attrs = method->flags;
1846 info->implattrs = method->iflags;
1847 if (sig->call_convention == MONO_CALL_DEFAULT)
1848 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1850 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1855 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1858 ICALL_EXPORT MonoArray*
1859 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1862 MonoDomain *domain = mono_domain_get ();
1864 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1865 mono_error_set_pending_exception (&error);
1869 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1870 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1873 MonoDomain *domain = mono_domain_get ();
1874 MonoReflectionMarshalAsAttribute* res = NULL;
1875 MonoMarshalSpec **mspecs;
1878 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1879 mono_method_get_marshal_info (method, mspecs);
1882 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1883 if (!mono_error_ok (&error)) {
1884 mono_error_set_pending_exception (&error);
1889 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1891 mono_metadata_free_marshal_spec (mspecs [i]);
1898 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1900 MonoClass *parent = field->field->parent;
1901 if (!parent->size_inited)
1902 mono_class_init (parent);
1903 mono_class_setup_fields_locking (parent);
1905 return field->field->offset - sizeof (MonoObject);
1908 ICALL_EXPORT MonoReflectionType*
1909 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1912 MonoReflectionType *ret;
1915 parent = declaring? field->field->parent: field->klass;
1917 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1918 mono_error_set_pending_exception (&error);
1924 ICALL_EXPORT MonoObject *
1925 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1928 MonoClass *fklass = field->klass;
1929 MonoClassField *cf = field->field;
1930 MonoDomain *domain = mono_object_domain (field);
1932 if (fklass->image->assembly->ref_only) {
1933 mono_set_pending_exception (mono_get_exception_invalid_operation (
1934 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1938 if (mono_security_core_clr_enabled () &&
1939 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1940 mono_error_set_pending_exception (&error);
1944 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1945 mono_error_set_pending_exception (&error);
1950 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1953 MonoClassField *cf = field->field;
1957 if (field->klass->image->assembly->ref_only) {
1958 mono_set_pending_exception (mono_get_exception_invalid_operation (
1959 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1963 if (mono_security_core_clr_enabled () &&
1964 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1965 mono_error_set_pending_exception (&error);
1969 type = mono_field_get_type_checked (cf, &error);
1970 if (!mono_error_ok (&error)) {
1971 mono_error_set_pending_exception (&error);
1975 v = (gchar *) value;
1977 switch (type->type) {
1980 case MONO_TYPE_BOOLEAN:
1983 case MONO_TYPE_CHAR:
1992 case MONO_TYPE_VALUETYPE:
1995 v += sizeof (MonoObject);
1997 case MONO_TYPE_STRING:
1998 case MONO_TYPE_OBJECT:
1999 case MONO_TYPE_CLASS:
2000 case MONO_TYPE_ARRAY:
2001 case MONO_TYPE_SZARRAY:
2004 case MONO_TYPE_GENERICINST: {
2005 MonoGenericClass *gclass = type->data.generic_class;
2006 g_assert (!gclass->context.class_inst->is_open);
2008 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
2009 MonoClass *nklass = mono_class_from_mono_type (type);
2010 MonoObject *nullable;
2013 * Convert the boxed vtype into a Nullable structure.
2014 * This is complicated by the fact that Nullables have
2015 * a variable structure.
2017 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2018 if (!mono_error_ok (&error)) {
2019 mono_error_set_pending_exception (&error);
2023 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2025 v = (gchar *)mono_object_unbox (nullable);
2028 if (gclass->container_class->valuetype && (v != NULL))
2029 v += sizeof (MonoObject);
2033 g_error ("type 0x%x not handled in "
2034 "ves_icall_FieldInfo_SetValueInternal", type->type);
2039 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2040 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2041 if (!is_ok (&error)) {
2042 mono_error_set_pending_exception (&error);
2045 if (!vtable->initialized) {
2046 if (!mono_runtime_class_init_full (vtable, &error)) {
2047 mono_error_set_pending_exception (&error);
2051 mono_field_static_set_value (vtable, cf, v);
2053 mono_field_set_value (obj, cf, v);
2058 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2067 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2068 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2072 if (MONO_TYPE_IS_REFERENCE (f->type))
2073 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2075 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2078 ICALL_EXPORT MonoObject *
2079 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2081 MonoObject *o = NULL;
2082 MonoClassField *field = rfield->field;
2084 MonoDomain *domain = mono_object_domain (rfield);
2086 MonoTypeEnum def_type;
2087 const char *def_value;
2091 mono_class_init (field->parent);
2093 t = mono_field_get_type_checked (field, &error);
2094 if (!mono_error_ok (&error)) {
2095 mono_error_set_pending_exception (&error);
2099 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2100 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2104 if (image_is_dynamic (field->parent->image)) {
2105 MonoClass *klass = field->parent;
2106 int fidx = field - klass->fields;
2108 g_assert (fidx >= 0 && fidx < klass->field.count);
2109 g_assert (klass->ext);
2110 g_assert (klass->ext->field_def_values);
2111 def_type = klass->ext->field_def_values [fidx].def_type;
2112 def_value = klass->ext->field_def_values [fidx].data;
2113 if (def_type == MONO_TYPE_END) {
2114 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2118 def_value = mono_class_get_field_default_value (field, &def_type);
2119 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2121 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2126 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2130 case MONO_TYPE_BOOLEAN:
2133 case MONO_TYPE_CHAR:
2141 case MONO_TYPE_R8: {
2144 /* boxed value type */
2145 t = g_new0 (MonoType, 1);
2147 klass = mono_class_from_mono_type (t);
2149 o = mono_object_new_checked (domain, klass, &error);
2150 if (!mono_error_ok (&error)) {
2151 mono_error_set_pending_exception (&error);
2154 v = ((gchar *) o) + sizeof (MonoObject);
2155 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2158 case MONO_TYPE_STRING:
2159 case MONO_TYPE_CLASS:
2160 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2163 g_assert_not_reached ();
2169 ICALL_EXPORT MonoReflectionType*
2170 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2173 MonoReflectionType *ret;
2176 type = mono_field_get_type_checked (ref_field->field, &error);
2177 if (!mono_error_ok (&error)) {
2178 mono_error_set_pending_exception (&error);
2182 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2183 if (!mono_error_ok (&error)) {
2184 mono_error_set_pending_exception (&error);
2191 /* From MonoProperty.cs */
2193 PInfo_Attributes = 1,
2194 PInfo_GetMethod = 1 << 1,
2195 PInfo_SetMethod = 1 << 2,
2196 PInfo_ReflectedType = 1 << 3,
2197 PInfo_DeclaringType = 1 << 4,
2202 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2205 MonoReflectionType *rt;
2206 MonoReflectionMethod *rm;
2207 MonoDomain *domain = mono_object_domain (property);
2208 const MonoProperty *pproperty = property->property;
2210 if ((req_info & PInfo_ReflectedType) != 0) {
2211 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2212 if (mono_error_set_pending_exception (&error))
2215 MONO_STRUCT_SETREF (info, parent, rt);
2217 if ((req_info & PInfo_DeclaringType) != 0) {
2218 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2219 if (mono_error_set_pending_exception (&error))
2222 MONO_STRUCT_SETREF (info, declaring_type, rt);
2225 if ((req_info & PInfo_Name) != 0)
2226 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2228 if ((req_info & PInfo_Attributes) != 0)
2229 info->attrs = pproperty->attrs;
2231 if ((req_info & PInfo_GetMethod) != 0) {
2232 if (pproperty->get &&
2233 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2234 pproperty->get->klass == property->klass)) {
2235 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2236 if (mono_error_set_pending_exception (&error))
2242 MONO_STRUCT_SETREF (info, get, rm);
2244 if ((req_info & PInfo_SetMethod) != 0) {
2245 if (pproperty->set &&
2246 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2247 pproperty->set->klass == property->klass)) {
2248 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2249 if (mono_error_set_pending_exception (&error))
2255 MONO_STRUCT_SETREF (info, set, rm);
2258 * There may be other methods defined for properties, though, it seems they are not exposed
2259 * in the reflection API
2264 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2267 MonoReflectionType *rt;
2268 MonoReflectionMethod *rm;
2269 MonoDomain *domain = mono_object_domain (event);
2271 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2272 if (mono_error_set_pending_exception (&error))
2275 MONO_STRUCT_SETREF (info, reflected_type, rt);
2277 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2278 if (mono_error_set_pending_exception (&error))
2281 MONO_STRUCT_SETREF (info, declaring_type, rt);
2283 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2284 info->attrs = event->event->attrs;
2286 if (event->event->add) {
2287 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2288 if (mono_error_set_pending_exception (&error))
2294 MONO_STRUCT_SETREF (info, add_method, rm);
2296 if (event->event->remove) {
2297 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2298 if (mono_error_set_pending_exception (&error))
2304 MONO_STRUCT_SETREF (info, remove_method, rm);
2306 if (event->event->raise) {
2307 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2308 if (mono_error_set_pending_exception (&error))
2314 MONO_STRUCT_SETREF (info, raise_method, rm);
2316 #ifndef MONO_SMALL_CONFIG
2317 if (event->event->other) {
2319 while (event->event->other [n])
2321 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2322 if (mono_error_set_pending_exception (&error))
2324 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2326 for (i = 0; i < n; i++) {
2327 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2328 if (mono_error_set_pending_exception (&error))
2330 mono_array_setref (info->other_methods, i, rm);
2337 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2342 mono_class_setup_interfaces (klass, error);
2343 if (!mono_error_ok (error))
2346 for (i = 0; i < klass->interface_count; i++) {
2347 ic = klass->interfaces [i];
2348 g_hash_table_insert (ifaces, ic, ic);
2350 collect_interfaces (ic, ifaces, error);
2351 if (!mono_error_ok (error))
2357 MonoArray *iface_array;
2358 MonoGenericContext *context;
2362 } FillIfaceArrayData;
2365 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2367 MonoReflectionType *rt;
2368 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2369 MonoClass *ic = (MonoClass *)key;
2370 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2372 if (!mono_error_ok (data->error))
2375 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2376 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2377 if (!mono_error_ok (data->error))
2381 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2382 if (!mono_error_ok (data->error))
2385 mono_array_setref (data->iface_array, data->next_idx++, rt);
2388 mono_metadata_free_type (inflated);
2392 get_interfaces_hash (gconstpointer v1)
2394 MonoClass *k = (MonoClass*)v1;
2396 return k->type_token;
2399 ICALL_EXPORT MonoArray*
2400 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2403 MonoClass *klass = mono_class_from_mono_type (type->type);
2405 FillIfaceArrayData data = { 0 };
2408 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2410 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2411 data.context = mono_class_get_context (klass);
2412 klass = klass->generic_class->container_class;
2415 for (parent = klass; parent; parent = parent->parent) {
2416 mono_class_setup_interfaces (parent, &error);
2417 if (!mono_error_ok (&error))
2419 collect_interfaces (parent, iface_hash, &error);
2420 if (!mono_error_ok (&error))
2424 data.error = &error;
2425 data.domain = mono_object_domain (type);
2427 len = g_hash_table_size (iface_hash);
2429 g_hash_table_destroy (iface_hash);
2430 if (!data.domain->empty_types) {
2431 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0, &error);
2432 if (!is_ok (&error))
2435 return data.domain->empty_types;
2438 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len, &error);
2439 if (!is_ok (&error))
2441 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2442 if (!mono_error_ok (&error))
2445 g_hash_table_destroy (iface_hash);
2446 return data.iface_array;
2449 g_hash_table_destroy (iface_hash);
2450 mono_error_set_pending_exception (&error);
2455 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2457 gboolean variance_used;
2458 MonoClass *klass = mono_class_from_mono_type (type->type);
2459 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2460 MonoReflectionMethod *member;
2463 int i = 0, len, ioffset;
2467 mono_class_init_checked (klass, &error);
2468 if (mono_error_set_pending_exception (&error))
2470 mono_class_init_checked (iclass, &error);
2471 if (mono_error_set_pending_exception (&error))
2474 mono_class_setup_vtable (klass);
2476 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2480 len = mono_class_num_methods (iclass);
2481 domain = mono_object_domain (type);
2482 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2483 if (mono_error_set_pending_exception (&error))
2485 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2486 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2487 if (mono_error_set_pending_exception (&error))
2489 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2491 while ((method = mono_class_get_methods (iclass, &iter))) {
2492 member = mono_method_get_object_checked (domain, method, iclass, &error);
2493 if (mono_error_set_pending_exception (&error))
2495 mono_array_setref (*methods, i, member);
2496 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2497 if (mono_error_set_pending_exception (&error))
2499 mono_array_setref (*targets, i, member);
2506 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2509 MonoClass *klass = mono_class_from_mono_type (type->type);
2511 mono_class_init_checked (klass, &error);
2512 if (mono_error_set_pending_exception (&error))
2515 if (image_is_dynamic (klass->image)) {
2516 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2517 *packing = tb->packing_size;
2518 *size = tb->class_size;
2520 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2524 ICALL_EXPORT MonoReflectionType*
2525 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2528 MonoReflectionType *ret;
2531 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2532 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2533 mono_error_set_pending_exception (&error);
2537 klass = mono_class_from_mono_type (type->type);
2538 mono_class_init_checked (klass, &error);
2539 if (mono_error_set_pending_exception (&error))
2543 // GetElementType should only return a type for:
2544 // Array Pointer PassedByRef
2545 if (type->type->byref)
2546 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2547 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2548 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2549 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2550 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2554 mono_error_set_pending_exception (&error);
2559 ICALL_EXPORT MonoReflectionType*
2560 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2563 MonoReflectionType *ret;
2565 if (type->type->byref)
2568 MonoClass *klass = mono_class_from_mono_type (type->type);
2572 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2573 mono_error_set_pending_exception (&error);
2578 ICALL_EXPORT MonoBoolean
2579 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2581 return type->type->type == MONO_TYPE_PTR;
2584 ICALL_EXPORT MonoBoolean
2585 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2587 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)));
2590 ICALL_EXPORT MonoBoolean
2591 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2593 return type->type->byref;
2596 ICALL_EXPORT MonoBoolean
2597 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2600 MonoClass *klass = mono_class_from_mono_type (type->type);
2601 mono_class_init_checked (klass, &error);
2602 if (mono_error_set_pending_exception (&error))
2605 return mono_class_is_com_object (klass);
2608 ICALL_EXPORT guint32
2609 ves_icall_reflection_get_token (MonoObject* obj)
2612 guint32 result = mono_reflection_get_token_checked (obj, &error);
2613 mono_error_set_pending_exception (&error);
2617 ICALL_EXPORT MonoReflectionModule*
2618 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2621 MonoReflectionModule *result = NULL;
2622 MonoClass *klass = mono_class_from_mono_type (type->type);
2623 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2624 mono_error_set_pending_exception (&error);
2628 ICALL_EXPORT MonoReflectionAssembly*
2629 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2632 MonoDomain *domain = mono_domain_get ();
2633 MonoClass *klass = mono_class_from_mono_type (type->type);
2634 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2635 mono_error_set_pending_exception (&error);
2639 ICALL_EXPORT MonoReflectionType*
2640 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2643 MonoReflectionType *ret;
2644 MonoDomain *domain = mono_domain_get ();
2647 if (type->type->byref)
2649 if (type->type->type == MONO_TYPE_VAR) {
2650 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2651 klass = param ? param->owner.klass : NULL;
2652 } else if (type->type->type == MONO_TYPE_MVAR) {
2653 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2654 klass = param ? param->owner.method->klass : NULL;
2656 klass = mono_class_from_mono_type (type->type)->nested_in;
2662 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2663 mono_error_set_pending_exception (&error);
2668 ICALL_EXPORT MonoString*
2669 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2671 MonoDomain *domain = mono_domain_get ();
2672 MonoClass *klass = mono_class_from_mono_type (type->type);
2674 if (type->type->byref) {
2675 char *n = g_strdup_printf ("%s&", klass->name);
2676 MonoString *res = mono_string_new (domain, n);
2682 return mono_string_new (domain, klass->name);
2686 ICALL_EXPORT MonoString*
2687 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2689 MonoDomain *domain = mono_domain_get ();
2690 MonoClass *klass = mono_class_from_mono_type (type->type);
2692 while (klass->nested_in)
2693 klass = klass->nested_in;
2695 if (klass->name_space [0] == '\0')
2698 return mono_string_new (domain, klass->name_space);
2702 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2706 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2707 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2711 klass = mono_class_from_mono_type (type->type);
2717 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2719 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2722 ICALL_EXPORT MonoArray*
2723 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2726 MonoReflectionType *rt;
2728 MonoClass *klass, *pklass;
2729 MonoDomain *domain = mono_object_domain (type);
2732 klass = mono_class_from_mono_type (type->type);
2734 if (klass->generic_container) {
2735 MonoGenericContainer *container = klass->generic_container;
2736 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2737 if (mono_error_set_pending_exception (&error))
2739 for (i = 0; i < container->type_argc; ++i) {
2740 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2742 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2743 if (mono_error_set_pending_exception (&error))
2746 mono_array_setref (res, i, rt);
2748 } else if (klass->generic_class) {
2749 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2750 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2751 if (mono_error_set_pending_exception (&error))
2753 for (i = 0; i < inst->type_argc; ++i) {
2754 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2755 if (mono_error_set_pending_exception (&error))
2758 mono_array_setref (res, i, rt);
2766 ICALL_EXPORT gboolean
2767 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2771 if (!IS_MONOTYPE (type))
2774 if (type->type->byref)
2777 klass = mono_class_from_mono_type (type->type);
2778 return klass->generic_container != NULL;
2781 ICALL_EXPORT MonoReflectionType*
2782 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2785 MonoReflectionType *ret;
2788 if (type->type->byref)
2791 klass = mono_class_from_mono_type (type->type);
2793 if (klass->generic_container) {
2794 return type; /* check this one */
2796 if (klass->generic_class) {
2797 MonoClass *generic_class = klass->generic_class->container_class;
2800 tb = mono_class_get_ref_info (generic_class);
2802 if (generic_class->wastypebuilder && tb)
2803 return (MonoReflectionType *)tb;
2805 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2806 mono_error_set_pending_exception (&error);
2814 ICALL_EXPORT MonoReflectionType*
2815 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2818 MonoReflectionType *ret;
2820 MonoType *geninst, **types;
2823 g_assert (IS_MONOTYPE (type));
2824 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2825 if (mono_error_set_pending_exception (&error))
2828 count = mono_array_length (type_array);
2829 types = g_new0 (MonoType *, count);
2831 for (i = 0; i < count; i++) {
2832 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2833 types [i] = t->type;
2836 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2839 mono_error_set_pending_exception (&error);
2843 klass = mono_class_from_mono_type (geninst);
2845 /*we might inflate to the GTD*/
2846 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2847 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2851 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2852 mono_error_set_pending_exception (&error);
2857 ICALL_EXPORT gboolean
2858 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2862 if (!IS_MONOTYPE (type))
2865 if (type->type->byref)
2868 klass = mono_class_from_mono_type (type->type);
2869 return klass->generic_class != NULL || klass->generic_container != NULL;
2873 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2875 if (!IS_MONOTYPE (type))
2878 if (is_generic_parameter (type->type))
2879 return mono_type_get_generic_param_num (type->type);
2883 ICALL_EXPORT GenericParameterAttributes
2884 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2886 g_assert (IS_MONOTYPE (type));
2887 g_assert (is_generic_parameter (type->type));
2888 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2891 ICALL_EXPORT MonoArray *
2892 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2895 MonoReflectionType *rt;
2896 MonoGenericParamInfo *param_info;
2902 g_assert (IS_MONOTYPE (type));
2904 domain = mono_object_domain (type);
2905 param_info = mono_generic_param_info (type->type->data.generic_param);
2906 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2909 res = mono_array_new_checked (domain, mono_defaults.monotype_class, count, &error);
2910 if (mono_error_set_pending_exception (&error))
2912 for (i = 0; i < count; i++) {
2913 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2914 if (mono_error_set_pending_exception (&error))
2917 mono_array_setref (res, i, rt);
2924 ICALL_EXPORT MonoBoolean
2925 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2927 return is_generic_parameter (type->type);
2930 ICALL_EXPORT MonoBoolean
2931 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2933 return is_generic_parameter (tb->type.type);
2937 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2938 MonoReflectionType *t)
2940 enumtype->type = t->type;
2943 ICALL_EXPORT MonoReflectionMethod*
2944 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2945 MonoReflectionMethod* generic)
2952 MonoReflectionMethod *ret = NULL;
2954 domain = ((MonoObject *)type)->vtable->domain;
2956 klass = mono_class_from_mono_type (type->type);
2957 mono_class_init_checked (klass, &error);
2958 if (mono_error_set_pending_exception (&error))
2962 while ((method = mono_class_get_methods (klass, &iter))) {
2963 if (method->token == generic->method->token) {
2964 ret = mono_method_get_object_checked (domain, method, klass, &error);
2965 if (mono_error_set_pending_exception (&error))
2973 ICALL_EXPORT MonoReflectionMethod *
2974 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2977 MonoType *type = ref_type->type;
2979 MonoReflectionMethod *ret = NULL;
2981 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2982 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2985 if (type->type == MONO_TYPE_VAR)
2988 method = mono_type_get_generic_param_owner (type)->owner.method;
2991 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2992 if (!mono_error_ok (&error))
2993 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2997 ICALL_EXPORT MonoBoolean
2998 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
3000 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3004 ICALL_EXPORT MonoBoolean
3005 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
3007 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3012 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
3014 MonoDomain *domain = mono_domain_get ();
3015 MonoImage *image = method->method->klass->image;
3016 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
3017 MonoTableInfo *tables = image->tables;
3018 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
3019 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
3020 guint32 im_cols [MONO_IMPLMAP_SIZE];
3021 guint32 scope_token;
3022 const char *import = NULL;
3023 const char *scope = NULL;
3025 if (image_is_dynamic (image)) {
3026 MonoReflectionMethodAux *method_aux =
3027 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
3029 import = method_aux->dllentry;
3030 scope = method_aux->dll;
3033 if (!import || !scope) {
3034 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
3039 if (piinfo->implmap_idx) {
3040 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
3042 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
3043 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
3044 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
3045 scope = mono_metadata_string_heap (image, scope_token);
3049 *flags = piinfo->piflags;
3050 *entry_point = mono_string_new (domain, import);
3051 *dll_name = mono_string_new (domain, scope);
3054 ICALL_EXPORT MonoReflectionMethod *
3055 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3057 MonoMethodInflated *imethod;
3059 MonoReflectionMethod *ret = NULL;
3062 if (method->method->is_generic)
3065 if (!method->method->is_inflated)
3068 imethod = (MonoMethodInflated *) method->method;
3070 result = imethod->declaring;
3071 /* Not a generic method. */
3072 if (!result->is_generic)
3075 if (image_is_dynamic (method->method->klass->image)) {
3076 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3077 MonoReflectionMethod *res;
3080 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3081 * the dynamic case as well ?
3083 mono_image_lock ((MonoImage*)image);
3084 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3085 mono_image_unlock ((MonoImage*)image);
3091 if (imethod->context.class_inst) {
3092 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3093 /*Generic methods gets the context of the GTD.*/
3094 if (mono_class_get_context (klass)) {
3095 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3096 if (!mono_error_ok (&error))
3101 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3103 if (!mono_error_ok (&error))
3104 mono_error_set_pending_exception (&error);
3108 ICALL_EXPORT gboolean
3109 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3111 return mono_method_signature (method->method)->generic_param_count != 0;
3114 ICALL_EXPORT gboolean
3115 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3117 return method->method->is_generic;
3120 ICALL_EXPORT MonoArray*
3121 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3124 MonoReflectionType *rt;
3129 domain = mono_object_domain (method);
3131 if (method->method->is_inflated) {
3132 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3135 count = inst->type_argc;
3136 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3137 if (mono_error_set_pending_exception (&error))
3140 for (i = 0; i < count; i++) {
3141 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3142 if (mono_error_set_pending_exception (&error))
3145 mono_array_setref (res, i, rt);
3152 count = mono_method_signature (method->method)->generic_param_count;
3153 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3154 if (mono_error_set_pending_exception (&error))
3157 for (i = 0; i < count; i++) {
3158 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3159 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3160 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3162 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3163 if (mono_error_set_pending_exception (&error))
3166 mono_array_setref (res, i, rt);
3172 ICALL_EXPORT MonoObject *
3173 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3177 * Invoke from reflection is supposed to always be a virtual call (the API
3178 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3179 * greater flexibility.
3181 MonoMethod *m = method->method;
3182 MonoMethodSignature *sig = mono_method_signature (m);
3185 void *obj = this_arg;
3189 if (mono_security_core_clr_enabled () &&
3190 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3191 mono_error_set_pending_exception (&error);
3195 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3196 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3197 mono_error_cleanup (&error); /* FIXME does this make sense? */
3198 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3203 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3204 if (!is_ok (&error)) {
3205 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3208 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3209 char *target_name = mono_type_get_full_name (m->klass);
3210 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3211 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3213 g_free (target_name);
3217 m = mono_object_get_virtual_method (this_arg, m);
3218 /* must pass the pointer to the value for valuetype methods */
3219 if (m->klass->valuetype)
3220 obj = mono_object_unbox (this_arg);
3221 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3222 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3227 if (sig->ret->byref) {
3228 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"));
3232 pcount = params? mono_array_length (params): 0;
3233 if (pcount != sig->param_count) {
3234 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3238 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3239 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."));
3243 image = m->klass->image;
3244 if (image->assembly->ref_only) {
3245 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."));
3249 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3250 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3254 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3258 intptr_t *lower_bounds;
3259 pcount = mono_array_length (params);
3260 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3261 /* Note: the synthetized array .ctors have int32 as argument type */
3262 for (i = 0; i < pcount; ++i)
3263 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3265 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3266 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3267 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3268 if (!mono_error_ok (&error)) {
3269 mono_error_set_pending_exception (&error);
3273 for (i = 0; i < mono_array_length (arr); ++i) {
3274 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3275 if (!mono_error_ok (&error)) {
3276 mono_error_set_pending_exception (&error);
3279 mono_array_setref_fast (arr, i, subarray);
3281 return (MonoObject*)arr;
3284 if (m->klass->rank == pcount) {
3285 /* Only lengths provided. */
3286 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3287 if (!mono_error_ok (&error)) {
3288 mono_error_set_pending_exception (&error);
3292 return (MonoObject*)arr;
3294 g_assert (pcount == (m->klass->rank * 2));
3295 /* The arguments are lower-bound-length pairs */
3296 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3298 for (i = 0; i < pcount / 2; ++i) {
3299 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3300 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3303 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3304 if (!mono_error_ok (&error)) {
3305 mono_error_set_pending_exception (&error);
3309 return (MonoObject*)arr;
3312 return mono_runtime_invoke_array (m, obj, params, NULL);
3315 #ifndef DISABLE_REMOTING
3316 ICALL_EXPORT MonoObject *
3317 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3320 MonoDomain *domain = mono_object_domain (method);
3321 MonoMethod *m = method->method;
3322 MonoMethodSignature *sig = mono_method_signature (m);
3323 MonoArray *out_args;
3325 int i, j, outarg_count = 0;
3327 if (m->klass == mono_defaults.object_class) {
3328 if (!strcmp (m->name, "FieldGetter")) {
3329 MonoClass *k = this_arg->vtable->klass;
3333 /* If this is a proxy, then it must be a CBO */
3334 if (k == mono_defaults.transparent_proxy_class) {
3335 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3336 this_arg = tp->rp->unwrapped_server;
3337 g_assert (this_arg);
3338 k = this_arg->vtable->klass;
3341 name = mono_array_get (params, MonoString *, 1);
3342 str = mono_string_to_utf8 (name);
3345 MonoClassField* field = mono_class_get_field_from_name (k, str);
3348 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3349 if (field_klass->valuetype) {
3350 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3351 if (mono_error_set_pending_exception (&error))
3354 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3356 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3357 if (mono_error_set_pending_exception (&error))
3359 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3360 mono_array_setref (out_args, 0, result);
3367 g_assert_not_reached ();
3369 } else if (!strcmp (m->name, "FieldSetter")) {
3370 MonoClass *k = this_arg->vtable->klass;
3376 /* If this is a proxy, then it must be a CBO */
3377 if (k == mono_defaults.transparent_proxy_class) {
3378 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3379 this_arg = tp->rp->unwrapped_server;
3380 g_assert (this_arg);
3381 k = this_arg->vtable->klass;
3384 name = mono_array_get (params, MonoString *, 1);
3385 str = mono_string_to_utf8 (name);
3388 MonoClassField* field = mono_class_get_field_from_name (k, str);
3391 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3392 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3394 if (field_klass->valuetype) {
3395 size = mono_type_size (field->type, &align);
3396 g_assert (size == mono_class_value_size (field_klass, NULL));
3397 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3399 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3402 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3403 if (mono_error_set_pending_exception (&error))
3405 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3414 g_assert_not_reached ();
3419 for (i = 0; i < mono_array_length (params); i++) {
3420 if (sig->params [i]->byref)
3424 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3425 if (mono_error_set_pending_exception (&error))
3428 /* handle constructors only for objects already allocated */
3429 if (!strcmp (method->method->name, ".ctor"))
3430 g_assert (this_arg);
3432 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3433 g_assert (!method->method->klass->valuetype);
3434 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3436 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3437 if (sig->params [i]->byref) {
3439 arg = mono_array_get (params, gpointer, i);
3440 mono_array_setref (out_args, j, arg);
3445 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3452 read_enum_value (const char *mem, int type)
3455 case MONO_TYPE_BOOLEAN:
3457 return *(guint8*)mem;
3459 return *(gint8*)mem;
3460 case MONO_TYPE_CHAR:
3462 return read16 (mem);
3464 return (gint16) read16 (mem);
3466 return read32 (mem);
3468 return (gint32) read32 (mem);
3471 return read64 (mem);
3473 g_assert_not_reached ();
3479 write_enum_value (char *mem, int type, guint64 value)
3483 case MONO_TYPE_I1: {
3484 guint8 *p = (guint8*)mem;
3490 case MONO_TYPE_CHAR: {
3491 guint16 *p = (guint16 *)mem;
3496 case MONO_TYPE_I4: {
3497 guint32 *p = (guint32 *)mem;
3502 case MONO_TYPE_I8: {
3503 guint64 *p = (guint64 *)mem;
3508 g_assert_not_reached ();
3513 ICALL_EXPORT MonoObject *
3514 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3522 domain = mono_object_domain (enumType);
3523 enumc = mono_class_from_mono_type (enumType->type);
3525 mono_class_init_checked (enumc, &error);
3526 if (mono_error_set_pending_exception (&error))
3529 etype = mono_class_enum_basetype (enumc);
3531 res = mono_object_new_checked (domain, enumc, &error);
3532 if (mono_error_set_pending_exception (&error))
3534 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3539 ICALL_EXPORT MonoBoolean
3540 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3542 int size = mono_class_value_size (a->vtable->klass, NULL);
3543 guint64 a_val = 0, b_val = 0;
3545 memcpy (&a_val, mono_object_unbox (a), size);
3546 memcpy (&b_val, mono_object_unbox (b), size);
3548 return (a_val & b_val) == b_val;
3551 ICALL_EXPORT MonoObject *
3552 ves_icall_System_Enum_get_value (MonoObject *eobj)
3564 g_assert (eobj->vtable->klass->enumtype);
3566 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3567 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3568 if (mono_error_set_pending_exception (&error))
3570 dst = (char *)res + sizeof (MonoObject);
3571 src = (char *)eobj + sizeof (MonoObject);
3572 size = mono_class_value_size (enumc, NULL);
3574 memcpy (dst, src, size);
3579 ICALL_EXPORT MonoReflectionType *
3580 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3583 MonoReflectionType *ret;
3587 klass = mono_class_from_mono_type (type->type);
3588 mono_class_init_checked (klass, &error);
3589 if (mono_error_set_pending_exception (&error))
3592 etype = mono_class_enum_basetype (klass);
3594 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3598 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3599 mono_error_set_pending_exception (&error);
3605 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3607 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3608 gpointer odata = (char *)other + sizeof (MonoObject);
3609 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3610 g_assert (basetype);
3615 if (eobj->vtable->klass != other->vtable->klass)
3618 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3619 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3620 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3623 return me > other ? 1 : -1; \
3626 switch (basetype->type) {
3628 COMPARE_ENUM_VALUES (guint8);
3630 COMPARE_ENUM_VALUES (gint8);
3631 case MONO_TYPE_CHAR:
3633 COMPARE_ENUM_VALUES (guint16);
3635 COMPARE_ENUM_VALUES (gint16);
3637 COMPARE_ENUM_VALUES (guint32);
3639 COMPARE_ENUM_VALUES (gint32);
3641 COMPARE_ENUM_VALUES (guint64);
3643 COMPARE_ENUM_VALUES (gint64);
3647 #undef COMPARE_ENUM_VALUES
3648 /* indicates that the enum was of an unsupported unerlying type */
3653 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3655 gpointer data = (char *)eobj + sizeof (MonoObject);
3656 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3657 g_assert (basetype);
3659 switch (basetype->type) {
3660 case MONO_TYPE_I1: {
3661 gint8 value = *((gint8*)data);
3662 return ((int)value ^ (int)value << 8);
3665 return *((guint8*)data);
3666 case MONO_TYPE_CHAR:
3668 return *((guint16*)data);
3670 case MONO_TYPE_I2: {
3671 gint16 value = *((gint16*)data);
3672 return ((int)(guint16)value | (((int)value) << 16));
3675 return *((guint32*)data);
3677 return *((gint32*)data);
3679 case MONO_TYPE_I8: {
3680 gint64 value = *((gint64*)data);
3681 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3684 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3689 ICALL_EXPORT MonoBoolean
3690 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3693 MonoDomain *domain = mono_object_domain (type);
3694 MonoClass *enumc = mono_class_from_mono_type (type->type);
3695 guint j = 0, nvalues;
3697 MonoClassField *field;
3699 guint64 field_value, previous_value = 0;
3700 gboolean sorted = TRUE;
3702 mono_class_init_checked (enumc, &error);
3703 if (mono_error_set_pending_exception (&error))
3707 if (!enumc->enumtype) {
3708 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3712 base_type = mono_class_enum_basetype (enumc)->type;
3714 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3715 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3716 if (mono_error_set_pending_exception (&error))
3718 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3719 if (mono_error_set_pending_exception (&error))
3723 while ((field = mono_class_get_fields (enumc, &iter))) {
3725 MonoTypeEnum def_type;
3727 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3729 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3731 if (mono_field_is_deleted (field))
3733 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3735 p = mono_class_get_field_default_value (field, &def_type);
3736 /* len = */ mono_metadata_decode_blob_size (p, &p);
3738 field_value = read_enum_value (p, base_type);
3739 mono_array_set (*values, guint64, j, field_value);
3741 if (previous_value > field_value)
3744 previous_value = field_value;
3752 BFLAGS_IgnoreCase = 1,
3753 BFLAGS_DeclaredOnly = 2,
3754 BFLAGS_Instance = 4,
3756 BFLAGS_Public = 0x10,
3757 BFLAGS_NonPublic = 0x20,
3758 BFLAGS_FlattenHierarchy = 0x40,
3759 BFLAGS_InvokeMethod = 0x100,
3760 BFLAGS_CreateInstance = 0x200,
3761 BFLAGS_GetField = 0x400,
3762 BFLAGS_SetField = 0x800,
3763 BFLAGS_GetProperty = 0x1000,
3764 BFLAGS_SetProperty = 0x2000,
3765 BFLAGS_ExactBinding = 0x10000,
3766 BFLAGS_SuppressChangeType = 0x20000,
3767 BFLAGS_OptionalParamBinding = 0x40000
3770 ICALL_EXPORT MonoArray*
3771 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3775 MonoClass *startklass, *klass, *refklass;
3780 char *utf8_name = NULL;
3781 int (*compare_func) (const char *s1, const char *s2) = NULL;
3782 MonoClassField *field;
3783 MonoPtrArray tmp_array;
3785 domain = ((MonoObject *)type)->vtable->domain;
3786 if (type->type->byref) {
3787 MonoArray *result = mono_array_new_checked (domain, mono_defaults.field_info_class, 0, &error);
3788 mono_error_set_pending_exception (&error);
3792 klass = startklass = mono_class_from_mono_type (type->type);
3793 refklass = mono_class_from_mono_type (reftype->type);
3795 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3798 if (mono_class_has_failure (klass)) {
3799 mono_ptr_array_destroy (tmp_array);
3800 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3805 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3806 guint32 flags = mono_field_get_flags (field);
3808 if (mono_field_is_deleted_with_flags (field, flags))
3810 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3811 if (bflags & BFLAGS_Public)
3813 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3814 if (bflags & BFLAGS_NonPublic) {
3821 if (flags & FIELD_ATTRIBUTE_STATIC) {
3822 if (bflags & BFLAGS_Static)
3823 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3826 if (bflags & BFLAGS_Instance)
3834 if (utf8_name == NULL) {
3835 utf8_name = mono_string_to_utf8 (name);
3836 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3839 if (compare_func (mono_field_get_name (field), utf8_name))
3843 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3844 if (!mono_error_ok (&error))
3846 mono_ptr_array_append (tmp_array, member);
3848 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3851 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array), &error);
3852 if (!is_ok (&error))
3855 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3856 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3858 mono_ptr_array_destroy (tmp_array);
3860 if (utf8_name != NULL)
3865 mono_ptr_array_destroy (tmp_array);
3866 mono_error_set_pending_exception (&error);
3871 method_nonpublic (MonoMethod* method, gboolean start_klass)
3873 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3874 case METHOD_ATTRIBUTE_ASSEM:
3875 return (start_klass || mono_defaults.generic_ilist_class);
3876 case METHOD_ATTRIBUTE_PRIVATE:
3878 case METHOD_ATTRIBUTE_PUBLIC:
3886 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3889 MonoClass *startklass;
3893 /*FIXME, use MonoBitSet*/
3894 guint32 method_slots_default [8];
3895 guint32 *method_slots = NULL;
3896 int (*compare_func) (const char *s1, const char *s2) = NULL;
3898 array = g_ptr_array_new ();
3903 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3905 /* An optimization for calls made from Delegate:CreateDelegate () */
3906 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3907 method = mono_get_delegate_invoke (klass);
3910 g_ptr_array_add (array, method);
3914 mono_class_setup_methods (klass);
3915 mono_class_setup_vtable (klass);
3916 if (mono_class_has_failure (klass))
3919 if (is_generic_parameter (&klass->byval_arg))
3920 nslots = mono_class_get_vtable_size (klass->parent);
3922 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3923 if (nslots >= sizeof (method_slots_default) * 8) {
3924 method_slots = g_new0 (guint32, nslots / 32 + 1);
3926 method_slots = method_slots_default;
3927 memset (method_slots, 0, sizeof (method_slots_default));
3930 mono_class_setup_methods (klass);
3931 mono_class_setup_vtable (klass);
3932 if (mono_class_has_failure (klass))
3936 while ((method = mono_class_get_methods (klass, &iter))) {
3938 if (method->slot != -1) {
3939 g_assert (method->slot < nslots);
3940 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3942 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3943 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3946 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3948 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3949 if (bflags & BFLAGS_Public)
3951 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3957 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3958 if (bflags & BFLAGS_Static)
3959 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3962 if (bflags & BFLAGS_Instance)
3970 if (compare_func (name, method->name))
3975 g_ptr_array_add (array, method);
3977 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3979 if (method_slots != method_slots_default)
3980 g_free (method_slots);
3985 if (method_slots != method_slots_default)
3986 g_free (method_slots);
3987 g_ptr_array_free (array, TRUE);
3989 if (mono_class_has_failure (klass)) {
3990 *ex = mono_class_get_exception_for_failure (klass);
3992 *ex = mono_get_exception_execution_engine ("Unknown error");
3997 ICALL_EXPORT MonoArray*
3998 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4000 static MonoClass *MethodInfo_array;
4004 MonoVTable *array_vtable;
4005 MonoException *ex = NULL;
4006 const char *mname = NULL;
4007 GPtrArray *method_array;
4008 MonoClass *klass, *refklass;
4011 mono_error_init (&error);
4013 if (!MethodInfo_array) {
4014 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
4015 mono_memory_barrier ();
4016 MethodInfo_array = klass;
4019 klass = mono_class_from_mono_type (type->type);
4020 refklass = mono_class_from_mono_type (reftype->type);
4021 domain = ((MonoObject *)type)->vtable->domain;
4022 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
4023 if (!is_ok (&error)) {
4024 mono_error_set_pending_exception (&error);
4027 if (type->type->byref) {
4028 res = mono_array_new_specific_checked (array_vtable, 0, &error);
4029 mono_error_set_pending_exception (&error);
4035 mname = mono_string_to_utf8 (name);
4037 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
4038 g_free ((char*)mname);
4040 mono_set_pending_exception (ex);
4044 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
4045 if (!mono_error_ok (&error)) {
4046 mono_error_set_pending_exception (&error);
4050 for (i = 0; i < method_array->len; ++i) {
4051 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
4052 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
4053 if (!mono_error_ok (&error))
4055 mono_array_setref (res, i, rm);
4059 g_ptr_array_free (method_array, TRUE);
4060 if (!mono_error_ok (&error))
4061 mono_set_pending_exception (mono_error_convert_to_exception (&error));
4065 ICALL_EXPORT MonoArray*
4066 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4069 MonoClass *startklass, *klass, *refklass;
4070 MonoArray *res = NULL;
4074 gpointer iter = NULL;
4075 MonoPtrArray tmp_array;
4078 domain = ((MonoObject *)type)->vtable->domain;
4079 if (type->type->byref) {
4080 res = mono_array_new_cached (domain, mono_defaults.method_info_class, 0, &error);
4081 mono_error_set_pending_exception (&error);
4085 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
4088 klass = startklass = mono_class_from_mono_type (type->type);
4089 refklass = mono_class_from_mono_type (reftype->type);
4091 mono_class_setup_methods (klass);
4092 if (mono_class_has_failure (klass)) {
4093 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
4098 while ((method = mono_class_get_methods (klass, &iter))) {
4100 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
4102 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4103 if (bflags & BFLAGS_Public)
4106 if (bflags & BFLAGS_NonPublic)
4112 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4113 if (bflags & BFLAGS_Static)
4114 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4117 if (bflags & BFLAGS_Instance)
4123 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
4124 if (mono_error_set_pending_exception (&error))
4127 mono_ptr_array_append (tmp_array, member);
4130 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array), &error);
4131 if (mono_error_set_pending_exception (&error))
4134 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4135 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4138 mono_ptr_array_destroy (tmp_array);
4144 property_hash (gconstpointer data)
4146 MonoProperty *prop = (MonoProperty*)data;
4148 return g_str_hash (prop->name);
4152 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
4154 if (method1->is_inflated)
4155 method1 = ((MonoMethodInflated*) method1)->declaring;
4156 if (method2->is_inflated)
4157 method2 = ((MonoMethodInflated*) method2)->declaring;
4159 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4163 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4165 // Properties are hide-by-name-and-signature
4166 if (!g_str_equal (prop1->name, prop2->name))
4169 /* If we see a property in a generic method, we want to
4170 compare the generic signatures, not the inflated signatures
4171 because we might conflate two properties that were
4175 public T this[T t] { getter { return t; } } // method 1
4176 public U this[U u] { getter { return u; } } // method 2
4179 If we see int Foo<int,int>::Item[int] we need to know if
4180 the indexer came from method 1 or from method 2, and we
4181 shouldn't conflate them. (Bugzilla 36283)
4183 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
4186 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4193 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4198 return method_nonpublic (accessor, start_klass);
4201 ICALL_EXPORT MonoArray*
4202 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4206 MonoClass *startklass, *klass;
4212 gchar *propname = NULL;
4213 int (*compare_func) (const char *s1, const char *s2) = NULL;
4215 GHashTable *properties = NULL;
4216 MonoPtrArray tmp_array;
4218 mono_error_init (&error);
4220 domain = ((MonoObject *)type)->vtable->domain;
4221 if (type->type->byref) {
4222 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), 0, &error);
4223 mono_error_set_pending_exception (&error);
4227 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4229 klass = startklass = mono_class_from_mono_type (type->type);
4232 propname = mono_string_to_utf8 (name);
4233 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4236 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4238 mono_class_setup_methods (klass);
4239 mono_class_setup_vtable (klass);
4240 if (mono_class_has_failure (klass))
4244 while ((prop = mono_class_get_properties (klass, &iter))) {
4250 flags = method->flags;
4253 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4254 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4255 if (bflags & BFLAGS_Public)
4257 } else if (bflags & BFLAGS_NonPublic) {
4258 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4259 property_accessor_nonpublic(prop->set, startklass == klass)) {
4266 if (flags & METHOD_ATTRIBUTE_STATIC) {
4267 if (bflags & BFLAGS_Static)
4268 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4271 if (bflags & BFLAGS_Instance)
4280 if (compare_func (propname, prop->name))
4284 if (g_hash_table_lookup (properties, prop))
4287 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4290 mono_ptr_array_append (tmp_array, pr);
4292 g_hash_table_insert (properties, prop, prop);
4294 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4297 g_hash_table_destroy (properties);
4300 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array), &error);
4301 if (!is_ok (&error))
4303 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4304 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4306 mono_ptr_array_destroy (tmp_array);
4313 if (mono_class_has_failure (klass)) {
4314 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4319 g_hash_table_destroy (properties);
4322 mono_ptr_array_destroy (tmp_array);
4324 mono_error_set_pending_exception (&error);
4330 event_hash (gconstpointer data)
4332 MonoEvent *event = (MonoEvent*)data;
4334 return g_str_hash (event->name);
4338 event_equal (MonoEvent *event1, MonoEvent *event2)
4340 // Events are hide-by-name
4341 return g_str_equal (event1->name, event2->name);
4344 ICALL_EXPORT MonoArray*
4345 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4349 MonoClass *startklass, *klass;
4355 char *utf8_name = NULL;
4356 int (*compare_func) (const char *s1, const char *s2) = NULL;
4357 GHashTable *events = NULL;
4358 MonoPtrArray tmp_array;
4360 mono_error_init (&error);
4362 domain = mono_object_domain (type);
4363 if (type->type->byref) {
4364 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), 0, &error);
4365 mono_error_set_pending_exception (&error);
4369 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4371 klass = startklass = mono_class_from_mono_type (type->type);
4373 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4375 mono_class_setup_methods (klass);
4376 mono_class_setup_vtable (klass);
4377 if (mono_class_has_failure (klass))
4381 while ((event = mono_class_get_events (klass, &iter))) {
4383 method = event->add;
4385 method = event->remove;
4387 method = event->raise;
4389 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4390 if (bflags & BFLAGS_Public)
4392 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4393 if (bflags & BFLAGS_NonPublic)
4398 if (bflags & BFLAGS_NonPublic)
4404 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4405 if (bflags & BFLAGS_Static)
4406 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4409 if (bflags & BFLAGS_Instance)
4414 if (bflags & BFLAGS_Instance)
4420 if (utf8_name == NULL) {
4421 utf8_name = mono_string_to_utf8 (name);
4422 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4425 if (compare_func (event->name, utf8_name))
4429 if (g_hash_table_lookup (events, event))
4432 MonoReflectionEvent *ev_obj;
4433 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4436 mono_ptr_array_append (tmp_array, ev_obj);
4438 g_hash_table_insert (events, event, event);
4440 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4443 g_hash_table_destroy (events);
4445 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array), &error);
4446 if (!is_ok (&error))
4449 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4450 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4452 mono_ptr_array_destroy (tmp_array);
4454 if (utf8_name != NULL)
4460 if (mono_class_has_failure (klass)) {
4461 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4467 g_hash_table_destroy (events);
4468 if (utf8_name != NULL)
4471 mono_ptr_array_destroy (tmp_array);
4473 mono_error_set_pending_exception (&error);
4477 ICALL_EXPORT MonoArray*
4478 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4481 MonoReflectionType *rt;
4484 MonoArray *res = NULL;
4489 MonoPtrArray tmp_array;
4491 mono_error_init (&error);
4493 domain = ((MonoObject *)type)->vtable->domain;
4494 if (type->type->byref) {
4495 MonoArray *result = mono_array_new_cached (domain, mono_defaults.monotype_class, 0, &error);
4496 mono_error_set_pending_exception (&error);
4499 klass = mono_class_from_mono_type (type->type);
4502 * If a nested type is generic, return its generic type definition.
4503 * Note that this means that the return value is essentially the set
4504 * of nested types of the generic type definition of @klass.
4506 * A note in MSDN claims that a generic type definition can have
4507 * nested types that aren't generic. In any case, the container of that
4508 * nested type would be the generic type definition.
4510 if (klass->generic_class)
4511 klass = klass->generic_class->container_class;
4513 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4515 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4517 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4518 if (bflags & BFLAGS_Public)
4521 if (bflags & BFLAGS_NonPublic)
4529 str = mono_string_to_utf8 (name);
4530 mono_identifier_unescape_type_name_chars (str);
4533 if (strcmp (nested->name, str))
4537 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4538 if (!is_ok (&error))
4541 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4544 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array), &error);
4545 if (!is_ok (&error))
4548 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4549 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4552 mono_ptr_array_destroy (tmp_array);
4556 mono_error_set_pending_exception (&error);
4560 ICALL_EXPORT MonoReflectionType*
4561 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4564 MonoReflectionType *ret;
4566 MonoType *type = NULL;
4567 MonoTypeNameParse info;
4568 gboolean type_resolve;
4570 /* On MS.NET, this does not fire a TypeResolve event */
4571 type_resolve = TRUE;
4572 str = mono_string_to_utf8 (name);
4573 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4574 if (!mono_reflection_parse_type (str, &info)) {
4576 mono_reflection_free_type_info (&info);
4578 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4581 /*g_print ("failed parse\n");*/
4585 if (info.assembly.name) {
4587 mono_reflection_free_type_info (&info);
4589 /* 1.0 and 2.0 throw different exceptions */
4590 if (mono_defaults.generic_ilist_class)
4591 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4593 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4599 if (module != NULL) {
4600 if (module->image) {
4601 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4602 if (!is_ok (&error)) {
4604 mono_reflection_free_type_info (&info);
4605 mono_error_set_pending_exception (&error);
4612 if (assembly_is_dynamic (assembly->assembly)) {
4613 /* Enumerate all modules */
4614 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4618 if (abuilder->modules) {
4619 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4620 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4621 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4622 if (!is_ok (&error)) {
4624 mono_reflection_free_type_info (&info);
4625 mono_error_set_pending_exception (&error);
4633 if (!type && abuilder->loaded_modules) {
4634 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4635 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4636 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4637 if (!is_ok (&error)) {
4639 mono_reflection_free_type_info (&info);
4640 mono_error_set_pending_exception (&error);
4649 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4650 if (!is_ok (&error)) {
4652 mono_reflection_free_type_info (&info);
4653 mono_error_set_pending_exception (&error);
4658 mono_reflection_free_type_info (&info);
4660 MonoException *e = NULL;
4663 e = mono_get_exception_type_load (name, NULL);
4666 mono_set_pending_exception (e);
4670 if (type->type == MONO_TYPE_CLASS) {
4671 MonoClass *klass = mono_type_get_class (type);
4673 /* need to report exceptions ? */
4674 if (throwOnError && mono_class_has_failure (klass)) {
4675 /* report SecurityException (or others) that occured when loading the assembly */
4676 MonoException *exc = mono_class_get_exception_for_failure (klass);
4677 mono_set_pending_exception (exc);
4682 /* g_print ("got it\n"); */
4683 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4684 mono_error_set_pending_exception (&error);
4690 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4693 gchar *shadow_ini_file;
4696 /* Check for shadow-copied assembly */
4697 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4698 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4700 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4701 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4707 g_free (shadow_ini_file);
4708 if (content != NULL) {
4711 *filename = content;
4718 ICALL_EXPORT MonoString *
4719 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4721 MonoDomain *domain = mono_object_domain (assembly);
4722 MonoAssembly *mass = assembly->assembly;
4723 MonoString *res = NULL;
4728 if (g_path_is_absolute (mass->image->name)) {
4729 absolute = g_strdup (mass->image->name);
4730 dirname = g_path_get_dirname (absolute);
4732 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4733 dirname = g_strdup (mass->basedir);
4736 replace_shadow_path (domain, dirname, &absolute);
4741 for (i = strlen (absolute) - 1; i >= 0; i--)
4742 if (absolute [i] == '\\')
4747 uri = g_filename_to_uri (absolute, NULL, NULL);
4749 const char *prepend = "file://";
4751 if (*absolute == '/' && *(absolute + 1) == '/') {
4754 prepend = "file:///";
4757 uri = g_strconcat (prepend, absolute, NULL);
4761 res = mono_string_new (domain, uri);
4768 ICALL_EXPORT MonoBoolean
4769 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4771 MonoAssembly *mass = assembly->assembly;
4773 return mass->in_gac;
4776 ICALL_EXPORT MonoReflectionAssembly*
4777 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4782 MonoImageOpenStatus status;
4783 MonoReflectionAssembly* result = NULL;
4785 name = mono_string_to_utf8 (mname);
4786 res = mono_assembly_load_with_partial_name (name, &status);
4792 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4794 mono_error_set_pending_exception (&error);
4798 ICALL_EXPORT MonoString *
4799 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4801 MonoDomain *domain = mono_object_domain (assembly);
4804 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4809 ICALL_EXPORT MonoBoolean
4810 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4812 return assembly->assembly->ref_only;
4815 ICALL_EXPORT MonoString *
4816 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4818 MonoDomain *domain = mono_object_domain (assembly);
4820 return mono_string_new (domain, assembly->assembly->image->version);
4823 ICALL_EXPORT MonoReflectionMethod*
4824 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4827 MonoReflectionMethod *res = NULL;
4830 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4834 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4835 if (!mono_error_ok (&error))
4838 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4841 if (!mono_error_ok (&error))
4842 mono_error_set_pending_exception (&error);
4846 ICALL_EXPORT MonoReflectionModule*
4847 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4850 MonoReflectionModule *result = NULL;
4851 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4852 if (!mono_error_ok (&error))
4853 mono_error_set_pending_exception (&error);
4857 ICALL_EXPORT MonoArray*
4858 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4861 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4862 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4863 if (mono_error_set_pending_exception (&error))
4868 for (i = 0; i < table->rows; ++i) {
4869 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4870 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4876 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4878 static MonoMethod *create_version = NULL;
4882 mono_error_init (error);
4885 if (!create_version) {
4886 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4887 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4888 g_assert (create_version);
4889 mono_method_desc_free (desc);
4895 args [3] = &revision;
4896 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4897 return_val_if_nok (error, NULL);
4899 mono_runtime_invoke_checked (create_version, result, args, error);
4900 return_val_if_nok (error, NULL);
4905 ICALL_EXPORT MonoArray*
4906 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4910 MonoDomain *domain = mono_object_domain (assembly);
4912 static MonoMethod *create_culture = NULL;
4913 MonoImage *image = assembly->assembly->image;
4917 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4920 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4921 if (mono_error_set_pending_exception (&error))
4925 if (count > 0 && !create_culture) {
4926 MonoMethodDesc *desc = mono_method_desc_new (
4927 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4928 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4929 g_assert (create_culture);
4930 mono_method_desc_free (desc);
4933 for (i = 0; i < count; i++) {
4934 MonoObject *version;
4935 MonoReflectionAssemblyName *aname;
4936 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4938 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4940 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4941 domain, mono_class_get_assembly_name_class (), &error);
4942 if (mono_error_set_pending_exception (&error))
4945 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4947 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4948 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4949 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4950 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4951 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4952 aname->versioncompat = 1; /* SameMachine (default) */
4953 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4955 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4956 if (mono_error_set_pending_exception (&error))
4959 MONO_OBJECT_SETREF (aname, version, version);
4961 if (create_culture) {
4963 MonoBoolean assembly_ref = 1;
4964 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4965 args [1] = &assembly_ref;
4967 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4968 if (mono_error_set_pending_exception (&error))
4971 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4974 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4975 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4976 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4978 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4979 /* public key token isn't copied - the class library will
4980 automatically generate it from the public key if required */
4981 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4982 if (mono_error_set_pending_exception (&error))
4985 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4986 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4988 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4989 if (mono_error_set_pending_exception (&error))
4992 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4993 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
4996 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
4997 if (mono_error_set_pending_exception (&error))
5000 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5003 /* note: this function doesn't return the codebase on purpose (i.e. it can
5004 be used under partial trust as path information isn't present). */
5006 mono_array_setref (result, i, aname);
5011 /* move this in some file in mono/util/ */
5013 g_concat_dir_and_file (const char *dir, const char *file)
5015 g_return_val_if_fail (dir != NULL, NULL);
5016 g_return_val_if_fail (file != NULL, NULL);
5019 * If the directory name doesn't have a / on the end, we need
5020 * to add one so we get a proper path to the file
5022 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
5023 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
5025 return g_strconcat (dir, file, NULL);
5029 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
5032 char *n = mono_string_to_utf8 (name);
5033 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5035 guint32 cols [MONO_MANIFEST_SIZE];
5036 guint32 impl, file_idx;
5040 for (i = 0; i < table->rows; ++i) {
5041 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5042 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5043 if (strcmp (val, n) == 0)
5047 if (i == table->rows)
5050 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
5053 * this code should only be called after obtaining the
5054 * ResourceInfo and handling the other cases.
5056 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
5057 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
5059 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
5064 module = assembly->assembly->image;
5067 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
5068 if (mono_error_set_pending_exception (&error))
5070 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
5072 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
5075 ICALL_EXPORT gboolean
5076 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
5079 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5081 guint32 cols [MONO_MANIFEST_SIZE];
5082 guint32 file_cols [MONO_FILE_SIZE];
5086 n = mono_string_to_utf8 (name);
5087 for (i = 0; i < table->rows; ++i) {
5088 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5089 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5090 if (strcmp (val, n) == 0)
5094 if (i == table->rows)
5097 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
5098 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
5101 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
5102 case MONO_IMPLEMENTATION_FILE:
5103 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5104 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5105 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
5106 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
5107 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
5108 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
5111 info->location = RESOURCE_LOCATION_EMBEDDED;
5114 case MONO_IMPLEMENTATION_ASSEMBLYREF:
5115 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5116 mono_assembly_load_reference (assembly->assembly->image, i - 1);
5117 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
5118 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
5119 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
5121 mono_set_pending_exception (ex);
5124 MonoReflectionAssembly *assm_obj;
5125 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5127 mono_error_set_pending_exception (&error);
5130 MONO_OBJECT_SETREF (info, assembly, assm_obj);
5132 /* Obtain info recursively */
5133 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5134 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5137 case MONO_IMPLEMENTATION_EXP_TYPE:
5138 g_assert_not_reached ();
5146 ICALL_EXPORT MonoObject*
5147 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
5150 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5151 MonoArray *result = NULL;
5156 /* check hash if needed */
5158 n = mono_string_to_utf8 (name);
5159 for (i = 0; i < table->rows; ++i) {
5160 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5161 if (strcmp (val, n) == 0) {
5164 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5165 fn = mono_string_new (mono_object_domain (assembly), n);
5167 return (MonoObject*)fn;
5175 for (i = 0; i < table->rows; ++i) {
5176 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5180 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
5181 if (mono_error_set_pending_exception (&error))
5186 for (i = 0; i < table->rows; ++i) {
5187 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5188 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5189 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5190 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5195 return (MonoObject*)result;
5198 ICALL_EXPORT MonoArray*
5199 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5202 MonoDomain *domain = mono_domain_get();
5205 int i, j, file_count = 0;
5206 MonoImage **modules;
5207 guint32 module_count, real_module_count;
5208 MonoTableInfo *table;
5209 guint32 cols [MONO_FILE_SIZE];
5210 MonoImage *image = assembly->assembly->image;
5212 g_assert (image != NULL);
5213 g_assert (!assembly_is_dynamic (assembly->assembly));
5215 table = &image->tables [MONO_TABLE_FILE];
5216 file_count = table->rows;
5218 modules = image->modules;
5219 module_count = image->module_count;
5221 real_module_count = 0;
5222 for (i = 0; i < module_count; ++i)
5224 real_module_count ++;
5226 klass = mono_class_get_module_class ();
5227 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5228 if (mono_error_set_pending_exception (&error))
5231 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5232 if (mono_error_set_pending_exception (&error))
5235 mono_array_setref (res, 0, image_obj);
5237 for (i = 0; i < module_count; ++i)
5239 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5240 if (mono_error_set_pending_exception (&error))
5242 mono_array_setref (res, j, rm);
5246 for (i = 0; i < file_count; ++i, ++j) {
5247 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5248 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5249 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5250 if (mono_error_set_pending_exception (&error))
5252 mono_array_setref (res, j, rm);
5255 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5257 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5258 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5261 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5262 if (mono_error_set_pending_exception (&error))
5264 mono_array_setref (res, j, rm);
5271 ICALL_EXPORT MonoReflectionMethod*
5272 ves_icall_GetCurrentMethod (void)
5274 MonoReflectionMethod *res = NULL;
5277 MonoMethod *m = mono_method_get_last_managed ();
5280 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5284 while (m->is_inflated)
5285 m = ((MonoMethodInflated*)m)->declaring;
5287 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5288 mono_error_set_pending_exception (&error);
5294 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5297 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5300 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5301 //method is inflated, we should inflate it on the other class
5302 MonoGenericContext ctx;
5303 ctx.method_inst = inflated->context.method_inst;
5304 ctx.class_inst = inflated->context.class_inst;
5305 if (klass->generic_class)
5306 ctx.class_inst = klass->generic_class->context.class_inst;
5307 else if (klass->generic_container)
5308 ctx.class_inst = klass->generic_container->context.class_inst;
5309 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5310 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5314 mono_class_setup_methods (method->klass);
5315 if (mono_class_has_failure (method->klass))
5317 for (i = 0; i < method->klass->method.count; ++i) {
5318 if (method->klass->methods [i] == method) {
5323 mono_class_setup_methods (klass);
5324 if (mono_class_has_failure (klass))
5326 g_assert (offset >= 0 && offset < klass->method.count);
5327 return klass->methods [offset];
5330 ICALL_EXPORT MonoReflectionMethod*
5331 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5333 MonoReflectionMethod *res = NULL;
5337 klass = mono_class_from_mono_type (type);
5338 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5340 if (method->klass != klass) {
5341 method = mono_method_get_equivalent_method (method, klass);
5346 klass = method->klass;
5347 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5348 mono_error_set_pending_exception (&error);
5352 ICALL_EXPORT MonoReflectionMethodBody*
5353 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5356 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5357 mono_error_set_pending_exception (&error);
5361 ICALL_EXPORT MonoReflectionAssembly*
5362 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5365 MonoReflectionAssembly *result;
5366 MonoMethod *dest = NULL;
5368 mono_stack_walk_no_il (get_executing, &dest);
5370 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5372 mono_error_set_pending_exception (&error);
5377 ICALL_EXPORT MonoReflectionAssembly*
5378 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5381 MonoReflectionAssembly *result;
5382 MonoDomain* domain = mono_domain_get ();
5384 if (!domain->entry_assembly)
5387 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5389 mono_error_set_pending_exception (&error);
5393 ICALL_EXPORT MonoReflectionAssembly*
5394 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5399 MonoReflectionAssembly *result;
5402 mono_stack_walk_no_il (get_executing, &dest);
5404 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5408 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5411 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5413 mono_error_set_pending_exception (&error);
5417 ICALL_EXPORT MonoString *
5418 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5419 gboolean assembly_qualified)
5421 MonoDomain *domain = mono_object_domain (object);
5422 MonoTypeNameFormat format;
5427 format = assembly_qualified ?
5428 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5429 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5431 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5433 name = mono_type_get_name_full (object->type, format);
5437 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5442 res = mono_string_new (domain, name);
5449 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5452 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5454 mono_class_init_checked (klass, &error);
5455 mono_error_set_pending_exception (&error);
5456 return mono_security_core_clr_class_level (klass);
5460 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5462 MonoClassField *field = rfield->field;
5463 return mono_security_core_clr_field_level (field, TRUE);
5467 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5469 MonoMethod *method = rfield->method;
5470 return mono_security_core_clr_method_level (method, TRUE);
5474 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)
5476 static MonoMethod *create_culture = NULL;
5480 const char *pkey_ptr;
5482 MonoBoolean assembly_ref = 0;
5484 mono_error_init (error);
5486 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5487 aname->major = name->major;
5488 aname->minor = name->minor;
5489 aname->build = name->build;
5490 aname->flags = name->flags;
5491 aname->revision = name->revision;
5492 aname->hashalg = name->hash_alg;
5493 aname->versioncompat = 1; /* SameMachine (default) */
5494 aname->processor_architecture = name->arch;
5496 if (by_default_version) {
5497 MonoObject *version;
5499 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5500 return_if_nok (error);
5502 MONO_OBJECT_SETREF (aname, version, version);
5506 if (absolute != NULL && *absolute != '\0') {
5507 const gchar *prepend = "file://";
5510 codebase = g_strdup (absolute);
5515 for (i = strlen (codebase) - 1; i >= 0; i--)
5516 if (codebase [i] == '\\')
5519 if (*codebase == '/' && *(codebase + 1) == '/') {
5522 prepend = "file:///";
5526 result = g_strconcat (prepend, codebase, NULL);
5532 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5536 if (!create_culture) {
5537 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5538 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5539 g_assert (create_culture);
5540 mono_method_desc_free (desc);
5543 if (name->culture) {
5544 args [0] = mono_string_new (domain, name->culture);
5545 args [1] = &assembly_ref;
5547 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5548 return_if_nok (error);
5550 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5553 if (name->public_key) {
5554 pkey_ptr = (char*)name->public_key;
5555 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5557 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5558 return_if_nok (error);
5559 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5560 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5561 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5562 } else if (default_publickey) {
5563 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5564 return_if_nok (error);
5565 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5566 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5569 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5570 if (name->public_key_token [0]) {
5574 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5575 return_if_nok (error);
5577 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5578 p = mono_array_addr (keyToken, char, 0);
5580 for (i = 0, j = 0; i < 8; i++) {
5581 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5582 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5585 } else if (default_token) {
5586 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5587 return_if_nok (error);
5588 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5592 ICALL_EXPORT MonoString *
5593 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5595 MonoDomain *domain = mono_object_domain (assembly);
5596 MonoAssembly *mass = assembly->assembly;
5600 name = mono_stringify_assembly_name (&mass->aname);
5601 res = mono_string_new (domain, name);
5608 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5612 MonoAssembly *mass = assembly->assembly;
5614 if (g_path_is_absolute (mass->image->name)) {
5615 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5616 mono_error_set_pending_exception (&error);
5619 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5621 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5622 mono_error_set_pending_exception (&error);
5628 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5632 MonoImageOpenStatus status = MONO_IMAGE_OK;
5635 MonoAssemblyName name;
5638 filename = mono_string_to_utf8 (fname);
5640 dirname = g_path_get_dirname (filename);
5641 replace_shadow_path (mono_domain_get (), dirname, &filename);
5644 image = mono_image_open (filename, &status);
5650 if (status == MONO_IMAGE_IMAGE_INVALID)
5651 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5653 exc = mono_get_exception_file_not_found2 (NULL, fname);
5654 mono_set_pending_exception (exc);
5658 res = mono_assembly_fill_assembly_name (image, &name);
5660 mono_image_close (image);
5662 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5666 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5667 mono_error_set_pending_exception (&error);
5669 mono_image_close (image);
5673 ICALL_EXPORT MonoBoolean
5674 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5675 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5677 MonoBoolean result = FALSE;
5678 MonoDeclSecurityEntry entry;
5680 /* SecurityAction.RequestMinimum */
5681 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5682 *minimum = entry.blob;
5683 *minLength = entry.size;
5686 /* SecurityAction.RequestOptional */
5687 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5688 *optional = entry.blob;
5689 *optLength = entry.size;
5692 /* SecurityAction.RequestRefuse */
5693 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5694 *refused = entry.blob;
5695 *refLength = entry.size;
5703 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5705 guint32 attrs, visibility;
5707 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5708 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5709 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5712 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5718 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5720 MonoReflectionType *rt;
5723 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5726 mono_error_init (error);
5728 /* we start the count from 1 because we skip the special type <Module> */
5731 for (i = 1; i < tdef->rows; ++i) {
5732 if (mono_module_type_is_visible (tdef, image, i + 1))
5736 count = tdef->rows - 1;
5738 res = mono_array_new_checked (domain, mono_defaults.monotype_class, count, error);
5739 return_val_if_nok (error, NULL);
5740 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5741 return_val_if_nok (error, NULL);
5743 for (i = 1; i < tdef->rows; ++i) {
5744 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5745 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5748 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5749 return_val_if_nok (error, NULL);
5751 mono_array_setref (res, count, rt);
5753 MonoException *ex = mono_error_convert_to_exception (error);
5754 mono_array_setref (*exceptions, count, ex);
5763 ICALL_EXPORT MonoArray*
5764 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5767 MonoArray *res = NULL;
5768 MonoArray *exceptions = NULL;
5769 MonoImage *image = NULL;
5770 MonoTableInfo *table = NULL;
5773 int i, len, ex_count;
5775 domain = mono_object_domain (assembly);
5777 g_assert (!assembly_is_dynamic (assembly->assembly));
5778 image = assembly->assembly->image;
5779 table = &image->tables [MONO_TABLE_FILE];
5780 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5781 if (mono_error_set_pending_exception (&error))
5784 /* Append data from all modules in the assembly */
5785 for (i = 0; i < table->rows; ++i) {
5786 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5787 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5792 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5793 if (mono_error_set_pending_exception (&error))
5797 /* Append the new types to the end of the array */
5798 if (mono_array_length (res2) > 0) {
5800 MonoArray *res3, *ex3;
5802 len1 = mono_array_length (res);
5803 len2 = mono_array_length (res2);
5805 res3 = mono_array_new_checked (domain, mono_defaults.monotype_class, len1 + len2, &error);
5806 if (mono_error_set_pending_exception (&error))
5808 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5809 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5812 ex3 = mono_array_new_checked (domain, mono_defaults.monotype_class, len1 + len2, &error);
5813 if (mono_error_set_pending_exception (&error))
5815 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5816 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5823 /* the ReflectionTypeLoadException must have all the types (Types property),
5824 * NULL replacing types which throws an exception. The LoaderException must
5825 * contain all exceptions for NULL items.
5828 len = mono_array_length (res);
5831 for (i = 0; i < len; i++) {
5832 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5836 klass = mono_type_get_class (t->type);
5837 if ((klass != NULL) && mono_class_has_failure (klass)) {
5838 /* keep the class in the list */
5839 list = g_list_append (list, klass);
5840 /* and replace Type with NULL */
5841 mono_array_setref (res, i, NULL);
5848 if (list || ex_count) {
5850 MonoException *exc = NULL;
5851 MonoArray *exl = NULL;
5852 int j, length = g_list_length (list) + ex_count;
5854 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5855 if (mono_error_set_pending_exception (&error)) {
5859 /* Types for which mono_class_get_checked () succeeded */
5860 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5861 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5862 mono_array_setref (exl, i, exc);
5864 /* Types for which it don't */
5865 for (j = 0; j < mono_array_length (exceptions); ++j) {
5866 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5868 g_assert (i < length);
5869 mono_array_setref (exl, i, exc);
5876 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5877 if (!is_ok (&error)) {
5878 mono_error_set_pending_exception (&error);
5881 mono_set_pending_exception (exc);
5888 ICALL_EXPORT gboolean
5889 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5892 MonoAssemblyName aname;
5893 MonoDomain *domain = mono_object_domain (name);
5895 gboolean is_version_defined;
5896 gboolean is_token_defined;
5898 aname.public_key = NULL;
5899 val = mono_string_to_utf8 (assname);
5900 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5901 g_free ((guint8*) aname.public_key);
5906 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5907 mono_error_set_pending_exception (&error);
5909 mono_assembly_name_free (&aname);
5910 g_free ((guint8*) aname.public_key);
5916 ICALL_EXPORT MonoReflectionType*
5917 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5920 MonoReflectionType *ret;
5921 MonoDomain *domain = mono_object_domain (module);
5924 g_assert (module->image);
5926 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5927 /* These images do not have a global type */
5930 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5931 if (!mono_error_ok (&error)) {
5932 mono_error_set_pending_exception (&error);
5936 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5937 if (!mono_error_ok (&error)) {
5938 mono_error_set_pending_exception (&error);
5946 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5948 /*if (module->image)
5949 mono_image_close (module->image);*/
5952 ICALL_EXPORT MonoString*
5953 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5955 MonoDomain *domain = mono_object_domain (module);
5957 g_assert (module->image);
5958 return mono_string_new (domain, module->image->guid);
5961 ICALL_EXPORT gpointer
5962 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5965 if (module->image && module->image->is_module_handle)
5966 return module->image->raw_data;
5969 return (gpointer) (-1);
5973 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5975 if (image_is_dynamic (image)) {
5976 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5977 *pe_kind = dyn->pe_kind;
5978 *machine = dyn->machine;
5981 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5982 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5987 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5989 return (image->md_version_major << 16) | (image->md_version_minor);
5992 ICALL_EXPORT MonoArray*
5993 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5996 MonoArray *exceptions;
5999 if (!module->image) {
6000 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.monotype_class, 0, &error);
6001 mono_error_set_pending_exception (&error);
6006 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
6007 if (mono_error_set_pending_exception (&error))
6010 for (i = 0; i < mono_array_length (exceptions); ++i) {
6011 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
6013 mono_set_pending_exception (ex);
6022 mono_memberref_is_method (MonoImage *image, guint32 token)
6024 if (!image_is_dynamic (image)) {
6025 guint32 cols [MONO_MEMBERREF_SIZE];
6027 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
6028 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
6029 mono_metadata_decode_blob_size (sig, &sig);
6030 return (*sig != 0x6);
6033 MonoClass *handle_class;
6035 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
6036 mono_error_cleanup (&error); /* just probing, ignore error */
6040 return mono_defaults.methodhandle_class == handle_class;
6045 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
6048 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
6049 mono_array_addr (type_args, MonoType*, 0));
6051 context->class_inst = NULL;
6053 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
6054 mono_array_addr (method_args, MonoType*, 0));
6056 context->method_inst = NULL;
6059 ICALL_EXPORT MonoType*
6060 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6063 int table = mono_metadata_token_table (token);
6064 int index = mono_metadata_token_index (token);
6065 MonoGenericContext context;
6068 *resolve_error = ResolveTokenError_Other;
6070 /* Validate token */
6071 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
6072 (table != MONO_TABLE_TYPESPEC)) {
6073 *resolve_error = ResolveTokenError_BadTable;
6077 if (image_is_dynamic (image)) {
6078 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
6079 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6080 mono_error_cleanup (&error);
6081 return klass ? &klass->byval_arg : NULL;
6084 init_generic_context_from_args (&context, type_args, method_args);
6085 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6086 mono_error_cleanup (&error);
6087 return klass ? &klass->byval_arg : NULL;
6090 if ((index <= 0) || (index > image->tables [table].rows)) {
6091 *resolve_error = ResolveTokenError_OutOfRange;
6095 init_generic_context_from_args (&context, type_args, method_args);
6096 klass = mono_class_get_checked (image, token, &error);
6098 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
6099 if (!mono_error_ok (&error)) {
6100 mono_error_set_pending_exception (&error);
6105 return &klass->byval_arg;
6110 ICALL_EXPORT MonoMethod*
6111 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6114 int table = mono_metadata_token_table (token);
6115 int index = mono_metadata_token_index (token);
6116 MonoGenericContext context;
6119 *resolve_error = ResolveTokenError_Other;
6121 /* Validate token */
6122 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
6123 (table != MONO_TABLE_MEMBERREF)) {
6124 *resolve_error = ResolveTokenError_BadTable;
6128 if (image_is_dynamic (image)) {
6129 if (table == MONO_TABLE_METHOD) {
6130 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6131 mono_error_cleanup (&error);
6135 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
6136 *resolve_error = ResolveTokenError_BadTable;
6140 init_generic_context_from_args (&context, type_args, method_args);
6141 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6142 mono_error_cleanup (&error);
6146 if ((index <= 0) || (index > image->tables [table].rows)) {
6147 *resolve_error = ResolveTokenError_OutOfRange;
6150 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6151 *resolve_error = ResolveTokenError_BadTable;
6155 init_generic_context_from_args (&context, type_args, method_args);
6156 method = mono_get_method_checked (image, token, NULL, &context, &error);
6157 mono_error_set_pending_exception (&error);
6162 ICALL_EXPORT MonoString*
6163 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6166 int index = mono_metadata_token_index (token);
6168 *resolve_error = ResolveTokenError_Other;
6170 /* Validate token */
6171 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6172 *resolve_error = ResolveTokenError_BadTable;
6176 if (image_is_dynamic (image)) {
6177 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6178 mono_error_cleanup (&error);
6182 if ((index <= 0) || (index >= image->heap_us.size)) {
6183 *resolve_error = ResolveTokenError_OutOfRange;
6187 /* FIXME: What to do if the index points into the middle of a string ? */
6189 return mono_ldstr (mono_domain_get (), image, index);
6192 ICALL_EXPORT MonoClassField*
6193 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6197 int table = mono_metadata_token_table (token);
6198 int index = mono_metadata_token_index (token);
6199 MonoGenericContext context;
6200 MonoClassField *field;
6202 *resolve_error = ResolveTokenError_Other;
6204 /* Validate token */
6205 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6206 *resolve_error = ResolveTokenError_BadTable;
6210 if (image_is_dynamic (image)) {
6211 if (table == MONO_TABLE_FIELD) {
6212 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6213 mono_error_cleanup (&error);
6217 if (mono_memberref_is_method (image, token)) {
6218 *resolve_error = ResolveTokenError_BadTable;
6222 init_generic_context_from_args (&context, type_args, method_args);
6223 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6224 mono_error_cleanup (&error);
6228 if ((index <= 0) || (index > image->tables [table].rows)) {
6229 *resolve_error = ResolveTokenError_OutOfRange;
6232 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6233 *resolve_error = ResolveTokenError_BadTable;
6237 init_generic_context_from_args (&context, type_args, method_args);
6238 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6239 mono_error_set_pending_exception (&error);
6245 ICALL_EXPORT MonoObject*
6246 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6250 int table = mono_metadata_token_table (token);
6252 *error = ResolveTokenError_Other;
6255 case MONO_TABLE_TYPEDEF:
6256 case MONO_TABLE_TYPEREF:
6257 case MONO_TABLE_TYPESPEC: {
6258 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6260 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6261 mono_error_set_pending_exception (&merror);
6268 case MONO_TABLE_METHOD:
6269 case MONO_TABLE_METHODSPEC: {
6270 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6272 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6273 mono_error_set_pending_exception (&merror);
6279 case MONO_TABLE_FIELD: {
6280 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6282 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6283 mono_error_set_pending_exception (&merror);
6289 case MONO_TABLE_MEMBERREF:
6290 if (mono_memberref_is_method (image, token)) {
6291 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6293 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6294 mono_error_set_pending_exception (&merror);
6301 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6303 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6304 mono_error_set_pending_exception (&merror);
6313 *error = ResolveTokenError_BadTable;
6319 ICALL_EXPORT MonoArray*
6320 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6323 int table = mono_metadata_token_table (token);
6324 int idx = mono_metadata_token_index (token);
6325 MonoTableInfo *tables = image->tables;
6330 *resolve_error = ResolveTokenError_OutOfRange;
6332 /* FIXME: Support other tables ? */
6333 if (table != MONO_TABLE_STANDALONESIG)
6336 if (image_is_dynamic (image))
6339 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6342 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6344 ptr = mono_metadata_blob_heap (image, sig);
6345 len = mono_metadata_decode_blob_size (ptr, &ptr);
6347 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6348 if (mono_error_set_pending_exception (&error))
6350 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6354 ICALL_EXPORT MonoReflectionType*
6355 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6358 MonoReflectionType *ret;
6360 int isbyref = 0, rank;
6361 char *str = mono_string_to_utf8 (smodifiers);
6364 klass = mono_class_from_mono_type (tb->type.type);
6366 /* logic taken from mono_reflection_parse_type(): keep in sync */
6370 if (isbyref) { /* only one level allowed by the spec */
6379 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6380 mono_error_set_pending_exception (&error);
6384 klass = mono_ptr_class_get (&klass->byval_arg);
6385 mono_class_init (klass);
6396 else if (*p != '*') { /* '*' means unknown lower bound */
6407 klass = mono_array_class_get (klass, rank);
6408 mono_class_init (klass);
6417 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6418 mono_error_set_pending_exception (&error);
6423 ICALL_EXPORT MonoBoolean
6424 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6430 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6436 check_for_invalid_type (MonoClass *klass, MonoError *error)
6441 mono_error_init (error);
6443 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6446 name = mono_type_get_full_name (klass);
6447 str = mono_string_new (mono_domain_get (), name);
6449 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6452 ICALL_EXPORT MonoReflectionType *
6453 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6456 MonoReflectionType *ret;
6457 MonoClass *klass, *aklass;
6459 klass = mono_class_from_mono_type (type->type);
6460 check_for_invalid_type (klass, &error);
6461 mono_error_set_pending_exception (&error);
6463 if (rank == 0) //single dimentional array
6464 aklass = mono_array_class_get (klass, 1);
6466 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6468 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6469 mono_error_set_pending_exception (&error);
6474 ICALL_EXPORT MonoReflectionType *
6475 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6478 MonoReflectionType *ret;
6481 klass = mono_class_from_mono_type (type->type);
6482 mono_class_init_checked (klass, &error);
6483 if (mono_error_set_pending_exception (&error))
6486 check_for_invalid_type (klass, &error);
6487 if (mono_error_set_pending_exception (&error))
6490 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6491 mono_error_set_pending_exception (&error);
6496 ICALL_EXPORT MonoReflectionType *
6497 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6500 MonoReflectionType *ret;
6501 MonoClass *klass, *pklass;
6503 klass = mono_class_from_mono_type (type->type);
6504 mono_class_init_checked (klass, &error);
6505 if (mono_error_set_pending_exception (&error))
6507 check_for_invalid_type (klass, &error);
6508 if (mono_error_set_pending_exception (&error))
6511 pklass = mono_ptr_class_get (type->type);
6513 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6514 mono_error_set_pending_exception (&error);
6519 ICALL_EXPORT MonoObject *
6520 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6521 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6524 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6525 MonoObject *delegate;
6527 MonoMethod *method = info->method;
6529 mono_class_init_checked (delegate_class, &error);
6530 if (mono_error_set_pending_exception (&error))
6533 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6534 /* FIXME improve this exception message */
6535 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6537 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6538 mono_error_set_pending_exception (&error);
6542 if (mono_security_core_clr_enabled ()) {
6543 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6544 if (throwOnBindFailure)
6545 mono_error_set_pending_exception (&error);
6547 mono_error_cleanup (&error);
6552 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6553 if (mono_error_set_pending_exception (&error))
6556 if (method_is_dynamic (method)) {
6557 /* Creating a trampoline would leak memory */
6558 func = mono_compile_method (method);
6560 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6561 method = mono_object_get_virtual_method (target, method);
6562 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6563 if (mono_error_set_pending_exception (&error))
6565 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6568 mono_delegate_ctor_with_method (delegate, target, func, method);
6573 ICALL_EXPORT MonoMulticastDelegate *
6574 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6577 MonoMulticastDelegate *ret;
6579 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6581 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6582 if (mono_error_set_pending_exception (&error))
6585 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6590 ICALL_EXPORT MonoReflectionMethod*
6591 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6593 MonoReflectionMethod *ret = NULL;
6595 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6596 mono_error_set_pending_exception (&error);
6602 static inline gint32
6603 mono_array_get_byte_length (MonoArray *array)
6609 klass = array->obj.vtable->klass;
6611 if (array->bounds == NULL)
6612 length = array->max_length;
6615 for (i = 0; i < klass->rank; ++ i)
6616 length *= array->bounds [i].length;
6619 switch (klass->element_class->byval_arg.type) {
6622 case MONO_TYPE_BOOLEAN:
6626 case MONO_TYPE_CHAR:
6634 return length * sizeof (gpointer);
6645 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6647 return mono_array_get_byte_length (array);
6651 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6653 return mono_array_get (array, gint8, idx);
6657 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6659 mono_array_set (array, gint8, idx, value);
6662 ICALL_EXPORT MonoBoolean
6663 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6665 guint8 *src_buf, *dest_buf;
6668 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6672 g_assert (count >= 0);
6674 /* This is called directly from the class libraries without going through the managed wrapper */
6675 MONO_CHECK_ARG_NULL (src, FALSE);
6676 MONO_CHECK_ARG_NULL (dest, FALSE);
6678 /* watch out for integer overflow */
6679 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6682 src_buf = (guint8 *)src->vector + src_offset;
6683 dest_buf = (guint8 *)dest->vector + dest_offset;
6686 memcpy (dest_buf, src_buf, count);
6688 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6693 #ifndef DISABLE_REMOTING
6694 ICALL_EXPORT MonoObject *
6695 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6698 MonoDomain *domain = mono_object_domain (this_obj);
6700 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6701 MonoTransparentProxy *tp;
6705 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6706 if (mono_error_set_pending_exception (&error))
6709 tp = (MonoTransparentProxy*) res;
6711 MONO_OBJECT_SETREF (tp, rp, rp);
6712 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6713 klass = mono_class_from_mono_type (type);
6715 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6716 mono_class_setup_vtable (klass);
6717 if (mono_class_has_failure (klass)) {
6718 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6722 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6723 if (!is_ok (&error)) {
6724 mono_error_set_pending_exception (&error);
6727 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6728 if (!is_ok (&error)) {
6729 mono_error_set_pending_exception (&error);
6733 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6737 ICALL_EXPORT MonoReflectionType *
6738 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6741 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6742 mono_error_set_pending_exception (&error);
6748 /* System.Environment */
6751 ves_icall_System_Environment_get_UserName (void)
6753 /* using glib is more portable */
6754 return mono_string_new (mono_domain_get (), g_get_user_name ());
6758 ICALL_EXPORT MonoString *
6759 ves_icall_System_Environment_get_MachineName (void)
6761 #if defined (HOST_WIN32)
6766 len = MAX_COMPUTERNAME_LENGTH + 1;
6767 buf = g_new (gunichar2, len);
6770 if (GetComputerName (buf, (PDWORD) &len)) {
6772 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6773 mono_error_set_pending_exception (&error);
6778 #elif !defined(DISABLE_SOCKETS)
6782 #if defined _SC_HOST_NAME_MAX
6783 n = sysconf (_SC_HOST_NAME_MAX);
6787 buf = g_malloc (n+1);
6789 if (gethostname (buf, n) == 0){
6791 result = mono_string_new (mono_domain_get (), buf);
6798 return mono_string_new (mono_domain_get (), "mono");
6803 ves_icall_System_Environment_get_Platform (void)
6805 #if defined (TARGET_WIN32)
6808 #elif defined(__MACH__)
6811 // Notice that the value is hidden from user code, and only exposed
6812 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6813 // define and making assumptions based on Unix/128/4 values before there
6814 // was a MacOS define. Lots of code would assume that not-Unix meant
6815 // Windows, but in this case, it would be OSX.
6824 ICALL_EXPORT MonoString *
6825 ves_icall_System_Environment_get_NewLine (void)
6827 #if defined (HOST_WIN32)
6828 return mono_string_new (mono_domain_get (), "\r\n");
6830 return mono_string_new (mono_domain_get (), "\n");
6834 ICALL_EXPORT MonoBoolean
6835 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6837 #if SIZEOF_VOID_P == 8
6841 gboolean isWow64Process = FALSE;
6842 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6843 return (MonoBoolean)isWow64Process;
6845 #elif defined(HAVE_SYS_UTSNAME_H)
6846 struct utsname name;
6848 if (uname (&name) >= 0) {
6849 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6856 ICALL_EXPORT MonoString *
6857 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6865 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6866 value = g_getenv (utf8_name);
6873 return mono_string_new (mono_domain_get (), value);
6877 * There is no standard way to get at environ.
6880 #ifndef __MINGW32_VERSION
6881 #if defined(__APPLE__)
6882 #if defined (TARGET_OSX)
6883 /* Apple defines this in crt_externs.h but doesn't provide that header for
6884 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6885 * in fact exist on all implementations (so far)
6887 gchar ***_NSGetEnviron(void);
6888 #define environ (*_NSGetEnviron())
6890 static char *mono_environ[1] = { NULL };
6891 #define environ mono_environ
6892 #endif /* defined (TARGET_OSX) */
6900 ICALL_EXPORT MonoArray *
6901 ves_icall_System_Environment_GetCoomandLineArgs (void)
6904 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6905 mono_error_set_pending_exception (&error);
6909 ICALL_EXPORT MonoArray *
6910 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6922 env_strings = GetEnvironmentStrings();
6925 env_string = env_strings;
6926 while (*env_string != '\0') {
6927 /* weird case that MS seems to skip */
6928 if (*env_string != '=')
6930 while (*env_string != '\0')
6936 domain = mono_domain_get ();
6937 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6938 if (mono_error_set_pending_exception (&error))
6943 env_string = env_strings;
6944 while (*env_string != '\0') {
6945 /* weird case that MS seems to skip */
6946 if (*env_string != '=') {
6947 equal_str = wcschr(env_string, '=');
6948 g_assert(equal_str);
6950 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6951 if (mono_error_set_pending_exception (&error))
6954 mono_array_setref (names, n, str);
6957 while (*env_string != '\0')
6962 FreeEnvironmentStrings (env_strings);
6976 for (e = environ; *e != 0; ++ e)
6979 domain = mono_domain_get ();
6980 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6981 if (mono_error_set_pending_exception (&error))
6985 for (e = environ; *e != 0; ++ e) {
6986 parts = g_strsplit (*e, "=", 2);
6988 str = mono_string_new (domain, *parts);
6989 mono_array_setref (names, n, str);
7002 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
7004 #if !GLIB_CHECK_VERSION(2,4,0)
7005 #define g_setenv(a,b,c) setenv(a,b,c)
7006 #define g_unsetenv(a) unsetenv(a)
7010 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
7013 gunichar2 *utf16_name, *utf16_value;
7015 gchar *utf8_name, *utf8_value;
7020 utf16_name = mono_string_to_utf16 (name);
7021 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7022 SetEnvironmentVariable (utf16_name, NULL);
7023 g_free (utf16_name);
7027 utf16_value = mono_string_to_utf16 (value);
7029 SetEnvironmentVariable (utf16_name, utf16_value);
7031 g_free (utf16_name);
7032 g_free (utf16_value);
7034 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
7036 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7037 g_unsetenv (utf8_name);
7042 utf8_value = mono_string_to_utf8_checked (value, &error);
7043 if (!mono_error_ok (&error)) {
7045 mono_error_set_pending_exception (&error);
7048 g_setenv (utf8_name, utf8_value, TRUE);
7051 g_free (utf8_value);
7056 ves_icall_System_Environment_Exit (int result)
7058 mono_environment_exitcode_set (result);
7060 /* FIXME: There are some cleanup hangs that should be worked out, but
7061 * if the program is going to exit, everything will be cleaned up when
7062 * NaCl exits anyway.
7064 #ifndef __native_client__
7065 if (!mono_runtime_try_shutdown ())
7066 mono_thread_exit ();
7068 /* Suspend all managed threads since the runtime is going away */
7069 mono_thread_suspend_all_other_threads ();
7071 mono_runtime_quit ();
7074 /* we may need to do some cleanup here... */
7078 ICALL_EXPORT MonoString*
7079 ves_icall_System_Environment_GetGacPath (void)
7081 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
7084 ICALL_EXPORT MonoString*
7085 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
7087 #if defined (HOST_WIN32)
7088 #ifndef CSIDL_FLAG_CREATE
7089 #define CSIDL_FLAG_CREATE 0x8000
7092 WCHAR path [MAX_PATH];
7093 /* Create directory if no existing */
7094 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
7099 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
7100 mono_error_set_pending_exception (&error);
7104 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7106 return mono_string_new (mono_domain_get (), "");
7109 ICALL_EXPORT MonoArray *
7110 ves_icall_System_Environment_GetLogicalDrives (void)
7113 gunichar2 buf [256], *ptr, *dname;
7115 guint initial_size = 127, size = 128;
7118 MonoString *drivestr;
7119 MonoDomain *domain = mono_domain_get ();
7125 while (size > initial_size) {
7126 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
7127 if (size > initial_size) {
7130 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7131 initial_size = size;
7145 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7146 if (mono_error_set_pending_exception (&error))
7153 while (*u16) { u16++; len ++; }
7154 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7155 if (mono_error_set_pending_exception (&error))
7158 mono_array_setref (result, ndrives++, drivestr);
7169 ICALL_EXPORT MonoString *
7170 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7172 gunichar2 volume_name [MAX_PATH + 1];
7174 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7176 return mono_string_from_utf16 (volume_name);
7179 ICALL_EXPORT MonoString *
7180 ves_icall_System_Environment_InternalGetHome (void)
7182 return mono_string_new (mono_domain_get (), g_get_home_dir ());
7185 static const char *encodings [] = {
7187 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7188 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7189 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7191 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7192 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7193 "x_unicode_2_0_utf_7",
7195 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7196 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7198 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7201 "unicodefffe", "utf_16be",
7208 * Returns the internal codepage, if the value of "int_code_page" is
7209 * 1 at entry, and we can not compute a suitable code page number,
7210 * returns the code page as a string
7212 ICALL_EXPORT MonoString*
7213 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
7218 char *codepage = NULL;
7220 int want_name = *int_code_page;
7223 *int_code_page = -1;
7225 g_get_charset (&cset);
7226 c = codepage = strdup (cset);
7227 for (c = codepage; *c; c++){
7228 if (isascii (*c) && isalpha (*c))
7233 /* g_print ("charset: %s\n", cset); */
7235 /* handle some common aliases */
7238 for (i = 0; p != 0; ){
7241 p = encodings [++i];
7244 if (strcmp (p, codepage) == 0){
7245 *int_code_page = code;
7248 p = encodings [++i];
7251 if (strstr (codepage, "utf_8") != NULL)
7252 *int_code_page |= 0x10000000;
7255 if (want_name && *int_code_page == -1)
7256 return mono_string_new (mono_domain_get (), cset);
7261 ICALL_EXPORT MonoBoolean
7262 ves_icall_System_Environment_get_HasShutdownStarted (void)
7264 if (mono_runtime_is_shutting_down ())
7267 if (mono_domain_is_unloading (mono_domain_get ()))
7274 ves_icall_System_Environment_BroadcastSettingChange (void)
7277 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7283 ves_icall_System_Environment_get_TickCount (void)
7285 /* this will overflow after ~24 days */
7286 return (gint32) (mono_msec_boottime () & 0xffffffff);
7290 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7296 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
7297 MonoReflectionMethod *method,
7298 MonoArray *out_args)
7300 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
7303 #ifndef DISABLE_REMOTING
7304 ICALL_EXPORT MonoBoolean
7305 ves_icall_IsTransparentProxy (MonoObject *proxy)
7310 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7316 ICALL_EXPORT MonoReflectionMethod *
7317 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7318 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7320 MonoReflectionMethod *ret = NULL;
7325 MonoMethod **vtable;
7326 MonoMethod *res = NULL;
7328 MONO_CHECK_ARG_NULL (rtype, NULL);
7329 MONO_CHECK_ARG_NULL (rmethod, NULL);
7331 method = rmethod->method;
7332 klass = mono_class_from_mono_type (rtype->type);
7333 mono_class_init_checked (klass, &error);
7334 if (mono_error_set_pending_exception (&error))
7337 if (MONO_CLASS_IS_INTERFACE (klass))
7340 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7343 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7344 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7350 mono_class_setup_vtable (klass);
7351 vtable = klass->vtable;
7353 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7354 gboolean variance_used = FALSE;
7355 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7356 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7358 res = vtable [offs + method->slot];
7360 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7363 if (method->slot != -1)
7364 res = vtable [method->slot];
7370 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7371 mono_error_set_pending_exception (&error);
7376 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7382 klass = mono_class_from_mono_type (type->type);
7383 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7384 if (!is_ok (&error)) {
7385 mono_error_set_pending_exception (&error);
7389 mono_vtable_set_is_remote (vtable, enable);
7392 #else /* DISABLE_REMOTING */
7395 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7397 g_assert_not_reached ();
7402 ICALL_EXPORT MonoObject *
7403 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7410 domain = mono_object_domain (type);
7411 klass = mono_class_from_mono_type (type->type);
7412 mono_class_init_checked (klass, &error);
7413 if (mono_error_set_pending_exception (&error))
7416 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7417 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7421 if (klass->rank >= 1) {
7422 g_assert (klass->rank == 1);
7423 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7424 mono_error_set_pending_exception (&error);
7427 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7428 if (!is_ok (&error)) {
7429 mono_error_set_pending_exception (&error);
7432 /* Bypass remoting object creation check */
7433 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7434 mono_error_set_pending_exception (&error);
7440 ICALL_EXPORT MonoString *
7441 ves_icall_System_IO_get_temp_path (void)
7443 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7446 #ifndef PLATFORM_NO_DRIVEINFO
7447 ICALL_EXPORT MonoBoolean
7448 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7449 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7453 ULARGE_INTEGER wapi_free_bytes_avail;
7454 ULARGE_INTEGER wapi_total_number_of_bytes;
7455 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7457 *error = ERROR_SUCCESS;
7458 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7459 &wapi_total_number_of_free_bytes);
7462 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7463 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7464 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7466 *free_bytes_avail = 0;
7467 *total_number_of_bytes = 0;
7468 *total_number_of_free_bytes = 0;
7469 *error = GetLastError ();
7475 ICALL_EXPORT guint32
7476 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7478 return GetDriveType (mono_string_chars (root_path_name));
7482 ICALL_EXPORT gpointer
7483 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7485 return mono_compile_method (method);
7488 ICALL_EXPORT MonoString *
7489 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7494 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7496 #if defined (HOST_WIN32)
7497 /* Avoid mixing '/' and '\\' */
7500 for (i = strlen (path) - 1; i >= 0; i--)
7501 if (path [i] == '/')
7505 mcpath = mono_string_new (mono_domain_get (), path);
7512 get_bundled_app_config (void)
7514 const gchar *app_config;
7517 gchar *config_file_name, *config_file_path;
7518 gsize len, config_file_path_length, config_ext_length;
7521 domain = mono_domain_get ();
7522 file = domain->setup->configuration_file;
7523 if (!file || file->length == 0)
7526 // Retrieve config file and remove the extension
7527 config_file_name = mono_string_to_utf8 (file);
7528 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7529 if (!config_file_path)
7530 config_file_path = config_file_name;
7532 config_file_path_length = strlen (config_file_path);
7533 config_ext_length = strlen (".config");
7534 if (config_file_path_length <= config_ext_length)
7537 len = config_file_path_length - config_ext_length;
7538 module = (gchar *)g_malloc0 (len + 1);
7539 memcpy (module, config_file_path, len);
7540 // Get the config file from the module name
7541 app_config = mono_config_string_for_assembly_file (module);
7544 if (config_file_name != config_file_path)
7545 g_free (config_file_name);
7546 g_free (config_file_path);
7551 return mono_string_new (mono_domain_get (), app_config);
7555 get_bundled_machine_config (void)
7557 const gchar *machine_config;
7559 machine_config = mono_get_machine_config ();
7561 if (!machine_config)
7564 return mono_string_new (mono_domain_get (), machine_config);
7567 ICALL_EXPORT MonoString *
7568 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7573 path = g_path_get_dirname (mono_get_config_dir ());
7575 #if defined (HOST_WIN32)
7576 /* Avoid mixing '/' and '\\' */
7579 for (i = strlen (path) - 1; i >= 0; i--)
7580 if (path [i] == '/')
7584 ipath = mono_string_new (mono_domain_get (), path);
7590 ICALL_EXPORT gboolean
7591 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7593 MonoPEResourceDataEntry *entry;
7596 if (!assembly || !result || !size)
7601 image = assembly->assembly->image;
7602 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7606 *result = mono_image_rva_map (image, entry->rde_data_offset);
7611 *size = entry->rde_size;
7616 ICALL_EXPORT MonoBoolean
7617 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7619 return mono_is_debugger_attached ();
7622 ICALL_EXPORT MonoBoolean
7623 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7625 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7626 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7632 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7634 if (mono_get_runtime_callbacks ()->debug_log)
7635 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7639 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7641 #if defined (HOST_WIN32)
7642 OutputDebugString (mono_string_chars (message));
7644 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7648 /* Only used for value types */
7649 ICALL_EXPORT MonoObject *
7650 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7657 domain = mono_object_domain (type);
7658 klass = mono_class_from_mono_type (type->type);
7659 mono_class_init_checked (klass, &error);
7660 if (mono_error_set_pending_exception (&error))
7663 if (mono_class_is_nullable (klass))
7664 /* No arguments -> null */
7667 result = mono_object_new_checked (domain, klass, &error);
7668 mono_error_set_pending_exception (&error);
7672 ICALL_EXPORT MonoReflectionMethod *
7673 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7675 MonoReflectionMethod *ret = NULL;
7678 MonoClass *klass, *parent;
7679 MonoGenericContext *generic_inst = NULL;
7680 MonoMethod *method = m->method;
7681 MonoMethod *result = NULL;
7684 if (method->klass == NULL)
7687 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7688 MONO_CLASS_IS_INTERFACE (method->klass) ||
7689 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7692 slot = mono_method_get_vtable_slot (method);
7696 klass = method->klass;
7697 if (klass->generic_class) {
7698 generic_inst = mono_class_get_context (klass);
7699 klass = klass->generic_class->container_class;
7703 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7704 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7705 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7706 or klass is the generic container class and generic_inst is the instantiation.
7708 when we go to the parent, if the parent is an open constructed type, we need to
7709 replace the type parameters by the definitions from the generic_inst, and then take it
7710 apart again into the klass and the generic_inst.
7712 For cases like this:
7713 class C<T> : B<T, int> {
7714 public override void Foo () { ... }
7716 class B<U,V> : A<HashMap<U,V>> {
7717 public override void Foo () { ... }
7720 public virtual void Foo () { ... }
7723 if at each iteration the parent isn't open, we can skip inflating it. if at some
7724 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7727 MonoGenericContext *parent_inst = NULL;
7728 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7729 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7730 if (!mono_error_ok (&error)) {
7731 mono_error_set_pending_exception (&error);
7735 if (parent->generic_class) {
7736 parent_inst = mono_class_get_context (parent);
7737 parent = parent->generic_class->container_class;
7740 mono_class_setup_vtable (parent);
7741 if (parent->vtable_size <= slot)
7744 generic_inst = parent_inst;
7747 klass = klass->parent;
7750 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7751 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7752 if (!mono_error_ok (&error)) {
7753 mono_error_set_pending_exception (&error);
7757 generic_inst = NULL;
7759 if (klass->generic_class) {
7760 generic_inst = mono_class_get_context (klass);
7761 klass = klass->generic_class->container_class;
7767 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7768 if (!mono_error_ok (&error)) {
7769 mono_error_set_pending_exception (&error);
7774 if (klass == method->klass)
7777 /*This is possible if definition == FALSE.
7778 * Do it here to be really sure we don't read invalid memory.
7780 if (slot >= klass->vtable_size)
7783 mono_class_setup_vtable (klass);
7785 result = klass->vtable [slot];
7786 if (result == NULL) {
7787 /* It is an abstract method */
7788 gpointer iter = NULL;
7789 while ((result = mono_class_get_methods (klass, &iter)))
7790 if (result->slot == slot)
7797 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7798 mono_error_set_pending_exception (&error);
7802 ICALL_EXPORT MonoString*
7803 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7805 MonoMethod *method = m->method;
7807 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7812 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7814 iter->sig = *(MonoMethodSignature**)argsp;
7816 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7817 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7820 /* FIXME: it's not documented what start is exactly... */
7824 iter->args = argsp + sizeof (gpointer);
7826 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7828 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7831 ICALL_EXPORT MonoTypedRef
7832 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7834 guint32 i, arg_size;
7838 i = iter->sig->sentinelpos + iter->next_arg;
7840 g_assert (i < iter->sig->param_count);
7842 res.type = iter->sig->params [i];
7843 res.klass = mono_class_from_mono_type (res.type);
7844 arg_size = mono_type_stack_size (res.type, &align);
7845 #if defined(__arm__) || defined(__mips__)
7846 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7848 res.value = iter->args;
7849 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7850 /* Values are stored as 8 byte register sized objects, but 'value'
7851 * is dereferenced as a pointer in other routines.
7853 res.value = (char*)res.value + 4;
7855 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7856 if (arg_size <= sizeof (gpointer)) {
7858 int padding = arg_size - mono_type_size (res.type, &dummy);
7859 res.value = (guint8*)res.value + padding;
7862 iter->args = (char*)iter->args + arg_size;
7865 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7870 ICALL_EXPORT MonoTypedRef
7871 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7873 guint32 i, arg_size;
7877 i = iter->sig->sentinelpos + iter->next_arg;
7879 g_assert (i < iter->sig->param_count);
7881 while (i < iter->sig->param_count) {
7882 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7884 res.type = iter->sig->params [i];
7885 res.klass = mono_class_from_mono_type (res.type);
7886 /* FIXME: endianess issue... */
7887 arg_size = mono_type_stack_size (res.type, &align);
7888 #if defined(__arm__) || defined(__mips__)
7889 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7891 res.value = iter->args;
7892 iter->args = (char*)iter->args + arg_size;
7894 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7897 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7905 ICALL_EXPORT MonoType*
7906 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7910 i = iter->sig->sentinelpos + iter->next_arg;
7912 g_assert (i < iter->sig->param_count);
7914 return iter->sig->params [i];
7917 ICALL_EXPORT MonoObject*
7918 mono_TypedReference_ToObject (MonoTypedRef* tref)
7921 MonoObject *result = NULL;
7922 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7923 MonoObject** objp = (MonoObject **)tref->value;
7927 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7928 mono_error_set_pending_exception (&error);
7932 ICALL_EXPORT MonoTypedRef
7933 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7936 MonoReflectionField *f;
7938 MonoType *ftype = NULL;
7942 memset (&res, 0, sizeof (res));
7945 g_assert (mono_array_length (fields) > 0);
7947 klass = target->vtable->klass;
7949 for (i = 0; i < mono_array_length (fields); ++i) {
7950 f = mono_array_get (fields, MonoReflectionField*, i);
7952 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7955 if (f->field->parent != klass) {
7956 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7960 p = (guint8*)target + f->field->offset;
7962 p += f->field->offset - sizeof (MonoObject);
7963 klass = mono_class_from_mono_type (f->field->type);
7964 ftype = f->field->type;
7968 res.klass = mono_class_from_mono_type (ftype);
7975 prelink_method (MonoMethod *method, MonoError *error)
7977 const char *exc_class, *exc_arg;
7979 mono_error_init (error);
7980 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7982 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7984 mono_error_set_exception_instance (error,
7985 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7988 /* create the wrapper, too? */
7992 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7996 prelink_method (method->method, &error);
7997 mono_error_set_pending_exception (&error);
8001 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
8004 MonoClass *klass = mono_class_from_mono_type (type->type);
8006 gpointer iter = NULL;
8008 mono_class_init_checked (klass, &error);
8009 if (mono_error_set_pending_exception (&error))
8012 while ((m = mono_class_get_methods (klass, &iter))) {
8013 prelink_method (m, &error);
8014 if (mono_error_set_pending_exception (&error))
8019 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
8021 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
8022 gint32 const **exponents,
8023 gunichar2 const **digitLowerTable,
8024 gunichar2 const **digitUpperTable,
8025 gint64 const **tenPowersList,
8026 gint32 const **decHexDigits)
8028 *mantissas = Formatter_MantissaBitsTable;
8029 *exponents = Formatter_TensExponentTable;
8030 *digitLowerTable = Formatter_DigitLowerTable;
8031 *digitUpperTable = Formatter_DigitUpperTable;
8032 *tenPowersList = Formatter_TenPowersList;
8033 *decHexDigits = Formatter_DecHexDigits;
8037 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
8038 * and avoid useless allocations.
8041 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
8043 MonoReflectionType *rt;
8047 mono_error_init (error);
8048 for (i = 0; i < type->num_mods; ++i) {
8049 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
8054 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
8055 return_val_if_nok (error, NULL);
8057 for (i = 0; i < type->num_mods; ++i) {
8058 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
8059 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
8060 return_val_if_nok (error, NULL);
8062 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8063 return_val_if_nok (error, NULL);
8065 mono_array_setref (res, count, rt);
8072 ICALL_EXPORT MonoArray*
8073 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
8076 MonoType *type = param->ClassImpl->type;
8077 MonoClass *member_class = mono_object_class (param->MemberImpl);
8078 MonoMethod *method = NULL;
8081 MonoMethodSignature *sig;
8084 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8085 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8086 method = rmethod->method;
8087 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
8088 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8089 if (!(method = prop->property->get))
8090 method = prop->property->set;
8093 char *type_name = mono_type_get_full_name (member_class);
8094 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
8095 MonoException *ex = mono_get_exception_not_supported (msg);
8098 mono_set_pending_exception (ex);
8102 image = method->klass->image;
8103 pos = param->PositionImpl;
8104 sig = mono_method_signature (method);
8108 type = sig->params [pos];
8110 res = type_array_from_modifiers (image, type, optional, &error);
8111 mono_error_set_pending_exception (&error);
8116 get_property_type (MonoProperty *prop)
8118 MonoMethodSignature *sig;
8120 sig = mono_method_signature (prop->get);
8122 } else if (prop->set) {
8123 sig = mono_method_signature (prop->set);
8124 return sig->params [sig->param_count - 1];
8129 ICALL_EXPORT MonoArray*
8130 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
8133 MonoType *type = get_property_type (property->property);
8134 MonoImage *image = property->klass->image;
8139 res = type_array_from_modifiers (image, type, optional, &error);
8140 mono_error_set_pending_exception (&error);
8145 *Construct a MonoType suited to be used to decode a constant blob object.
8147 * @type is the target type which will be constructed
8148 * @blob_type is the blob type, for example, that comes from the constant table
8149 * @real_type is the expected constructed type.
8152 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8154 type->type = blob_type;
8155 type->data.klass = NULL;
8156 if (blob_type == MONO_TYPE_CLASS)
8157 type->data.klass = mono_defaults.object_class;
8158 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8159 /* For enums, we need to use the base type */
8160 type->type = MONO_TYPE_VALUETYPE;
8161 type->data.klass = mono_class_from_mono_type (real_type);
8163 type->data.klass = mono_class_from_mono_type (real_type);
8166 ICALL_EXPORT MonoObject*
8167 property_info_get_default_value (MonoReflectionProperty *property)
8171 MonoProperty *prop = property->property;
8172 MonoType *type = get_property_type (prop);
8173 MonoDomain *domain = mono_object_domain (property);
8174 MonoTypeEnum def_type;
8175 const char *def_value;
8178 mono_class_init (prop->parent);
8180 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8181 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8185 def_value = mono_class_get_property_default_value (prop, &def_type);
8187 mono_type_from_blob_type (&blob_type, def_type, type);
8188 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8190 mono_error_set_pending_exception (&error);
8194 ICALL_EXPORT MonoBoolean
8195 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8198 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8199 MonoCustomAttrInfo *cinfo;
8202 mono_class_init_checked (attr_class, &error);
8203 if (mono_error_set_pending_exception (&error))
8206 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8207 if (!is_ok (&error)) {
8208 mono_error_set_pending_exception (&error);
8213 found = mono_custom_attrs_has_attr (cinfo, attr_class);
8215 mono_custom_attrs_free (cinfo);
8219 ICALL_EXPORT MonoArray*
8220 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8222 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8227 mono_class_init_checked (attr_class, &error);
8228 if (mono_error_set_pending_exception (&error))
8232 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8233 if (!mono_error_ok (&error)) {
8234 mono_error_set_pending_exception (&error);
8241 ICALL_EXPORT MonoArray*
8242 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8246 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8247 mono_error_set_pending_exception (&error);
8252 ICALL_EXPORT MonoString*
8253 ves_icall_Mono_Runtime_GetDisplayName (void)
8256 MonoString *display_name;
8258 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8259 display_name = mono_string_new (mono_domain_get (), info);
8261 return display_name;
8264 ICALL_EXPORT MonoString*
8265 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8268 MonoString *message;
8272 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8273 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8276 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8278 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8279 if (mono_error_set_pending_exception (&error))
8286 ICALL_EXPORT gpointer
8287 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8289 return GetCurrentProcess ();
8292 ICALL_EXPORT MonoBoolean
8293 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8295 return GetExitCodeProcess (handle, (guint32*) exitcode);
8298 ICALL_EXPORT MonoBoolean
8299 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8301 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8302 return CloseHandle (handle);
8304 return CloseProcess (handle);
8308 ICALL_EXPORT MonoBoolean
8309 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8311 return TerminateProcess (handle, exitcode);
8315 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8317 return WaitForInputIdle (handle, milliseconds);
8320 ICALL_EXPORT MonoBoolean
8321 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8323 return GetProcessWorkingSetSize (handle, min, max);
8326 ICALL_EXPORT MonoBoolean
8327 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8329 return SetProcessWorkingSetSize (handle, min, max);
8332 ICALL_EXPORT MonoBoolean
8333 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8335 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8339 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8341 return mono_process_current_pid ();
8345 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8347 return GetPriorityClass (handle);
8350 ICALL_EXPORT MonoBoolean
8351 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8353 return SetPriorityClass (handle, priorityClass);
8356 #ifndef DISABLE_ICALL_TABLES
8358 #define ICALL_TYPE(id,name,first)
8359 #define ICALL(id,name,func) Icall_ ## id,
8362 #include "metadata/icall-def.h"
8368 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8369 #define ICALL(id,name,func)
8371 #include "metadata/icall-def.h"
8377 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8378 #define ICALL(id,name,func)
8380 guint16 first_icall;
8383 static const IcallTypeDesc
8384 icall_type_descs [] = {
8385 #include "metadata/icall-def.h"
8389 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8392 #define ICALL_TYPE(id,name,first)
8395 #ifdef HAVE_ARRAY_ELEM_INIT
8396 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8397 #define MSGSTRFIELD1(line) str##line
8399 static const struct msgstrtn_t {
8400 #define ICALL(id,name,func)
8402 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8403 #include "metadata/icall-def.h"
8405 } icall_type_names_str = {
8406 #define ICALL_TYPE(id,name,first) (name),
8407 #include "metadata/icall-def.h"
8410 static const guint16 icall_type_names_idx [] = {
8411 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8412 #include "metadata/icall-def.h"
8415 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8417 static const struct msgstr_t {
8419 #define ICALL_TYPE(id,name,first)
8420 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8421 #include "metadata/icall-def.h"
8423 } icall_names_str = {
8424 #define ICALL(id,name,func) (name),
8425 #include "metadata/icall-def.h"
8428 static const guint16 icall_names_idx [] = {
8429 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8430 #include "metadata/icall-def.h"
8433 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8439 #define ICALL_TYPE(id,name,first) name,
8440 #define ICALL(id,name,func)
8441 static const char* const
8442 icall_type_names [] = {
8443 #include "metadata/icall-def.h"
8447 #define icall_type_name_get(id) (icall_type_names [(id)])
8451 #define ICALL_TYPE(id,name,first)
8452 #define ICALL(id,name,func) name,
8453 static const char* const
8455 #include "metadata/icall-def.h"
8458 #define icall_name_get(id) icall_names [(id)]
8460 #endif /* !HAVE_ARRAY_ELEM_INIT */
8464 #define ICALL_TYPE(id,name,first)
8465 #define ICALL(id,name,func) func,
8466 static const gconstpointer
8467 icall_functions [] = {
8468 #include "metadata/icall-def.h"
8472 #ifdef ENABLE_ICALL_SYMBOL_MAP
8475 #define ICALL_TYPE(id,name,first)
8476 #define ICALL(id,name,func) #func,
8477 static const gconstpointer
8478 icall_symbols [] = {
8479 #include "metadata/icall-def.h"
8484 #endif /* DISABLE_ICALL_TABLES */
8486 static mono_mutex_t icall_mutex;
8487 static GHashTable *icall_hash = NULL;
8488 static GHashTable *jit_icall_hash_name = NULL;
8489 static GHashTable *jit_icall_hash_addr = NULL;
8492 mono_icall_init (void)
8494 #ifndef DISABLE_ICALL_TABLES
8497 /* check that tables are sorted: disable in release */
8500 const char *prev_class = NULL;
8501 const char *prev_method;
8503 for (i = 0; i < Icall_type_num; ++i) {
8504 const IcallTypeDesc *desc;
8507 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8508 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8509 prev_class = icall_type_name_get (i);
8510 desc = &icall_type_descs [i];
8511 num_icalls = icall_desc_num_icalls (desc);
8512 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8513 for (j = 0; j < num_icalls; ++j) {
8514 const char *methodn = icall_name_get (desc->first_icall + j);
8515 if (prev_method && strcmp (prev_method, methodn) >= 0)
8516 g_print ("method %s should come before method %s\n", methodn, prev_method);
8517 prev_method = methodn;
8523 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8524 mono_os_mutex_init (&icall_mutex);
8528 mono_icall_lock (void)
8530 mono_locks_os_acquire (&icall_mutex, IcallLock);
8534 mono_icall_unlock (void)
8536 mono_locks_os_release (&icall_mutex, IcallLock);
8540 mono_icall_cleanup (void)
8542 g_hash_table_destroy (icall_hash);
8543 g_hash_table_destroy (jit_icall_hash_name);
8544 g_hash_table_destroy (jit_icall_hash_addr);
8545 mono_os_mutex_destroy (&icall_mutex);
8549 * mono_add_internal_call:
8550 * @name: method specification to surface to the managed world
8551 * @method: pointer to a C method to invoke when the method is called
8553 * This method surfaces the C function pointed by @method as a method
8554 * that has been surfaced in managed code with the method specified in
8555 * @name as an internal call.
8557 * Internal calls are surfaced to all app domains loaded and they are
8558 * accessibly by a type with the specified name.
8560 * You must provide a fully qualified type name, that is namespaces
8561 * and type name, followed by a colon and the method name, with an
8562 * optional signature to bind.
8564 * For example, the following are all valid declarations:
8566 * "MyApp.Services.ScriptService:Accelerate"
8567 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8569 * You use method parameters in cases where there might be more than
8570 * one surface method to managed code. That way you can register different
8571 * internal calls for different method overloads.
8573 * The internal calls are invoked with no marshalling. This means that .NET
8574 * types like System.String are exposed as `MonoString *` parameters. This is
8575 * different than the way that strings are surfaced in P/Invoke.
8577 * For more information on how the parameters are marshalled, see the
8578 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8581 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8582 * reference for more information on the format of method descriptions.
8585 mono_add_internal_call (const char *name, gconstpointer method)
8589 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8591 mono_icall_unlock ();
8594 #ifndef DISABLE_ICALL_TABLES
8596 #ifdef HAVE_ARRAY_ELEM_INIT
8598 compare_method_imap (const void *key, const void *elem)
8600 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8601 return strcmp (key, method_name);
8605 find_method_icall (const IcallTypeDesc *imap, const char *name)
8607 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);
8610 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8614 compare_class_imap (const void *key, const void *elem)
8616 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8617 return strcmp (key, class_name);
8620 static const IcallTypeDesc*
8621 find_class_icalls (const char *name)
8623 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);
8626 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8629 #else /* HAVE_ARRAY_ELEM_INIT */
8632 compare_method_imap (const void *key, const void *elem)
8634 const char** method_name = (const char**)elem;
8635 return strcmp (key, *method_name);
8639 find_method_icall (const IcallTypeDesc *imap, const char *name)
8641 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8644 return (gpointer)icall_functions [(nameslot - icall_names)];
8648 compare_class_imap (const void *key, const void *elem)
8650 const char** class_name = (const char**)elem;
8651 return strcmp (key, *class_name);
8654 static const IcallTypeDesc*
8655 find_class_icalls (const char *name)
8657 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8660 return &icall_type_descs [nameslot - icall_type_names];
8663 #endif /* HAVE_ARRAY_ELEM_INIT */
8665 #endif /* DISABLE_ICALL_TABLES */
8668 * we should probably export this as an helper (handle nested types).
8669 * Returns the number of chars written in buf.
8672 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8674 int nspacelen, cnamelen;
8675 nspacelen = strlen (klass->name_space);
8676 cnamelen = strlen (klass->name);
8677 if (nspacelen + cnamelen + 2 > bufsize)
8680 memcpy (buf, klass->name_space, nspacelen);
8681 buf [nspacelen ++] = '.';
8683 memcpy (buf + nspacelen, klass->name, cnamelen);
8684 buf [nspacelen + cnamelen] = 0;
8685 return nspacelen + cnamelen;
8688 #ifdef DISABLE_ICALL_TABLES
8690 no_icall_table (void)
8692 g_assert_not_reached ();
8697 mono_lookup_internal_call (MonoMethod *method)
8702 int typelen = 0, mlen, siglen;
8704 #ifndef DISABLE_ICALL_TABLES
8705 const IcallTypeDesc *imap = NULL;
8708 g_assert (method != NULL);
8710 if (method->is_inflated)
8711 method = ((MonoMethodInflated *) method)->declaring;
8713 if (method->klass->nested_in) {
8714 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8718 mname [pos++] = '/';
8721 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8727 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8732 #ifndef DISABLE_ICALL_TABLES
8733 imap = find_class_icalls (mname);
8736 mname [typelen] = ':';
8737 mname [typelen + 1] = ':';
8739 mlen = strlen (method->name);
8740 memcpy (mname + typelen + 2, method->name, mlen);
8741 sigstart = mname + typelen + 2 + mlen;
8744 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8745 siglen = strlen (tmpsig);
8746 if (typelen + mlen + siglen + 6 > sizeof (mname))
8749 memcpy (sigstart + 1, tmpsig, siglen);
8750 sigstart [siglen + 1] = ')';
8751 sigstart [siglen + 2] = 0;
8756 res = g_hash_table_lookup (icall_hash, mname);
8758 mono_icall_unlock ();;
8761 /* try without signature */
8763 res = g_hash_table_lookup (icall_hash, mname);
8765 mono_icall_unlock ();
8769 #ifdef DISABLE_ICALL_TABLES
8770 mono_icall_unlock ();
8771 /* Fail only when the result is actually used */
8772 /* mono_marshal_get_native_wrapper () depends on this */
8773 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8774 return ves_icall_System_String_ctor_RedirectToCreateString;
8776 return no_icall_table;
8778 /* it wasn't found in the static call tables */
8780 mono_icall_unlock ();
8783 res = find_method_icall (imap, sigstart - mlen);
8785 mono_icall_unlock ();
8788 /* try _with_ signature */
8790 res = find_method_icall (imap, sigstart - mlen);
8792 mono_icall_unlock ();
8796 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8797 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8798 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8799 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8800 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");
8801 g_print ("If you see other errors or faults after this message they are probably related\n");
8802 g_print ("and you need to fix your mono install first.\n");
8804 mono_icall_unlock ();
8810 #ifdef ENABLE_ICALL_SYMBOL_MAP
8812 func_cmp (gconstpointer key, gconstpointer p)
8814 return (gsize)key - (gsize)*(gsize*)p;
8819 * mono_lookup_icall_symbol:
8821 * Given the icall METHOD, returns its C symbol.
8824 mono_lookup_icall_symbol (MonoMethod *m)
8826 #ifdef DISABLE_ICALL_TABLES
8827 g_assert_not_reached ();
8830 #ifdef ENABLE_ICALL_SYMBOL_MAP
8834 static gconstpointer *functions_sorted;
8835 static const char**symbols_sorted;
8836 static gboolean inited;
8841 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8842 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8843 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8844 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8845 /* Bubble sort the two arrays */
8849 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8850 if (functions_sorted [i] > functions_sorted [i + 1]) {
8853 tmp = functions_sorted [i];
8854 functions_sorted [i] = functions_sorted [i + 1];
8855 functions_sorted [i + 1] = tmp;
8856 tmp = symbols_sorted [i];
8857 symbols_sorted [i] = symbols_sorted [i + 1];
8858 symbols_sorted [i + 1] = tmp;
8865 func = mono_lookup_internal_call (m);
8868 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8872 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8874 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8875 g_assert_not_reached ();
8882 type_from_typename (char *type_name)
8884 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8886 if (!strcmp (type_name, "int"))
8887 klass = mono_defaults.int_class;
8888 else if (!strcmp (type_name, "ptr"))
8889 klass = mono_defaults.int_class;
8890 else if (!strcmp (type_name, "void"))
8891 klass = mono_defaults.void_class;
8892 else if (!strcmp (type_name, "int32"))
8893 klass = mono_defaults.int32_class;
8894 else if (!strcmp (type_name, "uint32"))
8895 klass = mono_defaults.uint32_class;
8896 else if (!strcmp (type_name, "int8"))
8897 klass = mono_defaults.sbyte_class;
8898 else if (!strcmp (type_name, "uint8"))
8899 klass = mono_defaults.byte_class;
8900 else if (!strcmp (type_name, "int16"))
8901 klass = mono_defaults.int16_class;
8902 else if (!strcmp (type_name, "uint16"))
8903 klass = mono_defaults.uint16_class;
8904 else if (!strcmp (type_name, "long"))
8905 klass = mono_defaults.int64_class;
8906 else if (!strcmp (type_name, "ulong"))
8907 klass = mono_defaults.uint64_class;
8908 else if (!strcmp (type_name, "float"))
8909 klass = mono_defaults.single_class;
8910 else if (!strcmp (type_name, "double"))
8911 klass = mono_defaults.double_class;
8912 else if (!strcmp (type_name, "object"))
8913 klass = mono_defaults.object_class;
8914 else if (!strcmp (type_name, "obj"))
8915 klass = mono_defaults.object_class;
8916 else if (!strcmp (type_name, "string"))
8917 klass = mono_defaults.string_class;
8918 else if (!strcmp (type_name, "bool"))
8919 klass = mono_defaults.boolean_class;
8920 else if (!strcmp (type_name, "boolean"))
8921 klass = mono_defaults.boolean_class;
8923 g_error ("%s", type_name);
8924 g_assert_not_reached ();
8926 return &klass->byval_arg;
8930 * LOCKING: Take the corlib image lock.
8932 MonoMethodSignature*
8933 mono_create_icall_signature (const char *sigstr)
8938 MonoMethodSignature *res, *res2;
8939 MonoImage *corlib = mono_defaults.corlib;
8941 mono_image_lock (corlib);
8942 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8943 mono_image_unlock (corlib);
8948 parts = g_strsplit (sigstr, " ", 256);
8957 res = mono_metadata_signature_alloc (corlib, len - 1);
8962 * Under windows, the default pinvoke calling convention is STDCALL but
8965 res->call_convention = MONO_CALL_C;
8968 res->ret = type_from_typename (parts [0]);
8969 for (i = 1; i < len; ++i) {
8970 res->params [i - 1] = type_from_typename (parts [i]);
8975 mono_image_lock (corlib);
8976 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8978 res = res2; /*Value is allocated in the image pool*/
8980 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8981 mono_image_unlock (corlib);
8987 mono_find_jit_icall_by_name (const char *name)
8989 MonoJitICallInfo *info;
8990 g_assert (jit_icall_hash_name);
8993 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8994 mono_icall_unlock ();
8999 mono_find_jit_icall_by_addr (gconstpointer addr)
9001 MonoJitICallInfo *info;
9002 g_assert (jit_icall_hash_addr);
9005 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
9006 mono_icall_unlock ();
9012 * mono_get_jit_icall_info:
9014 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
9015 * caller should access it while holding the icall lock.
9018 mono_get_jit_icall_info (void)
9020 return jit_icall_hash_name;
9024 * mono_lookup_jit_icall_symbol:
9026 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
9029 mono_lookup_jit_icall_symbol (const char *name)
9031 MonoJitICallInfo *info;
9032 const char *res = NULL;
9035 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9037 res = info->c_symbol;
9038 mono_icall_unlock ();
9043 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
9046 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
9047 mono_icall_unlock ();
9051 * 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
9052 * icalls without wrappers in some cases.
9055 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
9057 MonoJitICallInfo *info;
9064 if (!jit_icall_hash_name) {
9065 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
9066 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
9069 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
9070 g_warning ("jit icall already defined \"%s\"\n", name);
9071 g_assert_not_reached ();
9074 info = g_new0 (MonoJitICallInfo, 1);
9079 info->c_symbol = c_symbol;
9080 info->no_raise = no_raise;
9083 info->wrapper = func;
9085 info->wrapper = NULL;
9088 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
9089 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
9091 mono_icall_unlock ();
9096 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
9098 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);