5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
9 * Aleksey Kliger (aleksey@xamarin.com)
11 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
12 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
14 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
25 #ifdef HAVE_SYS_TIME_H
31 #if defined (HOST_WIN32)
34 #if defined (HAVE_WCHAR_H)
38 #include "mono/utils/mono-membar.h"
39 #include <mono/metadata/object.h>
40 #include <mono/metadata/threads.h>
41 #include <mono/metadata/threads-types.h>
42 #include <mono/metadata/threadpool-ms.h>
43 #include <mono/metadata/threadpool-ms-io.h>
44 #include <mono/metadata/monitor.h>
45 #include <mono/metadata/reflection.h>
46 #include <mono/metadata/assembly.h>
47 #include <mono/metadata/tabledefs.h>
48 #include <mono/metadata/exception.h>
49 #include <mono/metadata/exception-internals.h>
50 #include <mono/metadata/file-io.h>
51 #include <mono/metadata/console-io.h>
52 #include <mono/metadata/mono-route.h>
53 #include <mono/metadata/socket-io.h>
54 #include <mono/metadata/mono-endian.h>
55 #include <mono/metadata/tokentype.h>
56 #include <mono/metadata/domain-internals.h>
57 #include <mono/metadata/metadata-internals.h>
58 #include <mono/metadata/class-internals.h>
59 #include <mono/metadata/reflection-internals.h>
60 #include <mono/metadata/marshal.h>
61 #include <mono/metadata/gc-internals.h>
62 #include <mono/metadata/mono-gc.h>
63 #include <mono/metadata/rand.h>
64 #include <mono/metadata/sysmath.h>
65 #include <mono/metadata/string-icalls.h>
66 #include <mono/metadata/debug-helpers.h>
67 #include <mono/metadata/process.h>
68 #include <mono/metadata/environment.h>
69 #include <mono/metadata/profiler-private.h>
70 #include <mono/metadata/locales.h>
71 #include <mono/metadata/filewatcher.h>
72 #include <mono/metadata/security.h>
73 #include <mono/metadata/mono-config.h>
74 #include <mono/metadata/cil-coff.h>
75 #include <mono/metadata/number-formatter.h>
76 #include <mono/metadata/security-manager.h>
77 #include <mono/metadata/security-core-clr.h>
78 #include <mono/metadata/mono-perfcounters.h>
79 #include <mono/metadata/mono-debug.h>
80 #include <mono/metadata/mono-ptr-array.h>
81 #include <mono/metadata/verify-internals.h>
82 #include <mono/metadata/runtime.h>
83 #include <mono/metadata/file-mmap.h>
84 #include <mono/metadata/seq-points-data.h>
85 #include <mono/io-layer/io-layer.h>
86 #include <mono/utils/monobitset.h>
87 #include <mono/utils/mono-time.h>
88 #include <mono/utils/mono-proclib.h>
89 #include <mono/utils/mono-string.h>
90 #include <mono/utils/mono-error-internals.h>
91 #include <mono/utils/mono-mmap.h>
92 #include <mono/utils/mono-io-portability.h>
93 #include <mono/utils/mono-digest.h>
94 #include <mono/utils/bsearch.h>
95 #include <mono/utils/mono-os-mutex.h>
96 #include <mono/utils/mono-threads.h>
98 #if defined (HOST_WIN32)
102 #include "decimal-ms.h"
103 #include "number-ms.h"
105 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
106 #include <sys/utsname.h>
109 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
111 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
113 /* Lazy class loading functions */
114 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
115 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
116 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
119 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
122 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
124 static inline MonoBoolean
125 is_generic_parameter (MonoType *type)
127 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
131 mono_class_init_checked (MonoClass *klass, MonoError *error)
133 mono_error_init (error);
135 if (!mono_class_init (klass))
136 mono_error_set_for_class_failure (error, klass);
139 ICALL_EXPORT MonoObject *
140 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
146 MonoObject *result = NULL;
148 ac = (MonoClass *)arr->obj.vtable->klass;
150 esize = mono_array_element_size (ac);
151 ea = (gpointer*)((char*)arr->vector + (pos * esize));
153 if (ac->element_class->valuetype) {
154 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
155 mono_error_set_pending_exception (&error);
157 result = (MonoObject *)*ea;
161 ICALL_EXPORT MonoObject *
162 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
168 MONO_CHECK_ARG_NULL (idxs, NULL);
171 ic = (MonoClass *)io->obj.vtable->klass;
173 ac = (MonoClass *)arr->obj.vtable->klass;
175 g_assert (ic->rank == 1);
176 if (io->bounds != NULL || io->max_length != ac->rank) {
177 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
181 ind = (gint32 *)io->vector;
183 if (arr->bounds == NULL) {
184 if (*ind < 0 || *ind >= arr->max_length) {
185 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
189 return ves_icall_System_Array_GetValueImpl (arr, *ind);
192 for (i = 0; i < ac->rank; i++) {
193 if ((ind [i] < arr->bounds [i].lower_bound) ||
194 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
195 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
200 pos = ind [0] - arr->bounds [0].lower_bound;
201 for (i = 1; i < ac->rank; i++)
202 pos = pos * arr->bounds [i].length + ind [i] -
203 arr->bounds [i].lower_bound;
205 return ves_icall_System_Array_GetValueImpl (arr, pos);
209 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
212 MonoClass *ac, *vc, *ec;
221 mono_error_init (&error);
224 vc = value->vtable->klass;
228 ac = arr->obj.vtable->klass;
229 ec = ac->element_class;
231 esize = mono_array_element_size (ac);
232 ea = (gpointer*)((char*)arr->vector + (pos * esize));
233 va = (gpointer*)((char*)value + sizeof (MonoObject));
235 if (mono_class_is_nullable (ec)) {
236 mono_nullable_init ((guint8*)ea, value, ec);
241 mono_gc_bzero_atomic (ea, esize);
245 #define NO_WIDENING_CONVERSION G_STMT_START{\
246 mono_set_pending_exception (mono_get_exception_argument ( \
247 "value", "not a widening conversion")); \
251 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
252 if (esize < vsize + (extra)) { \
253 mono_set_pending_exception (mono_get_exception_argument ( \
254 "value", "not a widening conversion")); \
259 #define INVALID_CAST G_STMT_START{ \
260 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
261 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
265 /* Check element (destination) type. */
266 switch (ec->byval_arg.type) {
267 case MONO_TYPE_STRING:
268 switch (vc->byval_arg.type) {
269 case MONO_TYPE_STRING:
275 case MONO_TYPE_BOOLEAN:
276 switch (vc->byval_arg.type) {
277 case MONO_TYPE_BOOLEAN:
290 NO_WIDENING_CONVERSION;
299 if (!ec->valuetype) {
300 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
301 if (mono_error_set_pending_exception (&error))
305 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
309 if (mono_object_isinst_checked (value, ec, &error)) {
310 if (ec->has_references)
311 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
313 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
316 if (mono_error_set_pending_exception (&error))
322 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
324 et = ec->byval_arg.type;
325 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
326 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
328 vt = vc->byval_arg.type;
329 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
330 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
332 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
338 case MONO_TYPE_CHAR: \
339 CHECK_WIDENING_CONVERSION(0); \
340 *(etype *) ea = (etype) u64; \
342 /* You can't assign a signed value to an unsigned array. */ \
347 /* You can't assign a floating point number to an integer array. */ \
350 NO_WIDENING_CONVERSION; \
354 #define ASSIGN_SIGNED(etype) G_STMT_START{\
360 CHECK_WIDENING_CONVERSION(0); \
361 *(etype *) ea = (etype) i64; \
363 /* You can assign an unsigned value to a signed array if the array's */ \
364 /* element size is larger than the value size. */ \
369 case MONO_TYPE_CHAR: \
370 CHECK_WIDENING_CONVERSION(1); \
371 *(etype *) ea = (etype) u64; \
373 /* You can't assign a floating point number to an integer array. */ \
376 NO_WIDENING_CONVERSION; \
380 #define ASSIGN_REAL(etype) G_STMT_START{\
384 CHECK_WIDENING_CONVERSION(0); \
385 *(etype *) ea = (etype) r64; \
387 /* All integer values fit into a floating point array, so we don't */ \
388 /* need to CHECK_WIDENING_CONVERSION here. */ \
393 *(etype *) ea = (etype) i64; \
399 case MONO_TYPE_CHAR: \
400 *(etype *) ea = (etype) u64; \
407 u64 = *(guint8 *) va;
410 u64 = *(guint16 *) va;
413 u64 = *(guint32 *) va;
416 u64 = *(guint64 *) va;
422 i64 = *(gint16 *) va;
425 i64 = *(gint32 *) va;
428 i64 = *(gint64 *) va;
431 r64 = *(gfloat *) va;
434 r64 = *(gdouble *) va;
437 u64 = *(guint16 *) va;
439 case MONO_TYPE_BOOLEAN:
440 /* Boolean is only compatible with itself. */
453 NO_WIDENING_CONVERSION;
460 /* If we can't do a direct copy, let's try a widening conversion. */
463 ASSIGN_UNSIGNED (guint16);
465 ASSIGN_UNSIGNED (guint8);
467 ASSIGN_UNSIGNED (guint16);
469 ASSIGN_UNSIGNED (guint32);
471 ASSIGN_UNSIGNED (guint64);
473 ASSIGN_SIGNED (gint8);
475 ASSIGN_SIGNED (gint16);
477 ASSIGN_SIGNED (gint32);
479 ASSIGN_SIGNED (gint64);
481 ASSIGN_REAL (gfloat);
483 ASSIGN_REAL (gdouble);
487 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
491 #undef NO_WIDENING_CONVERSION
492 #undef CHECK_WIDENING_CONVERSION
493 #undef ASSIGN_UNSIGNED
499 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
505 MONO_CHECK_ARG_NULL (idxs,);
507 ic = idxs->obj.vtable->klass;
508 ac = arr->obj.vtable->klass;
510 g_assert (ic->rank == 1);
511 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
512 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
516 ind = (gint32 *)idxs->vector;
518 if (arr->bounds == NULL) {
519 if (*ind < 0 || *ind >= arr->max_length) {
520 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
524 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
528 for (i = 0; i < ac->rank; i++)
529 if ((ind [i] < arr->bounds [i].lower_bound) ||
530 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
531 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
535 pos = ind [0] - arr->bounds [0].lower_bound;
536 for (i = 1; i < ac->rank; i++)
537 pos = pos * arr->bounds [i].length + ind [i] -
538 arr->bounds [i].lower_bound;
540 ves_icall_System_Array_SetValueImpl (arr, value, pos);
543 ICALL_EXPORT MonoArray *
544 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
547 MonoClass *aklass, *klass;
550 gboolean bounded = FALSE;
552 MONO_CHECK_ARG_NULL (type, NULL);
553 MONO_CHECK_ARG_NULL (lengths, NULL);
555 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
557 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
559 for (i = 0; i < mono_array_length (lengths); i++) {
560 if (mono_array_get (lengths, gint32, i) < 0) {
561 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
566 klass = mono_class_from_mono_type (type->type);
567 mono_class_init_checked (klass, &error);
568 if (mono_error_set_pending_exception (&error))
571 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
572 /* vectors are not the same as one dimensional arrays with no-zero bounds */
577 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
579 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
580 for (i = 0; i < aklass->rank; ++i) {
581 sizes [i] = mono_array_get (lengths, guint32, i);
583 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
585 sizes [i + aklass->rank] = 0;
588 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
589 mono_error_set_pending_exception (&error);
594 ICALL_EXPORT MonoArray *
595 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
598 MonoClass *aklass, *klass;
601 gboolean bounded = FALSE;
603 MONO_CHECK_ARG_NULL (type, NULL);
604 MONO_CHECK_ARG_NULL (lengths, NULL);
606 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
608 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
610 for (i = 0; i < mono_array_length (lengths); i++) {
611 if ((mono_array_get (lengths, gint64, i) < 0) ||
612 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
613 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
618 klass = mono_class_from_mono_type (type->type);
619 mono_class_init_checked (klass, &error);
620 if (mono_error_set_pending_exception (&error))
623 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
624 /* vectors are not the same as one dimensional arrays with no-zero bounds */
629 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
631 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
632 for (i = 0; i < aklass->rank; ++i) {
633 sizes [i] = mono_array_get (lengths, guint64, i);
635 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
637 sizes [i + aklass->rank] = 0;
640 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
641 mono_error_set_pending_exception (&error);
647 ves_icall_System_Array_GetRank (MonoObject *arr)
649 return arr->vtable->klass->rank;
653 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
655 gint32 rank = arr->obj.vtable->klass->rank;
658 if ((dimension < 0) || (dimension >= rank)) {
659 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
663 if (arr->bounds == NULL)
664 length = arr->max_length;
666 length = arr->bounds [dimension].length;
668 #ifdef MONO_BIG_ARRAYS
669 if (length > G_MAXINT32) {
670 mono_set_pending_exception (mono_get_exception_overflow ());
678 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
680 gint32 rank = arr->obj.vtable->klass->rank;
682 if ((dimension < 0) || (dimension >= rank)) {
683 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
687 if (arr->bounds == NULL)
688 return arr->max_length;
690 return arr->bounds [dimension].length;
694 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
696 gint32 rank = arr->obj.vtable->klass->rank;
698 if ((dimension < 0) || (dimension >= rank)) {
699 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
703 if (arr->bounds == NULL)
706 return arr->bounds [dimension].lower_bound;
710 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
712 int sz = mono_array_element_size (mono_object_class (arr));
713 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
716 ICALL_EXPORT MonoArray*
717 ves_icall_System_Array_Clone (MonoArray *arr)
720 MonoArray *result = mono_array_clone_checked (arr, &error);
721 mono_error_set_pending_exception (&error);
725 ICALL_EXPORT gboolean
726 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
731 MonoVTable *src_vtable;
732 MonoVTable *dest_vtable;
733 MonoClass *src_class;
734 MonoClass *dest_class;
736 src_vtable = source->obj.vtable;
737 dest_vtable = dest->obj.vtable;
739 if (src_vtable->rank != dest_vtable->rank)
742 if (source->bounds || dest->bounds)
745 /* there's no integer overflow since mono_array_length returns an unsigned integer */
746 if ((dest_idx + length > mono_array_length_fast (dest)) ||
747 (source_idx + length > mono_array_length_fast (source)))
750 src_class = src_vtable->klass->element_class;
751 dest_class = dest_vtable->klass->element_class;
754 * Handle common cases.
757 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
758 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
760 if (src_class == mono_defaults.object_class && dest_class->valuetype)
763 /* Check if we're copying a char[] <==> (u)short[] */
764 if (src_class != dest_class) {
765 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
768 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
769 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
773 if (dest_class->valuetype) {
774 element_size = mono_array_element_size (source->obj.vtable->klass);
775 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
776 if (dest_class->has_references) {
777 mono_value_copy_array (dest, dest_idx, source_addr, length);
779 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
780 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
783 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
790 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
796 ac = (MonoClass *)arr->obj.vtable->klass;
798 esize = mono_array_element_size (ac);
799 ea = (gpointer*)((char*)arr->vector + (pos * esize));
801 mono_gc_memmove_atomic (value, ea, esize);
805 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
811 ac = (MonoClass *)arr->obj.vtable->klass;
812 ec = ac->element_class;
814 esize = mono_array_element_size (ac);
815 ea = (gpointer*)((char*)arr->vector + (pos * esize));
817 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
818 g_assert (esize == sizeof (gpointer));
819 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
821 g_assert (ec->inited);
822 g_assert (esize == mono_class_value_size (ec, NULL));
823 if (ec->has_references)
824 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
826 mono_gc_memmove_atomic (ea, value, esize);
831 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
833 MonoClass *klass = array->obj.vtable->klass;
834 guint32 size = mono_array_element_size (klass);
835 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
837 const char *field_data;
839 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
840 MonoException *exc = mono_get_exception_argument("array",
841 "Cannot initialize array of non-primitive type.");
842 mono_set_pending_exception (exc);
846 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
847 MonoException *exc = mono_get_exception_argument("field_handle",
848 "Field doesn't have an RVA");
849 mono_set_pending_exception (exc);
853 size *= array->max_length;
854 field_data = mono_field_get_data (field_handle);
856 if (size > mono_type_size (field_handle->type, &align)) {
857 MonoException *exc = mono_get_exception_argument("field_handle",
858 "Field not large enough to fill array");
859 mono_set_pending_exception (exc);
863 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
865 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
866 guint ## n *src = (guint ## n *) field_data; \
868 nEnt = (size / sizeof(guint ## n)); \
870 for (i = 0; i < nEnt; i++) { \
871 data[i] = read ## n (&src[i]); \
875 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
877 switch (type->type) {
894 memcpy (mono_array_addr (array, char, 0), field_data, size);
898 memcpy (mono_array_addr (array, char, 0), field_data, size);
903 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
905 return offsetof (MonoString, chars);
908 ICALL_EXPORT MonoObject *
909 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
911 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
915 MonoObject *ret = mono_object_clone_checked (obj, &error);
916 mono_error_set_pending_exception (&error);
923 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
929 MONO_CHECK_ARG_NULL (handle,);
931 klass = mono_class_from_mono_type (handle);
932 MONO_CHECK_ARG (handle, klass,);
934 if (klass->generic_container)
937 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
938 if (!is_ok (&error)) {
939 mono_error_set_pending_exception (&error);
943 /* This will call the type constructor */
944 if (!mono_runtime_class_init_full (vtable, &error))
945 mono_error_set_pending_exception (&error);
949 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
953 mono_image_check_for_module_cctor (image);
954 if (image->has_module_cctor) {
955 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
956 if (!mono_error_ok (&error)) {
957 mono_error_set_pending_exception (&error);
960 /*It's fine to raise the exception here*/
961 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
962 if (!is_ok (&error)) {
963 mono_error_set_pending_exception (&error);
966 if (!mono_runtime_class_init_full (vtable, &error))
967 mono_error_set_pending_exception (&error);
971 ICALL_EXPORT MonoBoolean
972 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
977 /* later make this configurable and per-arch */
978 int min_size = 4096 * 4 * sizeof (void*);
979 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
980 /* if we have no info we are optimistic and assume there is enough room */
984 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
988 current = (guint8 *)&stack_addr;
989 if (current > stack_addr) {
990 if ((current - stack_addr) < min_size)
993 if (current - (stack_addr - stack_size) < min_size)
999 ICALL_EXPORT MonoObject *
1000 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
1003 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
1004 mono_error_set_pending_exception (&error);
1010 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1014 MonoObject **values = NULL;
1017 gint32 result = (int)(gsize)mono_defaults.int32_class;
1018 MonoClassField* field;
1021 klass = mono_object_class (this_obj);
1023 if (mono_class_num_fields (klass) == 0)
1027 * Compute the starting value of the hashcode for fields of primitive
1028 * types, and return the remaining fields in an array to the managed side.
1029 * This way, we can avoid costly reflection operations in managed code.
1032 while ((field = mono_class_get_fields (klass, &iter))) {
1033 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1035 if (mono_field_is_deleted (field))
1037 /* FIXME: Add more types */
1038 switch (field->type->type) {
1040 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1042 case MONO_TYPE_STRING: {
1044 s = *(MonoString**)((guint8*)this_obj + field->offset);
1046 result ^= mono_string_hash (s);
1051 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1052 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1053 if (!is_ok (&error)) {
1054 mono_error_set_pending_exception (&error);
1057 values [count++] = o;
1063 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1064 if (mono_error_set_pending_exception (&error))
1066 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1067 for (i = 0; i < count; ++i)
1068 mono_array_setref (*fields, i, values [i]);
1075 ICALL_EXPORT MonoBoolean
1076 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1080 MonoObject **values = NULL;
1082 MonoClassField* field;
1086 MONO_CHECK_ARG_NULL (that, FALSE);
1088 if (this_obj->vtable != that->vtable)
1091 klass = mono_object_class (this_obj);
1093 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1094 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1097 * Do the comparison for fields of primitive type and return a result if
1098 * possible. Otherwise, return the remaining fields in an array to the
1099 * managed side. This way, we can avoid costly reflection operations in
1104 while ((field = mono_class_get_fields (klass, &iter))) {
1105 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1107 if (mono_field_is_deleted (field))
1109 /* FIXME: Add more types */
1110 switch (field->type->type) {
1113 case MONO_TYPE_BOOLEAN:
1114 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1119 case MONO_TYPE_CHAR:
1120 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1125 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1130 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1134 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1138 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1143 case MONO_TYPE_STRING: {
1144 MonoString *s1, *s2;
1145 guint32 s1len, s2len;
1146 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1147 s2 = *(MonoString**)((guint8*)that + field->offset);
1150 if ((s1 == NULL) || (s2 == NULL))
1152 s1len = mono_string_length (s1);
1153 s2len = mono_string_length (s2);
1157 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1163 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1164 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1165 if (!is_ok (&error)) {
1166 mono_error_set_pending_exception (&error);
1169 values [count++] = o;
1170 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1171 if (!is_ok (&error)) {
1172 mono_error_set_pending_exception (&error);
1175 values [count++] = o;
1178 if (klass->enumtype)
1179 /* enums only have one non-static field */
1185 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1186 if (mono_error_set_pending_exception (&error))
1188 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1189 for (i = 0; i < count; ++i)
1190 mono_array_setref_fast (*fields, i, values [i]);
1197 ICALL_EXPORT MonoReflectionType *
1198 ves_icall_System_Object_GetType (MonoObject *obj)
1201 MonoReflectionType *ret;
1202 #ifndef DISABLE_REMOTING
1203 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1204 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1207 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1209 mono_error_set_pending_exception (&error);
1214 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1216 MONO_CHECK_ARG_NULL (obj, 0);
1219 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1220 mono_error_set_pending_exception (&error);
1225 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1226 MonoReflectionMethod *method,
1227 MonoArray *opt_param_types)
1229 MONO_CHECK_ARG_NULL (method, 0);
1232 gint32 result = mono_image_create_method_token (
1233 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1234 mono_error_set_pending_exception (&error);
1239 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1242 mono_image_create_pefile (mb, file, &error);
1243 mono_error_set_pending_exception (&error);
1247 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1250 mono_image_build_metadata (mb, &error);
1251 mono_error_set_pending_exception (&error);
1255 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1257 mono_image_register_token (mb->dynamic_image, token, obj);
1260 ICALL_EXPORT MonoObject*
1261 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1265 mono_loader_lock ();
1266 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1267 mono_loader_unlock ();
1272 ICALL_EXPORT MonoReflectionModule*
1273 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1276 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1277 mono_error_set_pending_exception (&error);
1282 * ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class:
1283 * @tb: a TypeBuilder object
1286 * Creates the generic class after all generic parameters have been added.
1289 ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class (MonoReflectionTypeBuilder *tb)
1292 (void) mono_reflection_create_generic_class (tb, &error);
1293 mono_error_set_pending_exception (&error);
1296 #ifndef DISABLE_REFLECTION_EMIT
1297 ICALL_EXPORT MonoArray*
1298 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
1301 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
1302 mono_error_set_pending_exception (&error);
1308 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1310 MonoMethod **dest = (MonoMethod **)data;
1312 /* skip unmanaged frames */
1317 if (!strcmp (m->klass->name_space, "System.Reflection"))
1326 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1328 MonoMethod **dest = (MonoMethod **)data;
1330 /* skip unmanaged frames */
1334 if (m->wrapper_type != MONO_WRAPPER_NONE)
1342 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1353 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1355 MonoMethod **dest = (MonoMethod **)data;
1357 /* skip unmanaged frames */
1361 if (m->wrapper_type != MONO_WRAPPER_NONE)
1369 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1370 || (!strcmp (m->klass->name_space, "System"))))
1380 static MonoReflectionType *
1381 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1383 MonoMethod *m, *dest;
1385 MonoType *type = NULL;
1386 MonoAssembly *assembly = NULL;
1387 gboolean type_resolve = FALSE;
1388 MonoImage *rootimage = NULL;
1390 mono_error_init (error);
1393 * We must compute the calling assembly as type loading must happen under a metadata context.
1394 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1395 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1397 m = mono_method_get_last_managed ();
1399 if (m && m->klass->image != mono_defaults.corlib) {
1400 /* Happens with inlining */
1402 /* Ugly hack: type_from_parsed_name is called from
1403 * System.Type.internal_from_name, which is called most
1404 * directly from System.Type.GetType(string,bool,bool) but
1405 * also indirectly from places such as
1406 * System.Type.GetType(string,func,func) (via
1407 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1408 * so we need to skip over all of those to find the true caller.
1410 * It would be nice if we had stack marks.
1412 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1418 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1419 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1420 * to crash. This only seems to happen in some strange remoting
1421 * scenarios and I was unable to figure out what's happening there.
1422 * Dec 10, 2005 - Martin.
1426 assembly = dest->klass->image->assembly;
1427 type_resolve = TRUE;
1428 rootimage = assembly->image;
1430 g_warning (G_STRLOC);
1433 if (info->assembly.name)
1434 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1437 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1438 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1439 return_val_if_nok (error, NULL);
1443 // Say we're looking for System.Generic.Dict<int, Local>
1444 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1445 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1446 // is messed up when we go to construct the Local as the type arg...
1448 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1449 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1450 if (!info->assembly.name && !type) {
1452 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1453 return_val_if_nok (error, NULL);
1455 if (assembly && !type && type_resolve) {
1456 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1457 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1458 return_val_if_nok (error, NULL);
1464 return mono_type_get_object_checked (mono_domain_get (), type, error);
1467 ICALL_EXPORT MonoReflectionType*
1468 ves_icall_System_Type_internal_from_name (MonoString *name,
1469 MonoBoolean throwOnError,
1470 MonoBoolean ignoreCase)
1473 MonoTypeNameParse info;
1474 MonoReflectionType *type = NULL;
1477 char *str = mono_string_to_utf8_checked (name, &error);
1478 if (!is_ok (&error))
1481 parsedOk = mono_reflection_parse_type (str, &info);
1483 /* mono_reflection_parse_type() mangles the string */
1485 mono_reflection_free_type_info (&info);
1487 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1491 type = type_from_parsed_name (&info, ignoreCase, &error);
1493 mono_reflection_free_type_info (&info);
1495 if (!is_ok (&error))
1500 mono_error_set_type_load_name (&error, g_strdup (str), NULL, "");
1507 if (!is_ok (&error)) {
1509 mono_error_set_pending_exception (&error);
1511 mono_error_cleanup (&error);
1519 ICALL_EXPORT MonoReflectionType*
1520 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1523 MonoReflectionType *ret;
1524 MonoDomain *domain = mono_domain_get ();
1526 ret = mono_type_get_object_checked (domain, handle, &error);
1527 mono_error_set_pending_exception (&error);
1532 /* System.TypeCode */
1551 TYPECODE_STRING = 18
1554 ICALL_EXPORT guint32
1555 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1557 int t = type->type->type;
1559 if (type->type->byref)
1560 return TYPECODE_OBJECT;
1564 case MONO_TYPE_VOID:
1565 return TYPECODE_OBJECT;
1566 case MONO_TYPE_BOOLEAN:
1567 return TYPECODE_BOOLEAN;
1569 return TYPECODE_BYTE;
1571 return TYPECODE_SBYTE;
1573 return TYPECODE_UINT16;
1575 return TYPECODE_INT16;
1576 case MONO_TYPE_CHAR:
1577 return TYPECODE_CHAR;
1581 return TYPECODE_OBJECT;
1583 return TYPECODE_UINT32;
1585 return TYPECODE_INT32;
1587 return TYPECODE_UINT64;
1589 return TYPECODE_INT64;
1591 return TYPECODE_SINGLE;
1593 return TYPECODE_DOUBLE;
1594 case MONO_TYPE_VALUETYPE: {
1595 MonoClass *klass = type->type->data.klass;
1597 if (klass->enumtype) {
1598 t = mono_class_enum_basetype (klass)->type;
1600 } else if (mono_is_corlib_image (klass->image)) {
1601 if (strcmp (klass->name_space, "System") == 0) {
1602 if (strcmp (klass->name, "Decimal") == 0)
1603 return TYPECODE_DECIMAL;
1604 else if (strcmp (klass->name, "DateTime") == 0)
1605 return TYPECODE_DATETIME;
1608 return TYPECODE_OBJECT;
1610 case MONO_TYPE_STRING:
1611 return TYPECODE_STRING;
1612 case MONO_TYPE_SZARRAY:
1613 case MONO_TYPE_ARRAY:
1614 case MONO_TYPE_OBJECT:
1616 case MONO_TYPE_MVAR:
1617 case MONO_TYPE_TYPEDBYREF:
1618 return TYPECODE_OBJECT;
1619 case MONO_TYPE_CLASS:
1621 MonoClass *klass = type->type->data.klass;
1622 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1623 if (strcmp (klass->name, "DBNull") == 0)
1624 return TYPECODE_DBNULL;
1627 return TYPECODE_OBJECT;
1628 case MONO_TYPE_GENERICINST:
1629 return TYPECODE_OBJECT;
1631 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1637 mono_type_is_primitive (MonoType *type)
1639 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1640 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1644 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1646 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1647 return mono_class_enum_basetype (type->data.klass);
1648 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1649 return mono_class_enum_basetype (type->data.generic_class->container_class);
1653 ICALL_EXPORT guint32
1654 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1659 g_assert (type != NULL);
1661 klass = mono_class_from_mono_type (type->type);
1662 klassc = mono_class_from_mono_type (c->type);
1664 if (type->type->byref ^ c->type->byref)
1667 if (type->type->byref) {
1668 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1669 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1671 klass = mono_class_from_mono_type (t);
1672 klassc = mono_class_from_mono_type (ot);
1674 if (mono_type_is_primitive (t)) {
1675 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1676 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1677 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1678 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1679 return t->type == ot->type;
1681 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1684 if (klass->valuetype)
1685 return klass == klassc;
1686 return klass->valuetype == klassc->valuetype;
1689 return mono_class_is_assignable_from (klass, klassc);
1692 ICALL_EXPORT guint32
1693 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1696 MonoClass *klass = mono_class_from_mono_type (type->type);
1697 mono_class_init_checked (klass, &error);
1698 if (!is_ok (&error)) {
1699 mono_error_set_pending_exception (&error);
1702 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1703 mono_error_set_pending_exception (&error);
1707 ICALL_EXPORT guint32
1708 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1710 MonoClass *klass = mono_class_from_mono_type (type->type);
1711 return klass->flags;
1714 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1715 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1718 MonoClass *klass = field->field->parent;
1719 MonoMarshalType *info;
1723 if (klass->generic_container ||
1724 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1727 ftype = mono_field_get_type (field->field);
1728 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1731 info = mono_marshal_load_type_info (klass);
1733 for (i = 0; i < info->num_fields; ++i) {
1734 if (info->fields [i].field == field->field) {
1735 if (!info->fields [i].mspec)
1738 MonoReflectionMarshalAsAttribute* obj;
1739 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1740 if (!mono_error_ok (&error))
1741 mono_error_set_pending_exception (&error);
1750 ICALL_EXPORT MonoReflectionField*
1751 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1754 gboolean found = FALSE;
1761 klass = handle->parent;
1763 klass = mono_class_from_mono_type (type);
1765 /* Check that the field belongs to the class */
1766 for (k = klass; k; k = k->parent) {
1767 if (k == handle->parent) {
1774 /* The managed code will throw the exception */
1778 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1779 mono_error_set_pending_exception (&error);
1783 ICALL_EXPORT MonoArray*
1784 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1787 MonoType *type = mono_field_get_type_checked (field->field, &error);
1790 if (!mono_error_ok (&error)) {
1791 mono_error_set_pending_exception (&error);
1795 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1796 mono_error_set_pending_exception (&error);
1801 vell_icall_get_method_attributes (MonoMethod *method)
1803 return method->flags;
1807 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1810 MonoReflectionType *rt;
1811 MonoDomain *domain = mono_domain_get ();
1812 MonoMethodSignature* sig;
1814 sig = mono_method_signature_checked (method, &error);
1815 if (!mono_error_ok (&error)) {
1816 mono_error_set_pending_exception (&error);
1820 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1821 if (!mono_error_ok (&error)) {
1822 mono_error_set_pending_exception (&error);
1826 MONO_STRUCT_SETREF (info, parent, rt);
1828 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1829 if (!mono_error_ok (&error)) {
1830 mono_error_set_pending_exception (&error);
1834 MONO_STRUCT_SETREF (info, ret, rt);
1836 info->attrs = method->flags;
1837 info->implattrs = method->iflags;
1838 if (sig->call_convention == MONO_CALL_DEFAULT)
1839 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1841 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1846 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1849 ICALL_EXPORT MonoArray*
1850 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1853 MonoDomain *domain = mono_domain_get ();
1855 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1856 mono_error_set_pending_exception (&error);
1860 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1861 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1864 MonoDomain *domain = mono_domain_get ();
1865 MonoReflectionMarshalAsAttribute* res = NULL;
1866 MonoMarshalSpec **mspecs;
1869 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1870 mono_method_get_marshal_info (method, mspecs);
1873 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1874 if (!mono_error_ok (&error)) {
1875 mono_error_set_pending_exception (&error);
1880 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1882 mono_metadata_free_marshal_spec (mspecs [i]);
1889 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1891 MonoClass *parent = field->field->parent;
1892 if (!parent->size_inited)
1893 mono_class_init (parent);
1894 mono_class_setup_fields_locking (parent);
1896 return field->field->offset - sizeof (MonoObject);
1899 ICALL_EXPORT MonoReflectionType*
1900 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1903 MonoReflectionType *ret;
1906 parent = declaring? field->field->parent: field->klass;
1908 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1909 mono_error_set_pending_exception (&error);
1915 ICALL_EXPORT MonoObject *
1916 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1919 MonoClass *fklass = field->klass;
1920 MonoClassField *cf = field->field;
1921 MonoDomain *domain = mono_object_domain (field);
1923 if (fklass->image->assembly->ref_only) {
1924 mono_set_pending_exception (mono_get_exception_invalid_operation (
1925 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1929 if (mono_security_core_clr_enabled () &&
1930 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1931 mono_error_set_pending_exception (&error);
1935 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1936 mono_error_set_pending_exception (&error);
1941 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1944 MonoClassField *cf = field->field;
1948 if (field->klass->image->assembly->ref_only) {
1949 mono_set_pending_exception (mono_get_exception_invalid_operation (
1950 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1954 if (mono_security_core_clr_enabled () &&
1955 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1956 mono_error_set_pending_exception (&error);
1960 type = mono_field_get_type_checked (cf, &error);
1961 if (!mono_error_ok (&error)) {
1962 mono_error_set_pending_exception (&error);
1966 v = (gchar *) value;
1968 switch (type->type) {
1971 case MONO_TYPE_BOOLEAN:
1974 case MONO_TYPE_CHAR:
1983 case MONO_TYPE_VALUETYPE:
1986 v += sizeof (MonoObject);
1988 case MONO_TYPE_STRING:
1989 case MONO_TYPE_OBJECT:
1990 case MONO_TYPE_CLASS:
1991 case MONO_TYPE_ARRAY:
1992 case MONO_TYPE_SZARRAY:
1995 case MONO_TYPE_GENERICINST: {
1996 MonoGenericClass *gclass = type->data.generic_class;
1997 g_assert (!gclass->context.class_inst->is_open);
1999 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
2000 MonoClass *nklass = mono_class_from_mono_type (type);
2001 MonoObject *nullable;
2004 * Convert the boxed vtype into a Nullable structure.
2005 * This is complicated by the fact that Nullables have
2006 * a variable structure.
2008 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2009 if (!mono_error_ok (&error)) {
2010 mono_error_set_pending_exception (&error);
2014 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2016 v = (gchar *)mono_object_unbox (nullable);
2019 if (gclass->container_class->valuetype && (v != NULL))
2020 v += sizeof (MonoObject);
2024 g_error ("type 0x%x not handled in "
2025 "ves_icall_FieldInfo_SetValueInternal", type->type);
2030 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2031 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2032 if (!is_ok (&error)) {
2033 mono_error_set_pending_exception (&error);
2036 if (!vtable->initialized) {
2037 if (!mono_runtime_class_init_full (vtable, &error)) {
2038 mono_error_set_pending_exception (&error);
2042 mono_field_static_set_value (vtable, cf, v);
2044 mono_field_set_value (obj, cf, v);
2049 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2058 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2059 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2063 if (MONO_TYPE_IS_REFERENCE (f->type))
2064 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2066 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2069 ICALL_EXPORT MonoObject *
2070 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2072 MonoObject *o = NULL;
2073 MonoClassField *field = rfield->field;
2075 MonoDomain *domain = mono_object_domain (rfield);
2077 MonoTypeEnum def_type;
2078 const char *def_value;
2082 mono_class_init (field->parent);
2084 t = mono_field_get_type_checked (field, &error);
2085 if (!mono_error_ok (&error)) {
2086 mono_error_set_pending_exception (&error);
2090 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2091 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2095 if (image_is_dynamic (field->parent->image)) {
2096 MonoClass *klass = field->parent;
2097 int fidx = field - klass->fields;
2099 g_assert (fidx >= 0 && fidx < klass->field.count);
2100 g_assert (klass->ext);
2101 g_assert (klass->ext->field_def_values);
2102 def_type = klass->ext->field_def_values [fidx].def_type;
2103 def_value = klass->ext->field_def_values [fidx].data;
2104 if (def_type == MONO_TYPE_END) {
2105 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2109 def_value = mono_class_get_field_default_value (field, &def_type);
2110 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2112 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2117 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2121 case MONO_TYPE_BOOLEAN:
2124 case MONO_TYPE_CHAR:
2132 case MONO_TYPE_R8: {
2135 /* boxed value type */
2136 t = g_new0 (MonoType, 1);
2138 klass = mono_class_from_mono_type (t);
2140 o = mono_object_new_checked (domain, klass, &error);
2141 if (!mono_error_ok (&error)) {
2142 mono_error_set_pending_exception (&error);
2145 v = ((gchar *) o) + sizeof (MonoObject);
2146 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2147 if (mono_error_set_pending_exception (&error))
2151 case MONO_TYPE_STRING:
2152 case MONO_TYPE_CLASS:
2153 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2154 if (mono_error_set_pending_exception (&error))
2158 g_assert_not_reached ();
2164 ICALL_EXPORT MonoReflectionType*
2165 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2168 MonoReflectionType *ret;
2171 type = mono_field_get_type_checked (ref_field->field, &error);
2172 if (!mono_error_ok (&error)) {
2173 mono_error_set_pending_exception (&error);
2177 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2178 if (!mono_error_ok (&error)) {
2179 mono_error_set_pending_exception (&error);
2186 /* From MonoProperty.cs */
2188 PInfo_Attributes = 1,
2189 PInfo_GetMethod = 1 << 1,
2190 PInfo_SetMethod = 1 << 2,
2191 PInfo_ReflectedType = 1 << 3,
2192 PInfo_DeclaringType = 1 << 4,
2197 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2200 MonoReflectionType *rt;
2201 MonoReflectionMethod *rm;
2202 MonoDomain *domain = mono_object_domain (property);
2203 const MonoProperty *pproperty = property->property;
2205 if ((req_info & PInfo_ReflectedType) != 0) {
2206 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2207 if (mono_error_set_pending_exception (&error))
2210 MONO_STRUCT_SETREF (info, parent, rt);
2212 if ((req_info & PInfo_DeclaringType) != 0) {
2213 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2214 if (mono_error_set_pending_exception (&error))
2217 MONO_STRUCT_SETREF (info, declaring_type, rt);
2220 if ((req_info & PInfo_Name) != 0)
2221 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2223 if ((req_info & PInfo_Attributes) != 0)
2224 info->attrs = pproperty->attrs;
2226 if ((req_info & PInfo_GetMethod) != 0) {
2227 if (pproperty->get &&
2228 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2229 pproperty->get->klass == property->klass)) {
2230 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2231 if (mono_error_set_pending_exception (&error))
2237 MONO_STRUCT_SETREF (info, get, rm);
2239 if ((req_info & PInfo_SetMethod) != 0) {
2240 if (pproperty->set &&
2241 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2242 pproperty->set->klass == property->klass)) {
2243 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2244 if (mono_error_set_pending_exception (&error))
2250 MONO_STRUCT_SETREF (info, set, rm);
2253 * There may be other methods defined for properties, though, it seems they are not exposed
2254 * in the reflection API
2259 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2262 MonoReflectionType *rt;
2263 MonoReflectionMethod *rm;
2264 MonoDomain *domain = mono_object_domain (event);
2266 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2267 if (mono_error_set_pending_exception (&error))
2270 MONO_STRUCT_SETREF (info, reflected_type, rt);
2272 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2273 if (mono_error_set_pending_exception (&error))
2276 MONO_STRUCT_SETREF (info, declaring_type, rt);
2278 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2279 info->attrs = event->event->attrs;
2281 if (event->event->add) {
2282 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2283 if (mono_error_set_pending_exception (&error))
2289 MONO_STRUCT_SETREF (info, add_method, rm);
2291 if (event->event->remove) {
2292 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2293 if (mono_error_set_pending_exception (&error))
2299 MONO_STRUCT_SETREF (info, remove_method, rm);
2301 if (event->event->raise) {
2302 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2303 if (mono_error_set_pending_exception (&error))
2309 MONO_STRUCT_SETREF (info, raise_method, rm);
2311 #ifndef MONO_SMALL_CONFIG
2312 if (event->event->other) {
2314 while (event->event->other [n])
2316 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2317 if (mono_error_set_pending_exception (&error))
2319 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2321 for (i = 0; i < n; i++) {
2322 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2323 if (mono_error_set_pending_exception (&error))
2325 mono_array_setref (info->other_methods, i, rm);
2332 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2337 mono_class_setup_interfaces (klass, error);
2338 if (!mono_error_ok (error))
2341 for (i = 0; i < klass->interface_count; i++) {
2342 ic = klass->interfaces [i];
2343 g_hash_table_insert (ifaces, ic, ic);
2345 collect_interfaces (ic, ifaces, error);
2346 if (!mono_error_ok (error))
2352 MonoArray *iface_array;
2353 MonoGenericContext *context;
2357 } FillIfaceArrayData;
2360 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2362 MonoReflectionType *rt;
2363 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2364 MonoClass *ic = (MonoClass *)key;
2365 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2367 if (!mono_error_ok (data->error))
2370 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2371 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2372 if (!mono_error_ok (data->error))
2376 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2377 if (!mono_error_ok (data->error))
2380 mono_array_setref (data->iface_array, data->next_idx++, rt);
2383 mono_metadata_free_type (inflated);
2387 get_interfaces_hash (gconstpointer v1)
2389 MonoClass *k = (MonoClass*)v1;
2391 return k->type_token;
2394 ICALL_EXPORT MonoArray*
2395 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2398 MonoClass *klass = mono_class_from_mono_type (type->type);
2400 FillIfaceArrayData data = { 0 };
2403 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2405 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2406 data.context = mono_class_get_context (klass);
2407 klass = klass->generic_class->container_class;
2410 for (parent = klass; parent; parent = parent->parent) {
2411 mono_class_setup_interfaces (parent, &error);
2412 if (!mono_error_ok (&error))
2414 collect_interfaces (parent, iface_hash, &error);
2415 if (!mono_error_ok (&error))
2419 data.error = &error;
2420 data.domain = mono_object_domain (type);
2422 len = g_hash_table_size (iface_hash);
2424 g_hash_table_destroy (iface_hash);
2425 if (!data.domain->empty_types) {
2426 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2427 if (!is_ok (&error))
2430 return data.domain->empty_types;
2433 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2434 if (!is_ok (&error))
2436 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2437 if (!mono_error_ok (&error))
2440 g_hash_table_destroy (iface_hash);
2441 return data.iface_array;
2444 g_hash_table_destroy (iface_hash);
2445 mono_error_set_pending_exception (&error);
2450 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2452 gboolean variance_used;
2453 MonoClass *klass = mono_class_from_mono_type (type->type);
2454 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2455 MonoReflectionMethod *member;
2458 int i = 0, len, ioffset;
2462 mono_class_init_checked (klass, &error);
2463 if (mono_error_set_pending_exception (&error))
2465 mono_class_init_checked (iclass, &error);
2466 if (mono_error_set_pending_exception (&error))
2469 mono_class_setup_vtable (klass);
2471 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2475 len = mono_class_num_methods (iclass);
2476 domain = mono_object_domain (type);
2477 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2478 if (mono_error_set_pending_exception (&error))
2480 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2481 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2482 if (mono_error_set_pending_exception (&error))
2484 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2486 while ((method = mono_class_get_methods (iclass, &iter))) {
2487 member = mono_method_get_object_checked (domain, method, iclass, &error);
2488 if (mono_error_set_pending_exception (&error))
2490 mono_array_setref (*methods, i, member);
2491 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2492 if (mono_error_set_pending_exception (&error))
2494 mono_array_setref (*targets, i, member);
2501 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2504 MonoClass *klass = mono_class_from_mono_type (type->type);
2506 mono_class_init_checked (klass, &error);
2507 if (mono_error_set_pending_exception (&error))
2510 if (image_is_dynamic (klass->image)) {
2511 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2512 *packing = tb->packing_size;
2513 *size = tb->class_size;
2515 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2519 ICALL_EXPORT MonoReflectionType*
2520 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2523 MonoReflectionType *ret;
2526 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2527 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2528 mono_error_set_pending_exception (&error);
2532 klass = mono_class_from_mono_type (type->type);
2533 mono_class_init_checked (klass, &error);
2534 if (mono_error_set_pending_exception (&error))
2538 // GetElementType should only return a type for:
2539 // Array Pointer PassedByRef
2540 if (type->type->byref)
2541 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2542 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2543 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2544 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2545 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2549 mono_error_set_pending_exception (&error);
2554 ICALL_EXPORT MonoReflectionType*
2555 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2558 MonoReflectionType *ret;
2560 if (type->type->byref)
2563 MonoClass *klass = mono_class_from_mono_type (type->type);
2567 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2568 mono_error_set_pending_exception (&error);
2573 ICALL_EXPORT MonoBoolean
2574 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2576 return type->type->type == MONO_TYPE_PTR;
2579 ICALL_EXPORT MonoBoolean
2580 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2582 return (!type->type->byref && (((type->type->type >= MONO_TYPE_BOOLEAN) && (type->type->type <= MONO_TYPE_R8)) || (type->type->type == MONO_TYPE_I) || (type->type->type == MONO_TYPE_U)));
2585 ICALL_EXPORT MonoBoolean
2586 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2588 return type->type->byref;
2591 ICALL_EXPORT MonoBoolean
2592 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2595 MonoClass *klass = mono_class_from_mono_type (type->type);
2596 mono_class_init_checked (klass, &error);
2597 if (mono_error_set_pending_exception (&error))
2600 return mono_class_is_com_object (klass);
2603 ICALL_EXPORT guint32
2604 ves_icall_reflection_get_token (MonoObject* obj)
2607 guint32 result = mono_reflection_get_token_checked (obj, &error);
2608 mono_error_set_pending_exception (&error);
2612 ICALL_EXPORT MonoReflectionModule*
2613 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2616 MonoReflectionModule *result = NULL;
2617 MonoClass *klass = mono_class_from_mono_type (type->type);
2618 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2619 mono_error_set_pending_exception (&error);
2623 ICALL_EXPORT MonoReflectionAssembly*
2624 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2627 MonoDomain *domain = mono_domain_get ();
2628 MonoClass *klass = mono_class_from_mono_type (type->type);
2629 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2630 mono_error_set_pending_exception (&error);
2634 ICALL_EXPORT MonoReflectionType*
2635 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2638 MonoReflectionType *ret;
2639 MonoDomain *domain = mono_domain_get ();
2642 if (type->type->byref)
2644 if (type->type->type == MONO_TYPE_VAR) {
2645 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2646 klass = param ? param->owner.klass : NULL;
2647 } else if (type->type->type == MONO_TYPE_MVAR) {
2648 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2649 klass = param ? param->owner.method->klass : NULL;
2651 klass = mono_class_from_mono_type (type->type)->nested_in;
2657 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2658 mono_error_set_pending_exception (&error);
2663 ICALL_EXPORT MonoString*
2664 ves_icall_RuntimeType_get_Name (MonoReflectionType *type)
2666 MonoDomain *domain = mono_domain_get ();
2667 MonoClass *klass = mono_class_from_mono_type (type->type);
2669 if (type->type->byref) {
2670 char *n = g_strdup_printf ("%s&", klass->name);
2671 MonoString *res = mono_string_new (domain, n);
2677 return mono_string_new (domain, klass->name);
2681 ICALL_EXPORT MonoString*
2682 ves_icall_RuntimeType_get_Namespace (MonoReflectionType *type)
2684 MonoDomain *domain = mono_domain_get ();
2685 MonoClass *klass = mono_class_from_mono_type (type->type);
2687 while (klass->nested_in)
2688 klass = klass->nested_in;
2690 if (klass->name_space [0] == '\0')
2693 return mono_string_new (domain, klass->name_space);
2697 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2701 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2702 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2706 klass = mono_class_from_mono_type (type->type);
2712 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2714 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2717 ICALL_EXPORT MonoArray*
2718 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2721 MonoReflectionType *rt;
2723 MonoClass *klass, *pklass;
2724 MonoDomain *domain = mono_object_domain (type);
2727 klass = mono_class_from_mono_type (type->type);
2729 if (klass->generic_container) {
2730 MonoGenericContainer *container = klass->generic_container;
2731 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2732 if (mono_error_set_pending_exception (&error))
2734 for (i = 0; i < container->type_argc; ++i) {
2735 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2737 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2738 if (mono_error_set_pending_exception (&error))
2741 mono_array_setref (res, i, rt);
2743 } else if (klass->generic_class) {
2744 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2745 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2746 if (mono_error_set_pending_exception (&error))
2748 for (i = 0; i < inst->type_argc; ++i) {
2749 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2750 if (mono_error_set_pending_exception (&error))
2753 mono_array_setref (res, i, rt);
2761 ICALL_EXPORT gboolean
2762 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2766 if (!IS_MONOTYPE (type))
2769 if (type->type->byref)
2772 klass = mono_class_from_mono_type (type->type);
2773 return klass->generic_container != NULL;
2776 ICALL_EXPORT MonoReflectionType*
2777 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2780 MonoReflectionType *ret;
2783 if (type->type->byref)
2786 klass = mono_class_from_mono_type (type->type);
2788 if (klass->generic_container) {
2789 return type; /* check this one */
2791 if (klass->generic_class) {
2792 MonoClass *generic_class = klass->generic_class->container_class;
2795 tb = mono_class_get_ref_info (generic_class);
2797 if (generic_class->wastypebuilder && tb)
2798 return (MonoReflectionType *)tb;
2800 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2801 mono_error_set_pending_exception (&error);
2809 ICALL_EXPORT MonoReflectionType*
2810 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2813 MonoReflectionType *ret;
2815 MonoType *geninst, **types;
2818 g_assert (IS_MONOTYPE (type));
2819 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2820 if (mono_error_set_pending_exception (&error))
2823 count = mono_array_length (type_array);
2824 types = g_new0 (MonoType *, count);
2826 for (i = 0; i < count; i++) {
2827 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2828 types [i] = t->type;
2831 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2834 mono_error_set_pending_exception (&error);
2838 klass = mono_class_from_mono_type (geninst);
2840 /*we might inflate to the GTD*/
2841 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2842 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2846 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2847 mono_error_set_pending_exception (&error);
2852 ICALL_EXPORT gboolean
2853 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2857 if (!IS_MONOTYPE (type))
2860 if (type->type->byref)
2863 klass = mono_class_from_mono_type (type->type);
2864 return klass->generic_class != NULL || klass->generic_container != NULL;
2868 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2870 if (!IS_MONOTYPE (type))
2873 if (is_generic_parameter (type->type))
2874 return mono_type_get_generic_param_num (type->type);
2878 ICALL_EXPORT GenericParameterAttributes
2879 ves_icall_RuntimeType_GetGenericParameterAttributes (MonoReflectionType *type)
2881 g_assert (IS_MONOTYPE (type));
2882 g_assert (is_generic_parameter (type->type));
2883 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2886 ICALL_EXPORT MonoArray *
2887 ves_icall_RuntimeType_GetGenericParameterConstraints (MonoReflectionType *type)
2890 MonoReflectionType *rt;
2891 MonoGenericParamInfo *param_info;
2897 g_assert (IS_MONOTYPE (type));
2899 domain = mono_object_domain (type);
2900 param_info = mono_generic_param_info (type->type->data.generic_param);
2901 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2904 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, &error);
2905 if (mono_error_set_pending_exception (&error))
2907 for (i = 0; i < count; i++) {
2908 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2909 if (mono_error_set_pending_exception (&error))
2912 mono_array_setref (res, i, rt);
2919 ICALL_EXPORT MonoBoolean
2920 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2922 return is_generic_parameter (type->type);
2925 ICALL_EXPORT MonoBoolean
2926 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2928 return is_generic_parameter (tb->type.type);
2932 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2933 MonoReflectionType *t)
2935 enumtype->type = t->type;
2938 ICALL_EXPORT MonoReflectionMethod*
2939 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2940 MonoReflectionMethod* generic)
2947 MonoReflectionMethod *ret = NULL;
2949 domain = ((MonoObject *)type)->vtable->domain;
2951 klass = mono_class_from_mono_type (type->type);
2952 mono_class_init_checked (klass, &error);
2953 if (mono_error_set_pending_exception (&error))
2957 while ((method = mono_class_get_methods (klass, &iter))) {
2958 if (method->token == generic->method->token) {
2959 ret = mono_method_get_object_checked (domain, method, klass, &error);
2960 if (mono_error_set_pending_exception (&error))
2968 ICALL_EXPORT MonoReflectionMethod *
2969 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
2972 MonoType *type = ref_type->type;
2974 MonoReflectionMethod *ret = NULL;
2976 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2977 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2980 if (type->type == MONO_TYPE_VAR)
2983 method = mono_type_get_generic_param_owner (type)->owner.method;
2986 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2987 if (!mono_error_ok (&error))
2988 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2992 ICALL_EXPORT MonoBoolean
2993 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2995 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2999 ICALL_EXPORT MonoBoolean
3000 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
3002 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3007 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
3009 MonoDomain *domain = mono_domain_get ();
3010 MonoImage *image = method->method->klass->image;
3011 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
3012 MonoTableInfo *tables = image->tables;
3013 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
3014 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
3015 guint32 im_cols [MONO_IMPLMAP_SIZE];
3016 guint32 scope_token;
3017 const char *import = NULL;
3018 const char *scope = NULL;
3020 if (image_is_dynamic (image)) {
3021 MonoReflectionMethodAux *method_aux =
3022 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
3024 import = method_aux->dllentry;
3025 scope = method_aux->dll;
3028 if (!import || !scope) {
3029 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
3034 if (piinfo->implmap_idx) {
3035 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
3037 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
3038 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
3039 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
3040 scope = mono_metadata_string_heap (image, scope_token);
3044 *flags = piinfo->piflags;
3045 *entry_point = mono_string_new (domain, import);
3046 *dll_name = mono_string_new (domain, scope);
3049 ICALL_EXPORT MonoReflectionMethod *
3050 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3052 MonoMethodInflated *imethod;
3054 MonoReflectionMethod *ret = NULL;
3057 if (method->method->is_generic)
3060 if (!method->method->is_inflated)
3063 imethod = (MonoMethodInflated *) method->method;
3065 result = imethod->declaring;
3066 /* Not a generic method. */
3067 if (!result->is_generic)
3070 if (image_is_dynamic (method->method->klass->image)) {
3071 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3072 MonoReflectionMethod *res;
3075 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3076 * the dynamic case as well ?
3078 mono_image_lock ((MonoImage*)image);
3079 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3080 mono_image_unlock ((MonoImage*)image);
3086 if (imethod->context.class_inst) {
3087 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3088 /*Generic methods gets the context of the GTD.*/
3089 if (mono_class_get_context (klass)) {
3090 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3091 if (!mono_error_ok (&error))
3096 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3098 if (!mono_error_ok (&error))
3099 mono_error_set_pending_exception (&error);
3103 ICALL_EXPORT gboolean
3104 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3106 return mono_method_signature (method->method)->generic_param_count != 0;
3109 ICALL_EXPORT gboolean
3110 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3112 return method->method->is_generic;
3115 ICALL_EXPORT MonoArray*
3116 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3119 MonoReflectionType *rt;
3124 domain = mono_object_domain (method);
3126 if (method->method->is_inflated) {
3127 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3130 count = inst->type_argc;
3131 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3132 if (mono_error_set_pending_exception (&error))
3135 for (i = 0; i < count; i++) {
3136 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3137 if (mono_error_set_pending_exception (&error))
3140 mono_array_setref (res, i, rt);
3147 count = mono_method_signature (method->method)->generic_param_count;
3148 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3149 if (mono_error_set_pending_exception (&error))
3152 for (i = 0; i < count; i++) {
3153 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3154 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3155 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3157 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3158 if (mono_error_set_pending_exception (&error))
3161 mono_array_setref (res, i, rt);
3167 ICALL_EXPORT MonoObject *
3168 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3172 * Invoke from reflection is supposed to always be a virtual call (the API
3173 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3174 * greater flexibility.
3176 MonoMethod *m = method->method;
3177 MonoMethodSignature *sig = mono_method_signature (m);
3180 void *obj = this_arg;
3184 if (mono_security_core_clr_enabled () &&
3185 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3186 mono_error_set_pending_exception (&error);
3190 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3191 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3192 mono_error_cleanup (&error); /* FIXME does this make sense? */
3193 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3198 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3199 if (!is_ok (&error)) {
3200 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3203 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3204 char *target_name = mono_type_get_full_name (m->klass);
3205 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3206 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3208 g_free (target_name);
3212 m = mono_object_get_virtual_method (this_arg, m);
3213 /* must pass the pointer to the value for valuetype methods */
3214 if (m->klass->valuetype)
3215 obj = mono_object_unbox (this_arg);
3216 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3217 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3222 if (sig->ret->byref) {
3223 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "Cannot invoke method returning ByRef type via reflection"));
3227 pcount = params? mono_array_length (params): 0;
3228 if (pcount != sig->param_count) {
3229 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3233 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3234 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class."));
3238 image = m->klass->image;
3239 if (image->assembly->ref_only) {
3240 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api."));
3244 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3245 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3249 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3253 intptr_t *lower_bounds;
3254 pcount = mono_array_length (params);
3255 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3256 /* Note: the synthetized array .ctors have int32 as argument type */
3257 for (i = 0; i < pcount; ++i)
3258 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3260 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3261 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3262 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3263 if (!mono_error_ok (&error)) {
3264 mono_error_set_pending_exception (&error);
3268 for (i = 0; i < mono_array_length (arr); ++i) {
3269 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3270 if (!mono_error_ok (&error)) {
3271 mono_error_set_pending_exception (&error);
3274 mono_array_setref_fast (arr, i, subarray);
3276 return (MonoObject*)arr;
3279 if (m->klass->rank == pcount) {
3280 /* Only lengths provided. */
3281 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3282 if (!mono_error_ok (&error)) {
3283 mono_error_set_pending_exception (&error);
3287 return (MonoObject*)arr;
3289 g_assert (pcount == (m->klass->rank * 2));
3290 /* The arguments are lower-bound-length pairs */
3291 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3293 for (i = 0; i < pcount / 2; ++i) {
3294 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3295 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3298 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3299 if (!mono_error_ok (&error)) {
3300 mono_error_set_pending_exception (&error);
3304 return (MonoObject*)arr;
3307 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3308 mono_error_set_pending_exception (&error);
3312 #ifndef DISABLE_REMOTING
3313 ICALL_EXPORT MonoObject *
3314 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3317 MonoDomain *domain = mono_object_domain (method);
3318 MonoMethod *m = method->method;
3319 MonoMethodSignature *sig = mono_method_signature (m);
3320 MonoArray *out_args;
3322 int i, j, outarg_count = 0;
3324 if (m->klass == mono_defaults.object_class) {
3325 if (!strcmp (m->name, "FieldGetter")) {
3326 MonoClass *k = this_arg->vtable->klass;
3330 /* If this is a proxy, then it must be a CBO */
3331 if (k == mono_defaults.transparent_proxy_class) {
3332 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3333 this_arg = tp->rp->unwrapped_server;
3334 g_assert (this_arg);
3335 k = this_arg->vtable->klass;
3338 name = mono_array_get (params, MonoString *, 1);
3339 str = mono_string_to_utf8_checked (name, &error);
3340 if (mono_error_set_pending_exception (&error))
3344 MonoClassField* field = mono_class_get_field_from_name (k, str);
3347 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3348 if (field_klass->valuetype) {
3349 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3350 if (mono_error_set_pending_exception (&error))
3353 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3355 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3356 if (mono_error_set_pending_exception (&error))
3358 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3359 mono_array_setref (out_args, 0, result);
3366 g_assert_not_reached ();
3368 } else if (!strcmp (m->name, "FieldSetter")) {
3369 MonoClass *k = this_arg->vtable->klass;
3375 /* If this is a proxy, then it must be a CBO */
3376 if (k == mono_defaults.transparent_proxy_class) {
3377 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3378 this_arg = tp->rp->unwrapped_server;
3379 g_assert (this_arg);
3380 k = this_arg->vtable->klass;
3383 name = mono_array_get (params, MonoString *, 1);
3384 str = mono_string_to_utf8_checked (name, &error);
3385 if (mono_error_set_pending_exception (&error))
3389 MonoClassField* field = mono_class_get_field_from_name (k, str);
3392 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3393 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3395 if (field_klass->valuetype) {
3396 size = mono_type_size (field->type, &align);
3397 g_assert (size == mono_class_value_size (field_klass, NULL));
3398 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3400 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3403 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3404 if (mono_error_set_pending_exception (&error))
3406 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3415 g_assert_not_reached ();
3420 for (i = 0; i < mono_array_length (params); i++) {
3421 if (sig->params [i]->byref)
3425 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3426 if (mono_error_set_pending_exception (&error))
3429 /* handle constructors only for objects already allocated */
3430 if (!strcmp (method->method->name, ".ctor"))
3431 g_assert (this_arg);
3433 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3434 g_assert (!method->method->klass->valuetype);
3435 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3436 if (mono_error_set_pending_exception (&error))
3439 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3440 if (sig->params [i]->byref) {
3442 arg = mono_array_get (params, gpointer, i);
3443 mono_array_setref (out_args, j, arg);
3448 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3455 read_enum_value (const char *mem, int type)
3458 case MONO_TYPE_BOOLEAN:
3460 return *(guint8*)mem;
3462 return *(gint8*)mem;
3463 case MONO_TYPE_CHAR:
3465 return read16 (mem);
3467 return (gint16) read16 (mem);
3469 return read32 (mem);
3471 return (gint32) read32 (mem);
3474 return read64 (mem);
3476 g_assert_not_reached ();
3482 write_enum_value (char *mem, int type, guint64 value)
3486 case MONO_TYPE_I1: {
3487 guint8 *p = (guint8*)mem;
3493 case MONO_TYPE_CHAR: {
3494 guint16 *p = (guint16 *)mem;
3499 case MONO_TYPE_I4: {
3500 guint32 *p = (guint32 *)mem;
3505 case MONO_TYPE_I8: {
3506 guint64 *p = (guint64 *)mem;
3511 g_assert_not_reached ();
3516 ICALL_EXPORT MonoObject *
3517 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3525 domain = mono_object_domain (enumType);
3526 enumc = mono_class_from_mono_type (enumType->type);
3528 mono_class_init_checked (enumc, &error);
3529 if (mono_error_set_pending_exception (&error))
3532 etype = mono_class_enum_basetype (enumc);
3534 res = mono_object_new_checked (domain, enumc, &error);
3535 if (mono_error_set_pending_exception (&error))
3537 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3542 ICALL_EXPORT MonoBoolean
3543 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3545 int size = mono_class_value_size (a->vtable->klass, NULL);
3546 guint64 a_val = 0, b_val = 0;
3548 memcpy (&a_val, mono_object_unbox (a), size);
3549 memcpy (&b_val, mono_object_unbox (b), size);
3551 return (a_val & b_val) == b_val;
3554 ICALL_EXPORT MonoObject *
3555 ves_icall_System_Enum_get_value (MonoObject *eobj)
3567 g_assert (eobj->vtable->klass->enumtype);
3569 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3570 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3571 if (mono_error_set_pending_exception (&error))
3573 dst = (char *)res + sizeof (MonoObject);
3574 src = (char *)eobj + sizeof (MonoObject);
3575 size = mono_class_value_size (enumc, NULL);
3577 memcpy (dst, src, size);
3582 ICALL_EXPORT MonoReflectionType *
3583 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3586 MonoReflectionType *ret;
3590 klass = mono_class_from_mono_type (type->type);
3591 mono_class_init_checked (klass, &error);
3592 if (mono_error_set_pending_exception (&error))
3595 etype = mono_class_enum_basetype (klass);
3597 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3601 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3602 mono_error_set_pending_exception (&error);
3608 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3610 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3611 gpointer odata = (char *)other + sizeof (MonoObject);
3612 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3613 g_assert (basetype);
3618 if (eobj->vtable->klass != other->vtable->klass)
3621 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3622 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3623 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3626 return me > other ? 1 : -1; \
3629 switch (basetype->type) {
3631 COMPARE_ENUM_VALUES (guint8);
3633 COMPARE_ENUM_VALUES (gint8);
3634 case MONO_TYPE_CHAR:
3636 COMPARE_ENUM_VALUES (guint16);
3638 COMPARE_ENUM_VALUES (gint16);
3640 COMPARE_ENUM_VALUES (guint32);
3642 COMPARE_ENUM_VALUES (gint32);
3644 COMPARE_ENUM_VALUES (guint64);
3646 COMPARE_ENUM_VALUES (gint64);
3650 #undef COMPARE_ENUM_VALUES
3651 /* indicates that the enum was of an unsupported unerlying type */
3656 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3658 gpointer data = (char *)eobj + sizeof (MonoObject);
3659 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3660 g_assert (basetype);
3662 switch (basetype->type) {
3663 case MONO_TYPE_I1: {
3664 gint8 value = *((gint8*)data);
3665 return ((int)value ^ (int)value << 8);
3668 return *((guint8*)data);
3669 case MONO_TYPE_CHAR:
3671 return *((guint16*)data);
3673 case MONO_TYPE_I2: {
3674 gint16 value = *((gint16*)data);
3675 return ((int)(guint16)value | (((int)value) << 16));
3678 return *((guint32*)data);
3680 return *((gint32*)data);
3682 case MONO_TYPE_I8: {
3683 gint64 value = *((gint64*)data);
3684 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3687 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3692 ICALL_EXPORT MonoBoolean
3693 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3696 MonoDomain *domain = mono_object_domain (type);
3697 MonoClass *enumc = mono_class_from_mono_type (type->type);
3698 guint j = 0, nvalues;
3700 MonoClassField *field;
3702 guint64 field_value, previous_value = 0;
3703 gboolean sorted = TRUE;
3705 mono_class_init_checked (enumc, &error);
3706 if (mono_error_set_pending_exception (&error))
3710 if (!enumc->enumtype) {
3711 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3715 base_type = mono_class_enum_basetype (enumc)->type;
3717 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3718 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3719 if (mono_error_set_pending_exception (&error))
3721 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3722 if (mono_error_set_pending_exception (&error))
3726 while ((field = mono_class_get_fields (enumc, &iter))) {
3728 MonoTypeEnum def_type;
3730 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3732 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3734 if (mono_field_is_deleted (field))
3736 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3738 p = mono_class_get_field_default_value (field, &def_type);
3739 /* len = */ mono_metadata_decode_blob_size (p, &p);
3741 field_value = read_enum_value (p, base_type);
3742 mono_array_set (*values, guint64, j, field_value);
3744 if (previous_value > field_value)
3747 previous_value = field_value;
3755 BFLAGS_IgnoreCase = 1,
3756 BFLAGS_DeclaredOnly = 2,
3757 BFLAGS_Instance = 4,
3759 BFLAGS_Public = 0x10,
3760 BFLAGS_NonPublic = 0x20,
3761 BFLAGS_FlattenHierarchy = 0x40,
3762 BFLAGS_InvokeMethod = 0x100,
3763 BFLAGS_CreateInstance = 0x200,
3764 BFLAGS_GetField = 0x400,
3765 BFLAGS_SetField = 0x800,
3766 BFLAGS_GetProperty = 0x1000,
3767 BFLAGS_SetProperty = 0x2000,
3768 BFLAGS_ExactBinding = 0x10000,
3769 BFLAGS_SuppressChangeType = 0x20000,
3770 BFLAGS_OptionalParamBinding = 0x40000
3773 ICALL_EXPORT MonoArray*
3774 ves_icall_RuntimeType_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3778 MonoClass *startklass, *klass, *refklass;
3783 char *utf8_name = NULL;
3784 int (*compare_func) (const char *s1, const char *s2) = NULL;
3785 MonoClassField *field;
3786 MonoPtrArray tmp_array;
3788 domain = ((MonoObject *)type)->vtable->domain;
3789 if (type->type->byref) {
3790 MonoArray *result = mono_array_new_checked (domain, mono_defaults.field_info_class, 0, &error);
3791 mono_error_set_pending_exception (&error);
3795 klass = startklass = mono_class_from_mono_type (type->type);
3796 refklass = mono_class_from_mono_type (reftype->type);
3798 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3801 if (mono_class_has_failure (klass)) {
3802 mono_ptr_array_destroy (tmp_array);
3803 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3808 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3809 guint32 flags = mono_field_get_flags (field);
3811 if (mono_field_is_deleted_with_flags (field, flags))
3813 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3814 if (bflags & BFLAGS_Public)
3816 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3817 if (bflags & BFLAGS_NonPublic) {
3824 if (flags & FIELD_ATTRIBUTE_STATIC) {
3825 if (bflags & BFLAGS_Static)
3826 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3829 if (bflags & BFLAGS_Instance)
3837 if (utf8_name == NULL) {
3838 utf8_name = mono_string_to_utf8_checked (name, &error);
3839 if (!is_ok (&error))
3841 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3844 if (compare_func (mono_field_get_name (field), utf8_name))
3848 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3849 if (!mono_error_ok (&error))
3851 mono_ptr_array_append (tmp_array, member);
3853 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3856 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array), &error);
3857 if (!is_ok (&error))
3860 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3861 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3863 mono_ptr_array_destroy (tmp_array);
3865 if (utf8_name != NULL)
3870 mono_ptr_array_destroy (tmp_array);
3871 mono_error_set_pending_exception (&error);
3876 method_nonpublic (MonoMethod* method, gboolean start_klass)
3878 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3879 case METHOD_ATTRIBUTE_ASSEM:
3880 return (start_klass || mono_defaults.generic_ilist_class);
3881 case METHOD_ATTRIBUTE_PRIVATE:
3883 case METHOD_ATTRIBUTE_PUBLIC:
3891 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3894 MonoClass *startklass;
3898 /*FIXME, use MonoBitSet*/
3899 guint32 method_slots_default [8];
3900 guint32 *method_slots = NULL;
3901 int (*compare_func) (const char *s1, const char *s2) = NULL;
3903 array = g_ptr_array_new ();
3908 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3910 /* An optimization for calls made from Delegate:CreateDelegate () */
3911 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3912 method = mono_get_delegate_invoke (klass);
3915 g_ptr_array_add (array, method);
3919 mono_class_setup_methods (klass);
3920 mono_class_setup_vtable (klass);
3921 if (mono_class_has_failure (klass))
3924 if (is_generic_parameter (&klass->byval_arg))
3925 nslots = mono_class_get_vtable_size (klass->parent);
3927 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3928 if (nslots >= sizeof (method_slots_default) * 8) {
3929 method_slots = g_new0 (guint32, nslots / 32 + 1);
3931 method_slots = method_slots_default;
3932 memset (method_slots, 0, sizeof (method_slots_default));
3935 mono_class_setup_methods (klass);
3936 mono_class_setup_vtable (klass);
3937 if (mono_class_has_failure (klass))
3941 while ((method = mono_class_get_methods (klass, &iter))) {
3943 if (method->slot != -1) {
3944 g_assert (method->slot < nslots);
3945 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3947 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3948 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3951 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3953 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3954 if (bflags & BFLAGS_Public)
3956 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3962 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3963 if (bflags & BFLAGS_Static)
3964 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3967 if (bflags & BFLAGS_Instance)
3975 if (compare_func (name, method->name))
3980 g_ptr_array_add (array, method);
3982 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3984 if (method_slots != method_slots_default)
3985 g_free (method_slots);
3990 if (method_slots != method_slots_default)
3991 g_free (method_slots);
3992 g_ptr_array_free (array, TRUE);
3994 if (mono_class_has_failure (klass)) {
3995 *ex = mono_class_get_exception_for_failure (klass);
3997 *ex = mono_get_exception_execution_engine ("Unknown error");
4002 ICALL_EXPORT MonoArray*
4003 ves_icall_RuntimeType_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4005 static MonoClass *MethodInfo_array;
4009 MonoVTable *array_vtable;
4010 MonoException *ex = NULL;
4011 const char *mname = NULL;
4012 GPtrArray *method_array;
4013 MonoClass *klass, *refklass;
4016 mono_error_init (&error);
4018 if (!MethodInfo_array) {
4019 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
4020 mono_memory_barrier ();
4021 MethodInfo_array = klass;
4024 klass = mono_class_from_mono_type (type->type);
4025 refklass = mono_class_from_mono_type (reftype->type);
4026 domain = ((MonoObject *)type)->vtable->domain;
4027 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
4028 if (!is_ok (&error)) {
4029 mono_error_set_pending_exception (&error);
4032 if (type->type->byref) {
4033 res = mono_array_new_specific_checked (array_vtable, 0, &error);
4034 mono_error_set_pending_exception (&error);
4040 mname = mono_string_to_utf8_checked (name, &error);
4041 if (mono_error_set_pending_exception (&error))
4045 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
4046 g_free ((char*)mname);
4048 mono_set_pending_exception (ex);
4052 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
4053 if (!mono_error_ok (&error)) {
4054 mono_error_set_pending_exception (&error);
4058 for (i = 0; i < method_array->len; ++i) {
4059 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
4060 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
4061 if (!mono_error_ok (&error))
4063 mono_array_setref (res, i, rm);
4067 g_ptr_array_free (method_array, TRUE);
4068 if (!mono_error_ok (&error))
4069 mono_set_pending_exception (mono_error_convert_to_exception (&error));
4073 ICALL_EXPORT MonoArray*
4074 ves_icall_RuntimeType_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4077 MonoClass *startklass, *klass, *refklass;
4078 MonoArray *res = NULL;
4082 gpointer iter = NULL;
4083 MonoPtrArray tmp_array;
4086 domain = ((MonoObject *)type)->vtable->domain;
4087 if (type->type->byref) {
4088 res = mono_array_new_cached (domain, mono_defaults.method_info_class, 0, &error);
4089 mono_error_set_pending_exception (&error);
4093 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
4096 klass = startklass = mono_class_from_mono_type (type->type);
4097 refklass = mono_class_from_mono_type (reftype->type);
4099 mono_class_setup_methods (klass);
4100 if (mono_class_has_failure (klass)) {
4101 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
4106 while ((method = mono_class_get_methods (klass, &iter))) {
4108 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
4110 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4111 if (bflags & BFLAGS_Public)
4114 if (bflags & BFLAGS_NonPublic)
4120 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4121 if (bflags & BFLAGS_Static)
4122 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4125 if (bflags & BFLAGS_Instance)
4131 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
4132 if (mono_error_set_pending_exception (&error))
4135 mono_ptr_array_append (tmp_array, member);
4138 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array), &error);
4139 if (mono_error_set_pending_exception (&error))
4142 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4143 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4146 mono_ptr_array_destroy (tmp_array);
4152 property_hash (gconstpointer data)
4154 MonoProperty *prop = (MonoProperty*)data;
4156 return g_str_hash (prop->name);
4160 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
4162 if (method1->is_inflated)
4163 method1 = ((MonoMethodInflated*) method1)->declaring;
4164 if (method2->is_inflated)
4165 method2 = ((MonoMethodInflated*) method2)->declaring;
4167 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4171 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4173 // Properties are hide-by-name-and-signature
4174 if (!g_str_equal (prop1->name, prop2->name))
4177 /* If we see a property in a generic method, we want to
4178 compare the generic signatures, not the inflated signatures
4179 because we might conflate two properties that were
4183 public T this[T t] { getter { return t; } } // method 1
4184 public U this[U u] { getter { return u; } } // method 2
4187 If we see int Foo<int,int>::Item[int] we need to know if
4188 the indexer came from method 1 or from method 2, and we
4189 shouldn't conflate them. (Bugzilla 36283)
4191 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
4194 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4201 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4206 return method_nonpublic (accessor, start_klass);
4209 ICALL_EXPORT MonoArray*
4210 ves_icall_RuntimeType_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4214 MonoClass *startklass, *klass;
4220 gchar *propname = NULL;
4221 int (*compare_func) (const char *s1, const char *s2) = NULL;
4223 GHashTable *properties = NULL;
4224 MonoPtrArray tmp_array;
4226 mono_error_init (&error);
4228 domain = ((MonoObject *)type)->vtable->domain;
4229 if (type->type->byref) {
4230 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), 0, &error);
4231 mono_error_set_pending_exception (&error);
4235 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4237 klass = startklass = mono_class_from_mono_type (type->type);
4240 propname = mono_string_to_utf8_checked (name, &error);
4241 if (mono_error_set_pending_exception (&error))
4243 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4246 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4248 mono_class_setup_methods (klass);
4249 mono_class_setup_vtable (klass);
4250 if (mono_class_has_failure (klass))
4254 while ((prop = mono_class_get_properties (klass, &iter))) {
4260 flags = method->flags;
4263 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4264 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4265 if (bflags & BFLAGS_Public)
4267 } else if (bflags & BFLAGS_NonPublic) {
4268 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4269 property_accessor_nonpublic(prop->set, startklass == klass)) {
4276 if (flags & METHOD_ATTRIBUTE_STATIC) {
4277 if (bflags & BFLAGS_Static)
4278 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4281 if (bflags & BFLAGS_Instance)
4290 if (compare_func (propname, prop->name))
4294 if (g_hash_table_lookup (properties, prop))
4297 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4300 mono_ptr_array_append (tmp_array, pr);
4302 g_hash_table_insert (properties, prop, prop);
4304 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4307 g_hash_table_destroy (properties);
4310 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array), &error);
4311 if (!is_ok (&error))
4313 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4314 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4316 mono_ptr_array_destroy (tmp_array);
4323 if (mono_class_has_failure (klass))
4324 mono_error_set_for_class_failure (&error, klass);
4328 g_hash_table_destroy (properties);
4331 mono_ptr_array_destroy (tmp_array);
4333 mono_error_set_pending_exception (&error);
4339 event_hash (gconstpointer data)
4341 MonoEvent *event = (MonoEvent*)data;
4343 return g_str_hash (event->name);
4347 event_equal (MonoEvent *event1, MonoEvent *event2)
4349 // Events are hide-by-name
4350 return g_str_equal (event1->name, event2->name);
4353 ICALL_EXPORT MonoArray*
4354 ves_icall_RuntimeType_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4358 MonoClass *startklass, *klass;
4364 char *utf8_name = NULL;
4365 int (*compare_func) (const char *s1, const char *s2) = NULL;
4366 GHashTable *events = NULL;
4367 MonoPtrArray tmp_array;
4369 mono_error_init (&error);
4371 domain = mono_object_domain (type);
4372 if (type->type->byref) {
4373 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), 0, &error);
4374 mono_error_set_pending_exception (&error);
4378 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4380 klass = startklass = mono_class_from_mono_type (type->type);
4382 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4384 mono_class_setup_methods (klass);
4385 mono_class_setup_vtable (klass);
4386 if (mono_class_has_failure (klass))
4390 while ((event = mono_class_get_events (klass, &iter))) {
4392 method = event->add;
4394 method = event->remove;
4396 method = event->raise;
4398 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4399 if (bflags & BFLAGS_Public)
4401 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4402 if (bflags & BFLAGS_NonPublic)
4407 if (bflags & BFLAGS_NonPublic)
4413 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4414 if (bflags & BFLAGS_Static)
4415 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4418 if (bflags & BFLAGS_Instance)
4423 if (bflags & BFLAGS_Instance)
4429 if (utf8_name == NULL) {
4430 utf8_name = mono_string_to_utf8_checked (name, &error);
4431 if (!is_ok (&error))
4433 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4436 if (compare_func (event->name, utf8_name))
4440 if (g_hash_table_lookup (events, event))
4443 MonoReflectionEvent *ev_obj;
4444 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4447 mono_ptr_array_append (tmp_array, ev_obj);
4449 g_hash_table_insert (events, event, event);
4451 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4454 g_hash_table_destroy (events);
4456 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array), &error);
4457 if (!is_ok (&error))
4460 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4461 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4463 mono_ptr_array_destroy (tmp_array);
4465 if (utf8_name != NULL)
4471 if (mono_class_has_failure (klass))
4472 mono_error_set_for_class_failure (&error, klass);
4477 g_hash_table_destroy (events);
4478 if (utf8_name != NULL)
4481 mono_ptr_array_destroy (tmp_array);
4483 mono_error_set_pending_exception (&error);
4487 ICALL_EXPORT MonoArray*
4488 ves_icall_RuntimeType_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4491 MonoReflectionType *rt;
4494 MonoArray *res = NULL;
4499 MonoPtrArray tmp_array;
4501 mono_error_init (&error);
4503 domain = ((MonoObject *)type)->vtable->domain;
4504 if (type->type->byref) {
4505 MonoArray *result = mono_array_new_cached (domain, mono_defaults.runtimetype_class, 0, &error);
4506 mono_error_set_pending_exception (&error);
4509 klass = mono_class_from_mono_type (type->type);
4512 * If a nested type is generic, return its generic type definition.
4513 * Note that this means that the return value is essentially the set
4514 * of nested types of the generic type definition of @klass.
4516 * A note in MSDN claims that a generic type definition can have
4517 * nested types that aren't generic. In any case, the container of that
4518 * nested type would be the generic type definition.
4520 if (klass->generic_class)
4521 klass = klass->generic_class->container_class;
4523 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4525 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4527 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4528 if (bflags & BFLAGS_Public)
4531 if (bflags & BFLAGS_NonPublic)
4539 str = mono_string_to_utf8_checked (name, &error);
4540 if (!is_ok (&error))
4542 mono_identifier_unescape_type_name_chars (str);
4545 if (strcmp (nested->name, str))
4549 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4550 if (!is_ok (&error))
4553 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4556 res = mono_array_new_cached (domain, mono_defaults.runtimetype_class, mono_ptr_array_size (tmp_array), &error);
4557 if (!is_ok (&error))
4560 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4561 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4564 mono_ptr_array_destroy (tmp_array);
4568 mono_error_set_pending_exception (&error);
4572 ICALL_EXPORT MonoReflectionType*
4573 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4576 MonoReflectionType *ret;
4578 MonoType *type = NULL;
4579 MonoTypeNameParse info;
4580 gboolean type_resolve;
4582 /* On MS.NET, this does not fire a TypeResolve event */
4583 type_resolve = TRUE;
4584 str = mono_string_to_utf8_checked (name, &error);
4585 if (mono_error_set_pending_exception (&error))
4587 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4588 if (!mono_reflection_parse_type (str, &info)) {
4590 mono_reflection_free_type_info (&info);
4592 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4595 /*g_print ("failed parse\n");*/
4599 if (info.assembly.name) {
4601 mono_reflection_free_type_info (&info);
4603 /* 1.0 and 2.0 throw different exceptions */
4604 if (mono_defaults.generic_ilist_class)
4605 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4607 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4613 if (module != NULL) {
4614 if (module->image) {
4615 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4616 if (!is_ok (&error)) {
4618 mono_reflection_free_type_info (&info);
4619 mono_error_set_pending_exception (&error);
4626 if (assembly_is_dynamic (assembly->assembly)) {
4627 /* Enumerate all modules */
4628 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4632 if (abuilder->modules) {
4633 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4634 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4635 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4636 if (!is_ok (&error)) {
4638 mono_reflection_free_type_info (&info);
4639 mono_error_set_pending_exception (&error);
4647 if (!type && abuilder->loaded_modules) {
4648 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4649 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4650 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4651 if (!is_ok (&error)) {
4653 mono_reflection_free_type_info (&info);
4654 mono_error_set_pending_exception (&error);
4663 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4664 if (!is_ok (&error)) {
4666 mono_reflection_free_type_info (&info);
4667 mono_error_set_pending_exception (&error);
4672 mono_reflection_free_type_info (&info);
4674 MonoException *e = NULL;
4677 e = mono_get_exception_type_load (name, NULL);
4680 mono_set_pending_exception (e);
4684 if (type->type == MONO_TYPE_CLASS) {
4685 MonoClass *klass = mono_type_get_class (type);
4687 /* need to report exceptions ? */
4688 if (throwOnError && mono_class_has_failure (klass)) {
4689 /* report SecurityException (or others) that occured when loading the assembly */
4690 MonoException *exc = mono_class_get_exception_for_failure (klass);
4691 mono_set_pending_exception (exc);
4696 /* g_print ("got it\n"); */
4697 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4698 mono_error_set_pending_exception (&error);
4704 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4707 gchar *shadow_ini_file;
4710 /* Check for shadow-copied assembly */
4711 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4712 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4714 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4715 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4721 g_free (shadow_ini_file);
4722 if (content != NULL) {
4725 *filename = content;
4732 ICALL_EXPORT MonoString *
4733 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4735 MonoDomain *domain = mono_object_domain (assembly);
4736 MonoAssembly *mass = assembly->assembly;
4737 MonoString *res = NULL;
4742 if (g_path_is_absolute (mass->image->name)) {
4743 absolute = g_strdup (mass->image->name);
4744 dirname = g_path_get_dirname (absolute);
4746 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4747 dirname = g_strdup (mass->basedir);
4750 replace_shadow_path (domain, dirname, &absolute);
4755 for (i = strlen (absolute) - 1; i >= 0; i--)
4756 if (absolute [i] == '\\')
4761 uri = g_filename_to_uri (absolute, NULL, NULL);
4763 const char *prepend = "file://";
4765 if (*absolute == '/' && *(absolute + 1) == '/') {
4768 prepend = "file:///";
4771 uri = g_strconcat (prepend, absolute, NULL);
4775 res = mono_string_new (domain, uri);
4782 ICALL_EXPORT MonoBoolean
4783 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4785 MonoAssembly *mass = assembly->assembly;
4787 return mass->in_gac;
4790 ICALL_EXPORT MonoReflectionAssembly*
4791 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4796 MonoImageOpenStatus status;
4797 MonoReflectionAssembly* result = NULL;
4799 name = mono_string_to_utf8_checked (mname, &error);
4800 if (mono_error_set_pending_exception (&error))
4802 res = mono_assembly_load_with_partial_name (name, &status);
4808 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4810 mono_error_set_pending_exception (&error);
4814 ICALL_EXPORT MonoString *
4815 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4817 MonoDomain *domain = mono_object_domain (assembly);
4820 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4825 ICALL_EXPORT MonoBoolean
4826 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4828 return assembly->assembly->ref_only;
4831 ICALL_EXPORT MonoString *
4832 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4834 MonoDomain *domain = mono_object_domain (assembly);
4836 return mono_string_new (domain, assembly->assembly->image->version);
4839 ICALL_EXPORT MonoReflectionMethod*
4840 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4843 MonoReflectionMethod *res = NULL;
4846 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4850 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4851 if (!mono_error_ok (&error))
4854 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4857 if (!mono_error_ok (&error))
4858 mono_error_set_pending_exception (&error);
4862 ICALL_EXPORT MonoReflectionModule*
4863 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4866 MonoReflectionModule *result = NULL;
4867 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4868 if (!mono_error_ok (&error))
4869 mono_error_set_pending_exception (&error);
4873 ICALL_EXPORT MonoArray*
4874 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4877 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4878 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4879 if (mono_error_set_pending_exception (&error))
4884 for (i = 0; i < table->rows; ++i) {
4885 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4886 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4892 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4894 static MonoMethod *create_version = NULL;
4898 mono_error_init (error);
4901 if (!create_version) {
4902 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4903 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4904 g_assert (create_version);
4905 mono_method_desc_free (desc);
4911 args [3] = &revision;
4912 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4913 return_val_if_nok (error, NULL);
4915 mono_runtime_invoke_checked (create_version, result, args, error);
4916 return_val_if_nok (error, NULL);
4921 ICALL_EXPORT MonoArray*
4922 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4926 MonoDomain *domain = mono_object_domain (assembly);
4928 static MonoMethod *create_culture = NULL;
4929 MonoImage *image = assembly->assembly->image;
4933 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4936 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4937 if (mono_error_set_pending_exception (&error))
4941 if (count > 0 && !create_culture) {
4942 MonoMethodDesc *desc = mono_method_desc_new (
4943 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4944 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4945 g_assert (create_culture);
4946 mono_method_desc_free (desc);
4949 for (i = 0; i < count; i++) {
4950 MonoObject *version;
4951 MonoReflectionAssemblyName *aname;
4952 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4954 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4956 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4957 domain, mono_class_get_assembly_name_class (), &error);
4958 if (mono_error_set_pending_exception (&error))
4961 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4963 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4964 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4965 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4966 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4967 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4968 aname->versioncompat = 1; /* SameMachine (default) */
4969 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4971 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4972 if (mono_error_set_pending_exception (&error))
4975 MONO_OBJECT_SETREF (aname, version, version);
4977 if (create_culture) {
4979 MonoBoolean assembly_ref = 1;
4980 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4981 args [1] = &assembly_ref;
4983 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4984 if (mono_error_set_pending_exception (&error))
4987 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4990 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4991 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4992 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4994 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4995 /* public key token isn't copied - the class library will
4996 automatically generate it from the public key if required */
4997 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4998 if (mono_error_set_pending_exception (&error))
5001 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5002 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
5004 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
5005 if (mono_error_set_pending_exception (&error))
5008 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5009 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
5012 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
5013 if (mono_error_set_pending_exception (&error))
5016 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5019 /* note: this function doesn't return the codebase on purpose (i.e. it can
5020 be used under partial trust as path information isn't present). */
5022 mono_array_setref (result, i, aname);
5027 /* move this in some file in mono/util/ */
5029 g_concat_dir_and_file (const char *dir, const char *file)
5031 g_return_val_if_fail (dir != NULL, NULL);
5032 g_return_val_if_fail (file != NULL, NULL);
5035 * If the directory name doesn't have a / on the end, we need
5036 * to add one so we get a proper path to the file
5038 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
5039 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
5041 return g_strconcat (dir, file, NULL);
5045 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
5048 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5050 guint32 cols [MONO_MANIFEST_SIZE];
5051 guint32 impl, file_idx;
5055 char *n = mono_string_to_utf8_checked (name, &error);
5056 if (mono_error_set_pending_exception (&error))
5059 for (i = 0; i < table->rows; ++i) {
5060 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5061 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5062 if (strcmp (val, n) == 0)
5066 if (i == table->rows)
5069 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
5072 * this code should only be called after obtaining the
5073 * ResourceInfo and handling the other cases.
5075 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
5076 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
5078 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
5083 module = assembly->assembly->image;
5086 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
5087 if (mono_error_set_pending_exception (&error))
5089 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
5091 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
5094 ICALL_EXPORT gboolean
5095 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
5098 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5100 guint32 cols [MONO_MANIFEST_SIZE];
5101 guint32 file_cols [MONO_FILE_SIZE];
5105 n = mono_string_to_utf8_checked (name, &error);
5106 if (mono_error_set_pending_exception (&error))
5108 for (i = 0; i < table->rows; ++i) {
5109 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5110 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5111 if (strcmp (val, n) == 0)
5115 if (i == table->rows)
5118 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
5119 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
5122 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
5123 case MONO_IMPLEMENTATION_FILE:
5124 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5125 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5126 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
5127 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
5128 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
5129 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
5132 info->location = RESOURCE_LOCATION_EMBEDDED;
5135 case MONO_IMPLEMENTATION_ASSEMBLYREF:
5136 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5137 mono_assembly_load_reference (assembly->assembly->image, i - 1);
5138 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
5139 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
5140 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
5142 mono_set_pending_exception (ex);
5145 MonoReflectionAssembly *assm_obj;
5146 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5148 mono_error_set_pending_exception (&error);
5151 MONO_OBJECT_SETREF (info, assembly, assm_obj);
5153 /* Obtain info recursively */
5154 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5155 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5158 case MONO_IMPLEMENTATION_EXP_TYPE:
5159 g_assert_not_reached ();
5167 ICALL_EXPORT MonoObject*
5168 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
5171 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5172 MonoArray *result = NULL;
5177 /* check hash if needed */
5179 n = mono_string_to_utf8_checked (name, &error);
5180 if (mono_error_set_pending_exception (&error))
5183 for (i = 0; i < table->rows; ++i) {
5184 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5185 if (strcmp (val, n) == 0) {
5188 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5189 fn = mono_string_new (mono_object_domain (assembly), n);
5191 return (MonoObject*)fn;
5199 for (i = 0; i < table->rows; ++i) {
5200 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5204 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
5205 if (mono_error_set_pending_exception (&error))
5210 for (i = 0; i < table->rows; ++i) {
5211 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5212 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5213 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5214 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5219 return (MonoObject*)result;
5222 ICALL_EXPORT MonoArray*
5223 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5226 MonoDomain *domain = mono_domain_get();
5229 int i, j, file_count = 0;
5230 MonoImage **modules;
5231 guint32 module_count, real_module_count;
5232 MonoTableInfo *table;
5233 guint32 cols [MONO_FILE_SIZE];
5234 MonoImage *image = assembly->assembly->image;
5236 g_assert (image != NULL);
5237 g_assert (!assembly_is_dynamic (assembly->assembly));
5239 table = &image->tables [MONO_TABLE_FILE];
5240 file_count = table->rows;
5242 modules = image->modules;
5243 module_count = image->module_count;
5245 real_module_count = 0;
5246 for (i = 0; i < module_count; ++i)
5248 real_module_count ++;
5250 klass = mono_class_get_module_class ();
5251 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5252 if (mono_error_set_pending_exception (&error))
5255 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5256 if (mono_error_set_pending_exception (&error))
5259 mono_array_setref (res, 0, image_obj);
5261 for (i = 0; i < module_count; ++i)
5263 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5264 if (mono_error_set_pending_exception (&error))
5266 mono_array_setref (res, j, rm);
5270 for (i = 0; i < file_count; ++i, ++j) {
5271 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5272 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5273 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5274 if (mono_error_set_pending_exception (&error))
5276 mono_array_setref (res, j, rm);
5279 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5281 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5282 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5285 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5286 if (mono_error_set_pending_exception (&error))
5288 mono_array_setref (res, j, rm);
5295 ICALL_EXPORT MonoReflectionMethod*
5296 ves_icall_GetCurrentMethod (void)
5298 MonoReflectionMethod *res = NULL;
5301 MonoMethod *m = mono_method_get_last_managed ();
5304 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5308 while (m->is_inflated)
5309 m = ((MonoMethodInflated*)m)->declaring;
5311 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5312 mono_error_set_pending_exception (&error);
5318 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5321 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5324 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5325 //method is inflated, we should inflate it on the other class
5326 MonoGenericContext ctx;
5327 ctx.method_inst = inflated->context.method_inst;
5328 ctx.class_inst = inflated->context.class_inst;
5329 if (klass->generic_class)
5330 ctx.class_inst = klass->generic_class->context.class_inst;
5331 else if (klass->generic_container)
5332 ctx.class_inst = klass->generic_container->context.class_inst;
5333 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5334 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5338 mono_class_setup_methods (method->klass);
5339 if (mono_class_has_failure (method->klass))
5341 for (i = 0; i < method->klass->method.count; ++i) {
5342 if (method->klass->methods [i] == method) {
5347 mono_class_setup_methods (klass);
5348 if (mono_class_has_failure (klass))
5350 g_assert (offset >= 0 && offset < klass->method.count);
5351 return klass->methods [offset];
5354 ICALL_EXPORT MonoReflectionMethod*
5355 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5357 MonoReflectionMethod *res = NULL;
5361 klass = mono_class_from_mono_type (type);
5362 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5364 if (method->klass != klass) {
5365 method = mono_method_get_equivalent_method (method, klass);
5370 klass = method->klass;
5371 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5372 mono_error_set_pending_exception (&error);
5376 ICALL_EXPORT MonoReflectionMethodBody*
5377 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5380 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5381 mono_error_set_pending_exception (&error);
5385 ICALL_EXPORT MonoReflectionAssembly*
5386 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5389 MonoReflectionAssembly *result;
5390 MonoMethod *dest = NULL;
5392 mono_stack_walk_no_il (get_executing, &dest);
5394 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5396 mono_error_set_pending_exception (&error);
5401 ICALL_EXPORT MonoReflectionAssembly*
5402 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5405 MonoReflectionAssembly *result;
5406 MonoDomain* domain = mono_domain_get ();
5408 if (!domain->entry_assembly)
5411 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5413 mono_error_set_pending_exception (&error);
5417 ICALL_EXPORT MonoReflectionAssembly*
5418 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5423 MonoReflectionAssembly *result;
5426 mono_stack_walk_no_il (get_executing, &dest);
5428 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5432 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5435 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5437 mono_error_set_pending_exception (&error);
5441 ICALL_EXPORT MonoString *
5442 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5443 gboolean assembly_qualified)
5445 MonoDomain *domain = mono_object_domain (object);
5446 MonoTypeNameFormat format;
5451 format = assembly_qualified ?
5452 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5453 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5455 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5457 name = mono_type_get_name_full (object->type, format);
5461 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5466 res = mono_string_new (domain, name);
5473 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5476 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5478 mono_class_init_checked (klass, &error);
5479 mono_error_set_pending_exception (&error);
5480 return mono_security_core_clr_class_level (klass);
5484 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5486 MonoClassField *field = rfield->field;
5487 return mono_security_core_clr_field_level (field, TRUE);
5491 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5493 MonoMethod *method = rfield->method;
5494 return mono_security_core_clr_method_level (method, TRUE);
5498 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)
5500 static MonoMethod *create_culture = NULL;
5504 const char *pkey_ptr;
5506 MonoBoolean assembly_ref = 0;
5508 mono_error_init (error);
5510 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5511 aname->major = name->major;
5512 aname->minor = name->minor;
5513 aname->build = name->build;
5514 aname->flags = name->flags;
5515 aname->revision = name->revision;
5516 aname->hashalg = name->hash_alg;
5517 aname->versioncompat = 1; /* SameMachine (default) */
5518 aname->processor_architecture = name->arch;
5520 if (by_default_version) {
5521 MonoObject *version;
5523 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5524 return_if_nok (error);
5526 MONO_OBJECT_SETREF (aname, version, version);
5530 if (absolute != NULL && *absolute != '\0') {
5531 const gchar *prepend = "file://";
5534 codebase = g_strdup (absolute);
5539 for (i = strlen (codebase) - 1; i >= 0; i--)
5540 if (codebase [i] == '\\')
5543 if (*codebase == '/' && *(codebase + 1) == '/') {
5546 prepend = "file:///";
5550 result = g_strconcat (prepend, codebase, NULL);
5556 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5560 if (!create_culture) {
5561 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5562 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5563 g_assert (create_culture);
5564 mono_method_desc_free (desc);
5567 if (name->culture) {
5568 args [0] = mono_string_new (domain, name->culture);
5569 args [1] = &assembly_ref;
5571 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5572 return_if_nok (error);
5574 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5577 if (name->public_key) {
5578 pkey_ptr = (char*)name->public_key;
5579 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5581 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5582 return_if_nok (error);
5583 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5584 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5585 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5586 } else if (default_publickey) {
5587 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5588 return_if_nok (error);
5589 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5590 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5593 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5594 if (name->public_key_token [0]) {
5598 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5599 return_if_nok (error);
5601 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5602 p = mono_array_addr (keyToken, char, 0);
5604 for (i = 0, j = 0; i < 8; i++) {
5605 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5606 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5609 } else if (default_token) {
5610 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5611 return_if_nok (error);
5612 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5616 ICALL_EXPORT MonoString *
5617 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5619 MonoDomain *domain = mono_object_domain (assembly);
5620 MonoAssembly *mass = assembly->assembly;
5624 name = mono_stringify_assembly_name (&mass->aname);
5625 res = mono_string_new (domain, name);
5632 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5636 MonoAssembly *mass = assembly->assembly;
5638 if (g_path_is_absolute (mass->image->name)) {
5639 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5640 mono_error_set_pending_exception (&error);
5643 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5645 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5646 mono_error_set_pending_exception (&error);
5652 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5656 MonoImageOpenStatus status = MONO_IMAGE_OK;
5659 MonoAssemblyName name;
5662 filename = mono_string_to_utf8_checked (fname, &error);
5663 if (mono_error_set_pending_exception (&error))
5666 dirname = g_path_get_dirname (filename);
5667 replace_shadow_path (mono_domain_get (), dirname, &filename);
5670 image = mono_image_open (filename, &status);
5676 if (status == MONO_IMAGE_IMAGE_INVALID)
5677 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5679 exc = mono_get_exception_file_not_found2 (NULL, fname);
5680 mono_set_pending_exception (exc);
5684 res = mono_assembly_fill_assembly_name (image, &name);
5686 mono_image_close (image);
5688 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5692 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5693 mono_error_set_pending_exception (&error);
5695 mono_image_close (image);
5699 ICALL_EXPORT MonoBoolean
5700 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5701 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5703 MonoBoolean result = FALSE;
5704 MonoDeclSecurityEntry entry;
5706 /* SecurityAction.RequestMinimum */
5707 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5708 *minimum = entry.blob;
5709 *minLength = entry.size;
5712 /* SecurityAction.RequestOptional */
5713 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5714 *optional = entry.blob;
5715 *optLength = entry.size;
5718 /* SecurityAction.RequestRefuse */
5719 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5720 *refused = entry.blob;
5721 *refLength = entry.size;
5729 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5731 guint32 attrs, visibility;
5733 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5734 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5735 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5738 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5744 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5746 MonoReflectionType *rt;
5749 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5752 mono_error_init (error);
5754 /* we start the count from 1 because we skip the special type <Module> */
5757 for (i = 1; i < tdef->rows; ++i) {
5758 if (mono_module_type_is_visible (tdef, image, i + 1))
5762 count = tdef->rows - 1;
5764 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5765 return_val_if_nok (error, NULL);
5766 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5767 return_val_if_nok (error, NULL);
5769 for (i = 1; i < tdef->rows; ++i) {
5770 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5771 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5774 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5775 return_val_if_nok (error, NULL);
5777 mono_array_setref (res, count, rt);
5779 MonoException *ex = mono_error_convert_to_exception (error);
5780 mono_array_setref (*exceptions, count, ex);
5789 ICALL_EXPORT MonoArray*
5790 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5793 MonoArray *res = NULL;
5794 MonoArray *exceptions = NULL;
5795 MonoImage *image = NULL;
5796 MonoTableInfo *table = NULL;
5799 int i, len, ex_count;
5801 domain = mono_object_domain (assembly);
5803 g_assert (!assembly_is_dynamic (assembly->assembly));
5804 image = assembly->assembly->image;
5805 table = &image->tables [MONO_TABLE_FILE];
5806 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5807 if (mono_error_set_pending_exception (&error))
5810 /* Append data from all modules in the assembly */
5811 for (i = 0; i < table->rows; ++i) {
5812 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5813 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5818 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5819 if (mono_error_set_pending_exception (&error))
5823 /* Append the new types to the end of the array */
5824 if (mono_array_length (res2) > 0) {
5826 MonoArray *res3, *ex3;
5828 len1 = mono_array_length (res);
5829 len2 = mono_array_length (res2);
5831 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5832 if (mono_error_set_pending_exception (&error))
5834 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5835 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5838 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5839 if (mono_error_set_pending_exception (&error))
5841 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5842 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5849 /* the ReflectionTypeLoadException must have all the types (Types property),
5850 * NULL replacing types which throws an exception. The LoaderException must
5851 * contain all exceptions for NULL items.
5854 len = mono_array_length (res);
5857 for (i = 0; i < len; i++) {
5858 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5862 klass = mono_type_get_class (t->type);
5863 if ((klass != NULL) && mono_class_has_failure (klass)) {
5864 /* keep the class in the list */
5865 list = g_list_append (list, klass);
5866 /* and replace Type with NULL */
5867 mono_array_setref (res, i, NULL);
5874 if (list || ex_count) {
5876 MonoException *exc = NULL;
5877 MonoArray *exl = NULL;
5878 int j, length = g_list_length (list) + ex_count;
5880 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5881 if (mono_error_set_pending_exception (&error)) {
5885 /* Types for which mono_class_get_checked () succeeded */
5886 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5887 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5888 mono_array_setref (exl, i, exc);
5890 /* Types for which it don't */
5891 for (j = 0; j < mono_array_length (exceptions); ++j) {
5892 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5894 g_assert (i < length);
5895 mono_array_setref (exl, i, exc);
5902 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5903 if (!is_ok (&error)) {
5904 mono_error_set_pending_exception (&error);
5907 mono_set_pending_exception (exc);
5914 ICALL_EXPORT gboolean
5915 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5918 MonoAssemblyName aname;
5919 MonoDomain *domain = mono_object_domain (name);
5921 gboolean is_version_defined;
5922 gboolean is_token_defined;
5924 aname.public_key = NULL;
5925 val = mono_string_to_utf8_checked (assname, &error);
5926 if (mono_error_set_pending_exception (&error))
5929 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5930 g_free ((guint8*) aname.public_key);
5935 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5936 mono_error_set_pending_exception (&error);
5938 mono_assembly_name_free (&aname);
5939 g_free ((guint8*) aname.public_key);
5945 ICALL_EXPORT MonoReflectionType*
5946 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5949 MonoReflectionType *ret;
5950 MonoDomain *domain = mono_object_domain (module);
5953 g_assert (module->image);
5955 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5956 /* These images do not have a global type */
5959 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5960 if (!mono_error_ok (&error)) {
5961 mono_error_set_pending_exception (&error);
5965 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5966 if (!mono_error_ok (&error)) {
5967 mono_error_set_pending_exception (&error);
5975 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5977 /*if (module->image)
5978 mono_image_close (module->image);*/
5981 ICALL_EXPORT MonoString*
5982 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5984 MonoDomain *domain = mono_object_domain (module);
5986 g_assert (module->image);
5987 return mono_string_new (domain, module->image->guid);
5990 ICALL_EXPORT gpointer
5991 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5994 if (module->image && module->image->is_module_handle)
5995 return module->image->raw_data;
5998 return (gpointer) (-1);
6002 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
6004 if (image_is_dynamic (image)) {
6005 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
6006 *pe_kind = dyn->pe_kind;
6007 *machine = dyn->machine;
6010 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
6011 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
6016 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
6018 return (image->md_version_major << 16) | (image->md_version_minor);
6021 ICALL_EXPORT MonoArray*
6022 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
6025 MonoArray *exceptions;
6028 if (!module->image) {
6029 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
6030 mono_error_set_pending_exception (&error);
6035 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
6036 if (mono_error_set_pending_exception (&error))
6039 for (i = 0; i < mono_array_length (exceptions); ++i) {
6040 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
6042 mono_set_pending_exception (ex);
6051 mono_memberref_is_method (MonoImage *image, guint32 token)
6053 if (!image_is_dynamic (image)) {
6054 guint32 cols [MONO_MEMBERREF_SIZE];
6056 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
6057 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
6058 mono_metadata_decode_blob_size (sig, &sig);
6059 return (*sig != 0x6);
6062 MonoClass *handle_class;
6064 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
6065 mono_error_cleanup (&error); /* just probing, ignore error */
6069 return mono_defaults.methodhandle_class == handle_class;
6074 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
6077 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
6078 mono_array_addr (type_args, MonoType*, 0));
6080 context->class_inst = NULL;
6082 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
6083 mono_array_addr (method_args, MonoType*, 0));
6085 context->method_inst = NULL;
6088 ICALL_EXPORT MonoType*
6089 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6092 int table = mono_metadata_token_table (token);
6093 int index = mono_metadata_token_index (token);
6094 MonoGenericContext context;
6097 *resolve_error = ResolveTokenError_Other;
6099 /* Validate token */
6100 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
6101 (table != MONO_TABLE_TYPESPEC)) {
6102 *resolve_error = ResolveTokenError_BadTable;
6106 if (image_is_dynamic (image)) {
6107 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
6108 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6109 mono_error_cleanup (&error);
6110 return klass ? &klass->byval_arg : NULL;
6113 init_generic_context_from_args (&context, type_args, method_args);
6114 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6115 mono_error_cleanup (&error);
6116 return klass ? &klass->byval_arg : NULL;
6119 if ((index <= 0) || (index > image->tables [table].rows)) {
6120 *resolve_error = ResolveTokenError_OutOfRange;
6124 init_generic_context_from_args (&context, type_args, method_args);
6125 klass = mono_class_get_checked (image, token, &error);
6127 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
6128 if (!mono_error_ok (&error)) {
6129 mono_error_set_pending_exception (&error);
6134 return &klass->byval_arg;
6139 ICALL_EXPORT MonoMethod*
6140 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6143 int table = mono_metadata_token_table (token);
6144 int index = mono_metadata_token_index (token);
6145 MonoGenericContext context;
6148 *resolve_error = ResolveTokenError_Other;
6150 /* Validate token */
6151 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
6152 (table != MONO_TABLE_MEMBERREF)) {
6153 *resolve_error = ResolveTokenError_BadTable;
6157 if (image_is_dynamic (image)) {
6158 if (table == MONO_TABLE_METHOD) {
6159 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6160 mono_error_cleanup (&error);
6164 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
6165 *resolve_error = ResolveTokenError_BadTable;
6169 init_generic_context_from_args (&context, type_args, method_args);
6170 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6171 mono_error_cleanup (&error);
6175 if ((index <= 0) || (index > image->tables [table].rows)) {
6176 *resolve_error = ResolveTokenError_OutOfRange;
6179 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6180 *resolve_error = ResolveTokenError_BadTable;
6184 init_generic_context_from_args (&context, type_args, method_args);
6185 method = mono_get_method_checked (image, token, NULL, &context, &error);
6186 mono_error_set_pending_exception (&error);
6191 ICALL_EXPORT MonoString*
6192 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6195 int index = mono_metadata_token_index (token);
6197 *resolve_error = ResolveTokenError_Other;
6199 /* Validate token */
6200 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6201 *resolve_error = ResolveTokenError_BadTable;
6205 if (image_is_dynamic (image)) {
6206 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6207 mono_error_cleanup (&error);
6211 if ((index <= 0) || (index >= image->heap_us.size)) {
6212 *resolve_error = ResolveTokenError_OutOfRange;
6216 /* FIXME: What to do if the index points into the middle of a string ? */
6218 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
6219 mono_error_set_pending_exception (&error);
6223 ICALL_EXPORT MonoClassField*
6224 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6228 int table = mono_metadata_token_table (token);
6229 int index = mono_metadata_token_index (token);
6230 MonoGenericContext context;
6231 MonoClassField *field;
6233 *resolve_error = ResolveTokenError_Other;
6235 /* Validate token */
6236 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6237 *resolve_error = ResolveTokenError_BadTable;
6241 if (image_is_dynamic (image)) {
6242 if (table == MONO_TABLE_FIELD) {
6243 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6244 mono_error_cleanup (&error);
6248 if (mono_memberref_is_method (image, token)) {
6249 *resolve_error = ResolveTokenError_BadTable;
6253 init_generic_context_from_args (&context, type_args, method_args);
6254 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6255 mono_error_cleanup (&error);
6259 if ((index <= 0) || (index > image->tables [table].rows)) {
6260 *resolve_error = ResolveTokenError_OutOfRange;
6263 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6264 *resolve_error = ResolveTokenError_BadTable;
6268 init_generic_context_from_args (&context, type_args, method_args);
6269 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6270 mono_error_set_pending_exception (&error);
6276 ICALL_EXPORT MonoObject*
6277 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6281 int table = mono_metadata_token_table (token);
6283 *error = ResolveTokenError_Other;
6286 case MONO_TABLE_TYPEDEF:
6287 case MONO_TABLE_TYPEREF:
6288 case MONO_TABLE_TYPESPEC: {
6289 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6291 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6292 mono_error_set_pending_exception (&merror);
6299 case MONO_TABLE_METHOD:
6300 case MONO_TABLE_METHODSPEC: {
6301 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6303 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6304 mono_error_set_pending_exception (&merror);
6310 case MONO_TABLE_FIELD: {
6311 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6313 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6314 mono_error_set_pending_exception (&merror);
6320 case MONO_TABLE_MEMBERREF:
6321 if (mono_memberref_is_method (image, token)) {
6322 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6324 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6325 mono_error_set_pending_exception (&merror);
6332 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6334 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6335 mono_error_set_pending_exception (&merror);
6344 *error = ResolveTokenError_BadTable;
6350 ICALL_EXPORT MonoArray*
6351 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6354 int table = mono_metadata_token_table (token);
6355 int idx = mono_metadata_token_index (token);
6356 MonoTableInfo *tables = image->tables;
6361 *resolve_error = ResolveTokenError_OutOfRange;
6363 /* FIXME: Support other tables ? */
6364 if (table != MONO_TABLE_STANDALONESIG)
6367 if (image_is_dynamic (image))
6370 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6373 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6375 ptr = mono_metadata_blob_heap (image, sig);
6376 len = mono_metadata_decode_blob_size (ptr, &ptr);
6378 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6379 if (mono_error_set_pending_exception (&error))
6381 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6385 ICALL_EXPORT MonoReflectionType*
6386 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6389 MonoReflectionType *ret;
6391 int isbyref = 0, rank;
6393 char *str = mono_string_to_utf8_checked (smodifiers, &error);
6394 if (mono_error_set_pending_exception (&error))
6397 klass = mono_class_from_mono_type (tb->type.type);
6399 /* logic taken from mono_reflection_parse_type(): keep in sync */
6403 if (isbyref) { /* only one level allowed by the spec */
6412 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6413 mono_error_set_pending_exception (&error);
6417 klass = mono_ptr_class_get (&klass->byval_arg);
6418 mono_class_init (klass);
6429 else if (*p != '*') { /* '*' means unknown lower bound */
6440 klass = mono_array_class_get (klass, rank);
6441 mono_class_init (klass);
6450 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6451 mono_error_set_pending_exception (&error);
6456 ICALL_EXPORT MonoBoolean
6457 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6463 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6469 check_for_invalid_type (MonoClass *klass, MonoError *error)
6474 mono_error_init (error);
6476 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6479 name = mono_type_get_full_name (klass);
6480 str = mono_string_new (mono_domain_get (), name);
6482 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6485 ICALL_EXPORT MonoReflectionType *
6486 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6489 MonoReflectionType *ret;
6490 MonoClass *klass, *aklass;
6492 klass = mono_class_from_mono_type (type->type);
6493 check_for_invalid_type (klass, &error);
6494 mono_error_set_pending_exception (&error);
6496 if (rank == 0) //single dimentional array
6497 aklass = mono_array_class_get (klass, 1);
6499 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6501 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6502 mono_error_set_pending_exception (&error);
6507 ICALL_EXPORT MonoReflectionType *
6508 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6511 MonoReflectionType *ret;
6514 klass = mono_class_from_mono_type (type->type);
6515 mono_class_init_checked (klass, &error);
6516 if (mono_error_set_pending_exception (&error))
6519 check_for_invalid_type (klass, &error);
6520 if (mono_error_set_pending_exception (&error))
6523 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6524 mono_error_set_pending_exception (&error);
6529 ICALL_EXPORT MonoReflectionType *
6530 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6533 MonoReflectionType *ret;
6534 MonoClass *klass, *pklass;
6536 klass = mono_class_from_mono_type (type->type);
6537 mono_class_init_checked (klass, &error);
6538 if (mono_error_set_pending_exception (&error))
6540 check_for_invalid_type (klass, &error);
6541 if (mono_error_set_pending_exception (&error))
6544 pklass = mono_ptr_class_get (type->type);
6546 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6547 mono_error_set_pending_exception (&error);
6552 ICALL_EXPORT MonoObject *
6553 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6554 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6557 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6558 MonoObject *delegate;
6560 MonoMethod *method = info->method;
6562 mono_class_init_checked (delegate_class, &error);
6563 if (mono_error_set_pending_exception (&error))
6566 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6567 /* FIXME improve this exception message */
6568 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6570 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6571 mono_error_set_pending_exception (&error);
6575 if (mono_security_core_clr_enabled ()) {
6576 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6577 if (throwOnBindFailure)
6578 mono_error_set_pending_exception (&error);
6580 mono_error_cleanup (&error);
6585 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6586 if (mono_error_set_pending_exception (&error))
6589 if (method_is_dynamic (method)) {
6590 /* Creating a trampoline would leak memory */
6591 func = mono_compile_method_checked (method, &error);
6592 if (mono_error_set_pending_exception (&error))
6595 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6596 method = mono_object_get_virtual_method (target, method);
6597 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6598 if (mono_error_set_pending_exception (&error))
6600 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6603 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6604 if (mono_error_set_pending_exception (&error))
6609 ICALL_EXPORT MonoMulticastDelegate *
6610 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6613 MonoMulticastDelegate *ret;
6615 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6617 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6618 if (mono_error_set_pending_exception (&error))
6621 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6626 ICALL_EXPORT MonoReflectionMethod*
6627 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6629 MonoReflectionMethod *ret = NULL;
6631 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6632 mono_error_set_pending_exception (&error);
6638 static inline gint32
6639 mono_array_get_byte_length (MonoArray *array)
6645 klass = array->obj.vtable->klass;
6647 if (array->bounds == NULL)
6648 length = array->max_length;
6651 for (i = 0; i < klass->rank; ++ i)
6652 length *= array->bounds [i].length;
6655 switch (klass->element_class->byval_arg.type) {
6658 case MONO_TYPE_BOOLEAN:
6662 case MONO_TYPE_CHAR:
6670 return length * sizeof (gpointer);
6681 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6683 return mono_array_get_byte_length (array);
6687 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6689 return mono_array_get (array, gint8, idx);
6693 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6695 mono_array_set (array, gint8, idx, value);
6698 ICALL_EXPORT MonoBoolean
6699 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6701 guint8 *src_buf, *dest_buf;
6704 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6708 g_assert (count >= 0);
6710 /* This is called directly from the class libraries without going through the managed wrapper */
6711 MONO_CHECK_ARG_NULL (src, FALSE);
6712 MONO_CHECK_ARG_NULL (dest, FALSE);
6714 /* watch out for integer overflow */
6715 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6718 src_buf = (guint8 *)src->vector + src_offset;
6719 dest_buf = (guint8 *)dest->vector + dest_offset;
6722 memcpy (dest_buf, src_buf, count);
6724 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6729 #ifndef DISABLE_REMOTING
6730 ICALL_EXPORT MonoObject *
6731 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6734 MonoDomain *domain = mono_object_domain (this_obj);
6736 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6737 MonoTransparentProxy *tp;
6741 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6742 if (mono_error_set_pending_exception (&error))
6745 tp = (MonoTransparentProxy*) res;
6747 MONO_OBJECT_SETREF (tp, rp, rp);
6748 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6749 klass = mono_class_from_mono_type (type);
6751 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6752 mono_class_setup_vtable (klass);
6753 if (mono_class_has_failure (klass)) {
6754 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6758 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6759 if (mono_error_set_pending_exception (&error))
6761 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6762 if (mono_error_set_pending_exception (&error))
6765 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6766 if (mono_error_set_pending_exception (&error))
6771 ICALL_EXPORT MonoReflectionType *
6772 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6775 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6776 mono_error_set_pending_exception (&error);
6782 /* System.Environment */
6785 ves_icall_System_Environment_get_UserName (void)
6787 /* using glib is more portable */
6788 return mono_string_new (mono_domain_get (), g_get_user_name ());
6792 ICALL_EXPORT MonoString *
6793 ves_icall_System_Environment_get_MachineName (void)
6795 #if defined (HOST_WIN32)
6800 len = MAX_COMPUTERNAME_LENGTH + 1;
6801 buf = g_new (gunichar2, len);
6804 if (GetComputerName (buf, (PDWORD) &len)) {
6806 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6807 mono_error_set_pending_exception (&error);
6812 #elif !defined(DISABLE_SOCKETS)
6816 #if defined _SC_HOST_NAME_MAX
6817 n = sysconf (_SC_HOST_NAME_MAX);
6821 buf = g_malloc (n+1);
6823 if (gethostname (buf, n) == 0){
6825 result = mono_string_new (mono_domain_get (), buf);
6832 return mono_string_new (mono_domain_get (), "mono");
6837 ves_icall_System_Environment_get_Platform (void)
6839 #if defined (TARGET_WIN32)
6842 #elif defined(__MACH__)
6845 // Notice that the value is hidden from user code, and only exposed
6846 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6847 // define and making assumptions based on Unix/128/4 values before there
6848 // was a MacOS define. Lots of code would assume that not-Unix meant
6849 // Windows, but in this case, it would be OSX.
6858 ICALL_EXPORT MonoString *
6859 ves_icall_System_Environment_get_NewLine (void)
6861 #if defined (HOST_WIN32)
6862 return mono_string_new (mono_domain_get (), "\r\n");
6864 return mono_string_new (mono_domain_get (), "\n");
6868 ICALL_EXPORT MonoBoolean
6869 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6871 #if SIZEOF_VOID_P == 8
6875 gboolean isWow64Process = FALSE;
6876 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6877 return (MonoBoolean)isWow64Process;
6879 #elif defined(HAVE_SYS_UTSNAME_H)
6880 struct utsname name;
6882 if (uname (&name) >= 0) {
6883 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6890 ICALL_EXPORT MonoString *
6891 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6900 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6901 if (mono_error_set_pending_exception (&error))
6903 value = g_getenv (utf8_name);
6910 return mono_string_new (mono_domain_get (), value);
6914 * There is no standard way to get at environ.
6917 #ifndef __MINGW32_VERSION
6918 #if defined(__APPLE__)
6919 #if defined (TARGET_OSX)
6920 /* Apple defines this in crt_externs.h but doesn't provide that header for
6921 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6922 * in fact exist on all implementations (so far)
6924 gchar ***_NSGetEnviron(void);
6925 #define environ (*_NSGetEnviron())
6927 static char *mono_environ[1] = { NULL };
6928 #define environ mono_environ
6929 #endif /* defined (TARGET_OSX) */
6937 ICALL_EXPORT MonoArray *
6938 ves_icall_System_Environment_GetCoomandLineArgs (void)
6941 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6942 mono_error_set_pending_exception (&error);
6946 ICALL_EXPORT MonoArray *
6947 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6959 env_strings = GetEnvironmentStrings();
6962 env_string = env_strings;
6963 while (*env_string != '\0') {
6964 /* weird case that MS seems to skip */
6965 if (*env_string != '=')
6967 while (*env_string != '\0')
6973 domain = mono_domain_get ();
6974 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6975 if (mono_error_set_pending_exception (&error))
6980 env_string = env_strings;
6981 while (*env_string != '\0') {
6982 /* weird case that MS seems to skip */
6983 if (*env_string != '=') {
6984 equal_str = wcschr(env_string, '=');
6985 g_assert(equal_str);
6987 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6988 if (mono_error_set_pending_exception (&error))
6991 mono_array_setref (names, n, str);
6994 while (*env_string != '\0')
6999 FreeEnvironmentStrings (env_strings);
7013 for (e = environ; *e != 0; ++ e)
7016 domain = mono_domain_get ();
7017 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
7018 if (mono_error_set_pending_exception (&error))
7022 for (e = environ; *e != 0; ++ e) {
7023 parts = g_strsplit (*e, "=", 2);
7025 str = mono_string_new (domain, *parts);
7026 mono_array_setref (names, n, str);
7039 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
7042 gunichar2 *utf16_name, *utf16_value;
7044 gchar *utf8_name, *utf8_value;
7049 utf16_name = mono_string_to_utf16 (name);
7050 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7051 SetEnvironmentVariable (utf16_name, NULL);
7052 g_free (utf16_name);
7056 utf16_value = mono_string_to_utf16 (value);
7058 SetEnvironmentVariable (utf16_name, utf16_value);
7060 g_free (utf16_name);
7061 g_free (utf16_value);
7063 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
7064 if (mono_error_set_pending_exception (&error))
7067 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7068 g_unsetenv (utf8_name);
7073 utf8_value = mono_string_to_utf8_checked (value, &error);
7074 if (!mono_error_ok (&error)) {
7076 mono_error_set_pending_exception (&error);
7079 g_setenv (utf8_name, utf8_value, TRUE);
7082 g_free (utf8_value);
7087 ves_icall_System_Environment_Exit (int result)
7089 mono_environment_exitcode_set (result);
7091 /* FIXME: There are some cleanup hangs that should be worked out, but
7092 * if the program is going to exit, everything will be cleaned up when
7093 * NaCl exits anyway.
7095 #ifndef __native_client__
7096 if (!mono_runtime_try_shutdown ())
7097 mono_thread_exit ();
7099 /* Suspend all managed threads since the runtime is going away */
7100 mono_thread_suspend_all_other_threads ();
7102 mono_runtime_quit ();
7105 /* we may need to do some cleanup here... */
7109 ICALL_EXPORT MonoString*
7110 ves_icall_System_Environment_GetGacPath (void)
7112 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
7115 ICALL_EXPORT MonoString*
7116 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
7118 #if defined (HOST_WIN32)
7119 #ifndef CSIDL_FLAG_CREATE
7120 #define CSIDL_FLAG_CREATE 0x8000
7123 WCHAR path [MAX_PATH];
7124 /* Create directory if no existing */
7125 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
7130 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
7131 mono_error_set_pending_exception (&error);
7135 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7137 return mono_string_new (mono_domain_get (), "");
7140 ICALL_EXPORT MonoArray *
7141 ves_icall_System_Environment_GetLogicalDrives (void)
7144 gunichar2 buf [256], *ptr, *dname;
7146 guint initial_size = 127, size = 128;
7149 MonoString *drivestr;
7150 MonoDomain *domain = mono_domain_get ();
7156 while (size > initial_size) {
7157 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
7158 if (size > initial_size) {
7161 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7162 initial_size = size;
7176 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7177 if (mono_error_set_pending_exception (&error))
7184 while (*u16) { u16++; len ++; }
7185 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7186 if (mono_error_set_pending_exception (&error))
7189 mono_array_setref (result, ndrives++, drivestr);
7200 ICALL_EXPORT MonoString *
7201 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7204 gunichar2 volume_name [MAX_PATH + 1];
7206 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7208 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
7209 mono_error_set_pending_exception (&error);
7213 ICALL_EXPORT MonoString *
7214 ves_icall_System_Environment_InternalGetHome (void)
7216 return mono_string_new (mono_domain_get (), g_get_home_dir ());
7219 static const char *encodings [] = {
7221 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7222 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7223 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7225 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7226 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7227 "x_unicode_2_0_utf_7",
7229 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7230 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7232 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7235 "unicodefffe", "utf_16be",
7242 * Returns the internal codepage, if the value of "int_code_page" is
7243 * 1 at entry, and we can not compute a suitable code page number,
7244 * returns the code page as a string
7246 ICALL_EXPORT MonoString*
7247 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
7252 char *codepage = NULL;
7254 int want_name = *int_code_page;
7257 *int_code_page = -1;
7259 g_get_charset (&cset);
7260 c = codepage = strdup (cset);
7261 for (c = codepage; *c; c++){
7262 if (isascii (*c) && isalpha (*c))
7267 /* g_print ("charset: %s\n", cset); */
7269 /* handle some common aliases */
7272 for (i = 0; p != 0; ){
7275 p = encodings [++i];
7278 if (strcmp (p, codepage) == 0){
7279 *int_code_page = code;
7282 p = encodings [++i];
7285 if (strstr (codepage, "utf_8") != NULL)
7286 *int_code_page |= 0x10000000;
7289 if (want_name && *int_code_page == -1)
7290 return mono_string_new (mono_domain_get (), cset);
7295 ICALL_EXPORT MonoBoolean
7296 ves_icall_System_Environment_get_HasShutdownStarted (void)
7298 if (mono_runtime_is_shutting_down ())
7301 if (mono_domain_is_unloading (mono_domain_get ()))
7308 ves_icall_System_Environment_BroadcastSettingChange (void)
7311 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7317 ves_icall_System_Environment_get_TickCount (void)
7319 /* this will overflow after ~24 days */
7320 return (gint32) (mono_msec_boottime () & 0xffffffff);
7324 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7330 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
7331 MonoReflectionMethod *method,
7332 MonoArray *out_args)
7335 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args, &error);
7336 mono_error_set_pending_exception (&error);
7339 #ifndef DISABLE_REMOTING
7340 ICALL_EXPORT MonoBoolean
7341 ves_icall_IsTransparentProxy (MonoObject *proxy)
7346 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7352 ICALL_EXPORT MonoReflectionMethod *
7353 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7354 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7356 MonoReflectionMethod *ret = NULL;
7361 MonoMethod **vtable;
7362 MonoMethod *res = NULL;
7364 MONO_CHECK_ARG_NULL (rtype, NULL);
7365 MONO_CHECK_ARG_NULL (rmethod, NULL);
7367 method = rmethod->method;
7368 klass = mono_class_from_mono_type (rtype->type);
7369 mono_class_init_checked (klass, &error);
7370 if (mono_error_set_pending_exception (&error))
7373 if (MONO_CLASS_IS_INTERFACE (klass))
7376 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7379 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7380 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7386 mono_class_setup_vtable (klass);
7387 vtable = klass->vtable;
7389 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7390 gboolean variance_used = FALSE;
7391 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7392 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7394 res = vtable [offs + method->slot];
7396 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7399 if (method->slot != -1)
7400 res = vtable [method->slot];
7406 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7407 mono_error_set_pending_exception (&error);
7412 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7418 klass = mono_class_from_mono_type (type->type);
7419 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7420 if (!is_ok (&error)) {
7421 mono_error_set_pending_exception (&error);
7425 mono_vtable_set_is_remote (vtable, enable);
7428 #else /* DISABLE_REMOTING */
7431 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7433 g_assert_not_reached ();
7438 ICALL_EXPORT MonoObject *
7439 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7446 domain = mono_object_domain (type);
7447 klass = mono_class_from_mono_type (type->type);
7448 mono_class_init_checked (klass, &error);
7449 if (mono_error_set_pending_exception (&error))
7452 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7453 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7457 if (klass->rank >= 1) {
7458 g_assert (klass->rank == 1);
7459 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7460 mono_error_set_pending_exception (&error);
7463 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7464 if (!is_ok (&error)) {
7465 mono_error_set_pending_exception (&error);
7468 /* Bypass remoting object creation check */
7469 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7470 mono_error_set_pending_exception (&error);
7476 ICALL_EXPORT MonoString *
7477 ves_icall_System_IO_get_temp_path (void)
7479 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7482 #ifndef PLATFORM_NO_DRIVEINFO
7483 ICALL_EXPORT MonoBoolean
7484 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7485 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7489 ULARGE_INTEGER wapi_free_bytes_avail;
7490 ULARGE_INTEGER wapi_total_number_of_bytes;
7491 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7493 *error = ERROR_SUCCESS;
7494 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7495 &wapi_total_number_of_free_bytes);
7498 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7499 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7500 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7502 *free_bytes_avail = 0;
7503 *total_number_of_bytes = 0;
7504 *total_number_of_free_bytes = 0;
7505 *error = GetLastError ();
7511 ICALL_EXPORT guint32
7512 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7514 return GetDriveType (mono_string_chars (root_path_name));
7518 ICALL_EXPORT gpointer
7519 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7522 gpointer result = mono_compile_method_checked (method, &error);
7523 mono_error_set_pending_exception (&error);
7527 ICALL_EXPORT MonoString *
7528 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7533 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7535 #if defined (HOST_WIN32)
7536 /* Avoid mixing '/' and '\\' */
7539 for (i = strlen (path) - 1; i >= 0; i--)
7540 if (path [i] == '/')
7544 mcpath = mono_string_new (mono_domain_get (), path);
7550 /* this is an icall */
7552 get_bundled_app_config (void)
7555 const gchar *app_config;
7558 gchar *config_file_name, *config_file_path;
7559 gsize len, config_file_path_length, config_ext_length;
7562 domain = mono_domain_get ();
7563 file = domain->setup->configuration_file;
7564 if (!file || file->length == 0)
7567 // Retrieve config file and remove the extension
7568 config_file_name = mono_string_to_utf8_checked (file, &error);
7569 if (mono_error_set_pending_exception (&error))
7571 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7572 if (!config_file_path)
7573 config_file_path = config_file_name;
7575 config_file_path_length = strlen (config_file_path);
7576 config_ext_length = strlen (".config");
7577 if (config_file_path_length <= config_ext_length)
7580 len = config_file_path_length - config_ext_length;
7581 module = (gchar *)g_malloc0 (len + 1);
7582 memcpy (module, config_file_path, len);
7583 // Get the config file from the module name
7584 app_config = mono_config_string_for_assembly_file (module);
7587 if (config_file_name != config_file_path)
7588 g_free (config_file_name);
7589 g_free (config_file_path);
7594 return mono_string_new (mono_domain_get (), app_config);
7598 get_bundled_machine_config (void)
7600 const gchar *machine_config;
7602 machine_config = mono_get_machine_config ();
7604 if (!machine_config)
7607 return mono_string_new (mono_domain_get (), machine_config);
7610 ICALL_EXPORT MonoString *
7611 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7616 path = g_path_get_dirname (mono_get_config_dir ());
7618 #if defined (HOST_WIN32)
7619 /* Avoid mixing '/' and '\\' */
7622 for (i = strlen (path) - 1; i >= 0; i--)
7623 if (path [i] == '/')
7627 ipath = mono_string_new (mono_domain_get (), path);
7633 ICALL_EXPORT gboolean
7634 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7636 MonoPEResourceDataEntry *entry;
7639 if (!assembly || !result || !size)
7644 image = assembly->assembly->image;
7645 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7649 *result = mono_image_rva_map (image, entry->rde_data_offset);
7654 *size = entry->rde_size;
7659 ICALL_EXPORT MonoBoolean
7660 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7662 return mono_is_debugger_attached ();
7665 ICALL_EXPORT MonoBoolean
7666 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7668 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7669 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7675 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7677 if (mono_get_runtime_callbacks ()->debug_log)
7678 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7682 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7684 #if defined (HOST_WIN32)
7685 OutputDebugString (mono_string_chars (message));
7687 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7691 /* Only used for value types */
7692 ICALL_EXPORT MonoObject *
7693 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7700 domain = mono_object_domain (type);
7701 klass = mono_class_from_mono_type (type->type);
7702 mono_class_init_checked (klass, &error);
7703 if (mono_error_set_pending_exception (&error))
7706 if (mono_class_is_nullable (klass))
7707 /* No arguments -> null */
7710 result = mono_object_new_checked (domain, klass, &error);
7711 mono_error_set_pending_exception (&error);
7715 ICALL_EXPORT MonoReflectionMethod *
7716 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7718 MonoReflectionMethod *ret = NULL;
7721 MonoClass *klass, *parent;
7722 MonoGenericContext *generic_inst = NULL;
7723 MonoMethod *method = m->method;
7724 MonoMethod *result = NULL;
7727 if (method->klass == NULL)
7730 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7731 MONO_CLASS_IS_INTERFACE (method->klass) ||
7732 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7735 slot = mono_method_get_vtable_slot (method);
7739 klass = method->klass;
7740 if (klass->generic_class) {
7741 generic_inst = mono_class_get_context (klass);
7742 klass = klass->generic_class->container_class;
7746 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7747 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7748 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7749 or klass is the generic container class and generic_inst is the instantiation.
7751 when we go to the parent, if the parent is an open constructed type, we need to
7752 replace the type parameters by the definitions from the generic_inst, and then take it
7753 apart again into the klass and the generic_inst.
7755 For cases like this:
7756 class C<T> : B<T, int> {
7757 public override void Foo () { ... }
7759 class B<U,V> : A<HashMap<U,V>> {
7760 public override void Foo () { ... }
7763 public virtual void Foo () { ... }
7766 if at each iteration the parent isn't open, we can skip inflating it. if at some
7767 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7770 MonoGenericContext *parent_inst = NULL;
7771 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7772 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7773 if (!mono_error_ok (&error)) {
7774 mono_error_set_pending_exception (&error);
7778 if (parent->generic_class) {
7779 parent_inst = mono_class_get_context (parent);
7780 parent = parent->generic_class->container_class;
7783 mono_class_setup_vtable (parent);
7784 if (parent->vtable_size <= slot)
7787 generic_inst = parent_inst;
7790 klass = klass->parent;
7793 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7794 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7795 if (!mono_error_ok (&error)) {
7796 mono_error_set_pending_exception (&error);
7800 generic_inst = NULL;
7802 if (klass->generic_class) {
7803 generic_inst = mono_class_get_context (klass);
7804 klass = klass->generic_class->container_class;
7810 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7811 if (!mono_error_ok (&error)) {
7812 mono_error_set_pending_exception (&error);
7817 if (klass == method->klass)
7820 /*This is possible if definition == FALSE.
7821 * Do it here to be really sure we don't read invalid memory.
7823 if (slot >= klass->vtable_size)
7826 mono_class_setup_vtable (klass);
7828 result = klass->vtable [slot];
7829 if (result == NULL) {
7830 /* It is an abstract method */
7831 gpointer iter = NULL;
7832 while ((result = mono_class_get_methods (klass, &iter)))
7833 if (result->slot == slot)
7840 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7841 mono_error_set_pending_exception (&error);
7845 ICALL_EXPORT MonoString*
7846 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7848 MonoMethod *method = m->method;
7850 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7855 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7857 iter->sig = *(MonoMethodSignature**)argsp;
7859 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7860 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7863 /* FIXME: it's not documented what start is exactly... */
7867 iter->args = argsp + sizeof (gpointer);
7869 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7871 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7874 ICALL_EXPORT MonoTypedRef
7875 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7877 guint32 i, arg_size;
7881 i = iter->sig->sentinelpos + iter->next_arg;
7883 g_assert (i < iter->sig->param_count);
7885 res.type = iter->sig->params [i];
7886 res.klass = mono_class_from_mono_type (res.type);
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 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7893 /* Values are stored as 8 byte register sized objects, but 'value'
7894 * is dereferenced as a pointer in other routines.
7896 res.value = (char*)res.value + 4;
7898 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7899 if (arg_size <= sizeof (gpointer)) {
7901 int padding = arg_size - mono_type_size (res.type, &dummy);
7902 res.value = (guint8*)res.value + padding;
7905 iter->args = (char*)iter->args + arg_size;
7908 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7913 ICALL_EXPORT MonoTypedRef
7914 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7916 guint32 i, arg_size;
7920 i = iter->sig->sentinelpos + iter->next_arg;
7922 g_assert (i < iter->sig->param_count);
7924 while (i < iter->sig->param_count) {
7925 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7927 res.type = iter->sig->params [i];
7928 res.klass = mono_class_from_mono_type (res.type);
7929 /* FIXME: endianess issue... */
7930 arg_size = mono_type_stack_size (res.type, &align);
7931 #if defined(__arm__) || defined(__mips__)
7932 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7934 res.value = iter->args;
7935 iter->args = (char*)iter->args + arg_size;
7937 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7940 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7948 ICALL_EXPORT MonoType*
7949 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7953 i = iter->sig->sentinelpos + iter->next_arg;
7955 g_assert (i < iter->sig->param_count);
7957 return iter->sig->params [i];
7960 ICALL_EXPORT MonoObject*
7961 mono_TypedReference_ToObject (MonoTypedRef* tref)
7964 MonoObject *result = NULL;
7965 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7966 MonoObject** objp = (MonoObject **)tref->value;
7970 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7971 mono_error_set_pending_exception (&error);
7975 ICALL_EXPORT MonoTypedRef
7976 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7979 MonoReflectionField *f;
7981 MonoType *ftype = NULL;
7985 memset (&res, 0, sizeof (res));
7988 g_assert (mono_array_length (fields) > 0);
7990 klass = target->vtable->klass;
7992 for (i = 0; i < mono_array_length (fields); ++i) {
7993 f = mono_array_get (fields, MonoReflectionField*, i);
7995 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7998 if (f->field->parent != klass) {
7999 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
8003 p = (guint8*)target + f->field->offset;
8005 p += f->field->offset - sizeof (MonoObject);
8006 klass = mono_class_from_mono_type (f->field->type);
8007 ftype = f->field->type;
8011 res.klass = mono_class_from_mono_type (ftype);
8018 prelink_method (MonoMethod *method, MonoError *error)
8020 const char *exc_class, *exc_arg;
8022 mono_error_init (error);
8023 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
8025 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
8027 mono_error_set_exception_instance (error,
8028 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
8031 /* create the wrapper, too? */
8035 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
8039 prelink_method (method->method, &error);
8040 mono_error_set_pending_exception (&error);
8044 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
8047 MonoClass *klass = mono_class_from_mono_type (type->type);
8049 gpointer iter = NULL;
8051 mono_class_init_checked (klass, &error);
8052 if (mono_error_set_pending_exception (&error))
8055 while ((m = mono_class_get_methods (klass, &iter))) {
8056 prelink_method (m, &error);
8057 if (mono_error_set_pending_exception (&error))
8062 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
8064 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
8065 gint32 const **exponents,
8066 gunichar2 const **digitLowerTable,
8067 gunichar2 const **digitUpperTable,
8068 gint64 const **tenPowersList,
8069 gint32 const **decHexDigits)
8071 *mantissas = Formatter_MantissaBitsTable;
8072 *exponents = Formatter_TensExponentTable;
8073 *digitLowerTable = Formatter_DigitLowerTable;
8074 *digitUpperTable = Formatter_DigitUpperTable;
8075 *tenPowersList = Formatter_TenPowersList;
8076 *decHexDigits = Formatter_DecHexDigits;
8080 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
8081 * and avoid useless allocations.
8084 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
8086 MonoReflectionType *rt;
8090 mono_error_init (error);
8091 for (i = 0; i < type->num_mods; ++i) {
8092 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
8097 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
8098 return_val_if_nok (error, NULL);
8100 for (i = 0; i < type->num_mods; ++i) {
8101 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
8102 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
8103 return_val_if_nok (error, NULL);
8105 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8106 return_val_if_nok (error, NULL);
8108 mono_array_setref (res, count, rt);
8115 ICALL_EXPORT MonoArray*
8116 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
8119 MonoType *type = param->ClassImpl->type;
8120 MonoClass *member_class = mono_object_class (param->MemberImpl);
8121 MonoMethod *method = NULL;
8124 MonoMethodSignature *sig;
8127 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8128 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8129 method = rmethod->method;
8130 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
8131 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8132 if (!(method = prop->property->get))
8133 method = prop->property->set;
8136 char *type_name = mono_type_get_full_name (member_class);
8137 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
8138 MonoException *ex = mono_get_exception_not_supported (msg);
8141 mono_set_pending_exception (ex);
8145 image = method->klass->image;
8146 pos = param->PositionImpl;
8147 sig = mono_method_signature (method);
8151 type = sig->params [pos];
8153 res = type_array_from_modifiers (image, type, optional, &error);
8154 mono_error_set_pending_exception (&error);
8159 get_property_type (MonoProperty *prop)
8161 MonoMethodSignature *sig;
8163 sig = mono_method_signature (prop->get);
8165 } else if (prop->set) {
8166 sig = mono_method_signature (prop->set);
8167 return sig->params [sig->param_count - 1];
8172 ICALL_EXPORT MonoArray*
8173 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
8176 MonoType *type = get_property_type (property->property);
8177 MonoImage *image = property->klass->image;
8182 res = type_array_from_modifiers (image, type, optional, &error);
8183 mono_error_set_pending_exception (&error);
8188 *Construct a MonoType suited to be used to decode a constant blob object.
8190 * @type is the target type which will be constructed
8191 * @blob_type is the blob type, for example, that comes from the constant table
8192 * @real_type is the expected constructed type.
8195 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8197 type->type = blob_type;
8198 type->data.klass = NULL;
8199 if (blob_type == MONO_TYPE_CLASS)
8200 type->data.klass = mono_defaults.object_class;
8201 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8202 /* For enums, we need to use the base type */
8203 type->type = MONO_TYPE_VALUETYPE;
8204 type->data.klass = mono_class_from_mono_type (real_type);
8206 type->data.klass = mono_class_from_mono_type (real_type);
8209 ICALL_EXPORT MonoObject*
8210 property_info_get_default_value (MonoReflectionProperty *property)
8214 MonoProperty *prop = property->property;
8215 MonoType *type = get_property_type (prop);
8216 MonoDomain *domain = mono_object_domain (property);
8217 MonoTypeEnum def_type;
8218 const char *def_value;
8221 mono_class_init (prop->parent);
8223 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8224 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8228 def_value = mono_class_get_property_default_value (prop, &def_type);
8230 mono_type_from_blob_type (&blob_type, def_type, type);
8231 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8233 mono_error_set_pending_exception (&error);
8237 ICALL_EXPORT MonoBoolean
8238 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8241 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8242 MonoCustomAttrInfo *cinfo;
8245 mono_class_init_checked (attr_class, &error);
8246 if (mono_error_set_pending_exception (&error))
8249 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8250 if (!is_ok (&error)) {
8251 mono_error_set_pending_exception (&error);
8256 found = mono_custom_attrs_has_attr (cinfo, attr_class);
8258 mono_custom_attrs_free (cinfo);
8262 ICALL_EXPORT MonoArray*
8263 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8265 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8270 mono_class_init_checked (attr_class, &error);
8271 if (mono_error_set_pending_exception (&error))
8275 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8276 if (!mono_error_ok (&error)) {
8277 mono_error_set_pending_exception (&error);
8284 ICALL_EXPORT MonoArray*
8285 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8289 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8290 mono_error_set_pending_exception (&error);
8295 ICALL_EXPORT MonoString*
8296 ves_icall_Mono_Runtime_GetDisplayName (void)
8299 MonoString *display_name;
8301 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8302 display_name = mono_string_new (mono_domain_get (), info);
8304 return display_name;
8307 ICALL_EXPORT MonoString*
8308 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8311 MonoString *message;
8315 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8316 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8319 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8321 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8322 if (mono_error_set_pending_exception (&error))
8329 ICALL_EXPORT gpointer
8330 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8332 return GetCurrentProcess ();
8335 ICALL_EXPORT MonoBoolean
8336 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8338 return GetExitCodeProcess (handle, (guint32*) exitcode);
8341 ICALL_EXPORT MonoBoolean
8342 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8344 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8345 return CloseHandle (handle);
8347 return CloseProcess (handle);
8351 ICALL_EXPORT MonoBoolean
8352 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8354 return TerminateProcess (handle, exitcode);
8358 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8360 return WaitForInputIdle (handle, milliseconds);
8363 ICALL_EXPORT MonoBoolean
8364 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8366 return GetProcessWorkingSetSize (handle, min, max);
8369 ICALL_EXPORT MonoBoolean
8370 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8372 return SetProcessWorkingSetSize (handle, min, max);
8375 ICALL_EXPORT MonoBoolean
8376 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8378 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8382 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8384 return mono_process_current_pid ();
8388 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8390 return GetPriorityClass (handle);
8393 ICALL_EXPORT MonoBoolean
8394 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8396 return SetPriorityClass (handle, priorityClass);
8399 #ifndef DISABLE_ICALL_TABLES
8401 #define ICALL_TYPE(id,name,first)
8402 #define ICALL(id,name,func) Icall_ ## id,
8405 #include "metadata/icall-def.h"
8411 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8412 #define ICALL(id,name,func)
8414 #include "metadata/icall-def.h"
8420 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8421 #define ICALL(id,name,func)
8423 guint16 first_icall;
8426 static const IcallTypeDesc
8427 icall_type_descs [] = {
8428 #include "metadata/icall-def.h"
8432 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8435 #define ICALL_TYPE(id,name,first)
8438 #ifdef HAVE_ARRAY_ELEM_INIT
8439 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8440 #define MSGSTRFIELD1(line) str##line
8442 static const struct msgstrtn_t {
8443 #define ICALL(id,name,func)
8445 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8446 #include "metadata/icall-def.h"
8448 } icall_type_names_str = {
8449 #define ICALL_TYPE(id,name,first) (name),
8450 #include "metadata/icall-def.h"
8453 static const guint16 icall_type_names_idx [] = {
8454 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8455 #include "metadata/icall-def.h"
8458 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8460 static const struct msgstr_t {
8462 #define ICALL_TYPE(id,name,first)
8463 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8464 #include "metadata/icall-def.h"
8466 } icall_names_str = {
8467 #define ICALL(id,name,func) (name),
8468 #include "metadata/icall-def.h"
8471 static const guint16 icall_names_idx [] = {
8472 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8473 #include "metadata/icall-def.h"
8476 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8482 #define ICALL_TYPE(id,name,first) name,
8483 #define ICALL(id,name,func)
8484 static const char* const
8485 icall_type_names [] = {
8486 #include "metadata/icall-def.h"
8490 #define icall_type_name_get(id) (icall_type_names [(id)])
8494 #define ICALL_TYPE(id,name,first)
8495 #define ICALL(id,name,func) name,
8496 static const char* const
8498 #include "metadata/icall-def.h"
8501 #define icall_name_get(id) icall_names [(id)]
8503 #endif /* !HAVE_ARRAY_ELEM_INIT */
8507 #define ICALL_TYPE(id,name,first)
8508 #define ICALL(id,name,func) func,
8509 static const gconstpointer
8510 icall_functions [] = {
8511 #include "metadata/icall-def.h"
8515 #ifdef ENABLE_ICALL_SYMBOL_MAP
8518 #define ICALL_TYPE(id,name,first)
8519 #define ICALL(id,name,func) #func,
8520 static const gconstpointer
8521 icall_symbols [] = {
8522 #include "metadata/icall-def.h"
8527 #endif /* DISABLE_ICALL_TABLES */
8529 static mono_mutex_t icall_mutex;
8530 static GHashTable *icall_hash = NULL;
8531 static GHashTable *jit_icall_hash_name = NULL;
8532 static GHashTable *jit_icall_hash_addr = NULL;
8535 mono_icall_init (void)
8537 #ifndef DISABLE_ICALL_TABLES
8540 /* check that tables are sorted: disable in release */
8543 const char *prev_class = NULL;
8544 const char *prev_method;
8546 for (i = 0; i < Icall_type_num; ++i) {
8547 const IcallTypeDesc *desc;
8550 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8551 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8552 prev_class = icall_type_name_get (i);
8553 desc = &icall_type_descs [i];
8554 num_icalls = icall_desc_num_icalls (desc);
8555 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8556 for (j = 0; j < num_icalls; ++j) {
8557 const char *methodn = icall_name_get (desc->first_icall + j);
8558 if (prev_method && strcmp (prev_method, methodn) >= 0)
8559 g_print ("method %s should come before method %s\n", methodn, prev_method);
8560 prev_method = methodn;
8566 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8567 mono_os_mutex_init (&icall_mutex);
8571 mono_icall_lock (void)
8573 mono_locks_os_acquire (&icall_mutex, IcallLock);
8577 mono_icall_unlock (void)
8579 mono_locks_os_release (&icall_mutex, IcallLock);
8583 mono_icall_cleanup (void)
8585 g_hash_table_destroy (icall_hash);
8586 g_hash_table_destroy (jit_icall_hash_name);
8587 g_hash_table_destroy (jit_icall_hash_addr);
8588 mono_os_mutex_destroy (&icall_mutex);
8592 * mono_add_internal_call:
8593 * @name: method specification to surface to the managed world
8594 * @method: pointer to a C method to invoke when the method is called
8596 * This method surfaces the C function pointed by @method as a method
8597 * that has been surfaced in managed code with the method specified in
8598 * @name as an internal call.
8600 * Internal calls are surfaced to all app domains loaded and they are
8601 * accessibly by a type with the specified name.
8603 * You must provide a fully qualified type name, that is namespaces
8604 * and type name, followed by a colon and the method name, with an
8605 * optional signature to bind.
8607 * For example, the following are all valid declarations:
8609 * "MyApp.Services.ScriptService:Accelerate"
8610 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8612 * You use method parameters in cases where there might be more than
8613 * one surface method to managed code. That way you can register different
8614 * internal calls for different method overloads.
8616 * The internal calls are invoked with no marshalling. This means that .NET
8617 * types like System.String are exposed as `MonoString *` parameters. This is
8618 * different than the way that strings are surfaced in P/Invoke.
8620 * For more information on how the parameters are marshalled, see the
8621 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8624 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8625 * reference for more information on the format of method descriptions.
8628 mono_add_internal_call (const char *name, gconstpointer method)
8632 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8634 mono_icall_unlock ();
8637 #ifndef DISABLE_ICALL_TABLES
8639 #ifdef HAVE_ARRAY_ELEM_INIT
8641 compare_method_imap (const void *key, const void *elem)
8643 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8644 return strcmp (key, method_name);
8648 find_method_icall (const IcallTypeDesc *imap, const char *name)
8650 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);
8653 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8657 compare_class_imap (const void *key, const void *elem)
8659 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8660 return strcmp (key, class_name);
8663 static const IcallTypeDesc*
8664 find_class_icalls (const char *name)
8666 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);
8669 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8672 #else /* HAVE_ARRAY_ELEM_INIT */
8675 compare_method_imap (const void *key, const void *elem)
8677 const char** method_name = (const char**)elem;
8678 return strcmp (key, *method_name);
8682 find_method_icall (const IcallTypeDesc *imap, const char *name)
8684 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8687 return (gpointer)icall_functions [(nameslot - icall_names)];
8691 compare_class_imap (const void *key, const void *elem)
8693 const char** class_name = (const char**)elem;
8694 return strcmp (key, *class_name);
8697 static const IcallTypeDesc*
8698 find_class_icalls (const char *name)
8700 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8703 return &icall_type_descs [nameslot - icall_type_names];
8706 #endif /* HAVE_ARRAY_ELEM_INIT */
8708 #endif /* DISABLE_ICALL_TABLES */
8711 * we should probably export this as an helper (handle nested types).
8712 * Returns the number of chars written in buf.
8715 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8717 int nspacelen, cnamelen;
8718 nspacelen = strlen (klass->name_space);
8719 cnamelen = strlen (klass->name);
8720 if (nspacelen + cnamelen + 2 > bufsize)
8723 memcpy (buf, klass->name_space, nspacelen);
8724 buf [nspacelen ++] = '.';
8726 memcpy (buf + nspacelen, klass->name, cnamelen);
8727 buf [nspacelen + cnamelen] = 0;
8728 return nspacelen + cnamelen;
8731 #ifdef DISABLE_ICALL_TABLES
8733 no_icall_table (void)
8735 g_assert_not_reached ();
8740 mono_lookup_internal_call (MonoMethod *method)
8745 int typelen = 0, mlen, siglen;
8747 #ifndef DISABLE_ICALL_TABLES
8748 const IcallTypeDesc *imap = NULL;
8751 g_assert (method != NULL);
8753 if (method->is_inflated)
8754 method = ((MonoMethodInflated *) method)->declaring;
8756 if (method->klass->nested_in) {
8757 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8761 mname [pos++] = '/';
8764 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8770 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8775 #ifndef DISABLE_ICALL_TABLES
8776 imap = find_class_icalls (mname);
8779 mname [typelen] = ':';
8780 mname [typelen + 1] = ':';
8782 mlen = strlen (method->name);
8783 memcpy (mname + typelen + 2, method->name, mlen);
8784 sigstart = mname + typelen + 2 + mlen;
8787 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8788 siglen = strlen (tmpsig);
8789 if (typelen + mlen + siglen + 6 > sizeof (mname))
8792 memcpy (sigstart + 1, tmpsig, siglen);
8793 sigstart [siglen + 1] = ')';
8794 sigstart [siglen + 2] = 0;
8799 res = g_hash_table_lookup (icall_hash, mname);
8801 mono_icall_unlock ();;
8804 /* try without signature */
8806 res = g_hash_table_lookup (icall_hash, mname);
8808 mono_icall_unlock ();
8812 #ifdef DISABLE_ICALL_TABLES
8813 mono_icall_unlock ();
8814 /* Fail only when the result is actually used */
8815 /* mono_marshal_get_native_wrapper () depends on this */
8816 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8817 return ves_icall_System_String_ctor_RedirectToCreateString;
8819 return no_icall_table;
8821 /* it wasn't found in the static call tables */
8823 mono_icall_unlock ();
8826 res = find_method_icall (imap, sigstart - mlen);
8828 mono_icall_unlock ();
8831 /* try _with_ signature */
8833 res = find_method_icall (imap, sigstart - mlen);
8835 mono_icall_unlock ();
8839 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8840 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8841 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8842 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8843 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");
8844 g_print ("If you see other errors or faults after this message they are probably related\n");
8845 g_print ("and you need to fix your mono install first.\n");
8847 mono_icall_unlock ();
8853 #ifdef ENABLE_ICALL_SYMBOL_MAP
8855 func_cmp (gconstpointer key, gconstpointer p)
8857 return (gsize)key - (gsize)*(gsize*)p;
8862 * mono_lookup_icall_symbol:
8864 * Given the icall METHOD, returns its C symbol.
8867 mono_lookup_icall_symbol (MonoMethod *m)
8869 #ifdef DISABLE_ICALL_TABLES
8870 g_assert_not_reached ();
8873 #ifdef ENABLE_ICALL_SYMBOL_MAP
8877 static gconstpointer *functions_sorted;
8878 static const char**symbols_sorted;
8879 static gboolean inited;
8884 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8885 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8886 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8887 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8888 /* Bubble sort the two arrays */
8892 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8893 if (functions_sorted [i] > functions_sorted [i + 1]) {
8896 tmp = functions_sorted [i];
8897 functions_sorted [i] = functions_sorted [i + 1];
8898 functions_sorted [i + 1] = tmp;
8899 tmp = symbols_sorted [i];
8900 symbols_sorted [i] = symbols_sorted [i + 1];
8901 symbols_sorted [i + 1] = tmp;
8908 func = mono_lookup_internal_call (m);
8911 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8915 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8917 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8918 g_assert_not_reached ();
8925 type_from_typename (char *type_name)
8927 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8929 if (!strcmp (type_name, "int"))
8930 klass = mono_defaults.int_class;
8931 else if (!strcmp (type_name, "ptr"))
8932 klass = mono_defaults.int_class;
8933 else if (!strcmp (type_name, "void"))
8934 klass = mono_defaults.void_class;
8935 else if (!strcmp (type_name, "int32"))
8936 klass = mono_defaults.int32_class;
8937 else if (!strcmp (type_name, "uint32"))
8938 klass = mono_defaults.uint32_class;
8939 else if (!strcmp (type_name, "int8"))
8940 klass = mono_defaults.sbyte_class;
8941 else if (!strcmp (type_name, "uint8"))
8942 klass = mono_defaults.byte_class;
8943 else if (!strcmp (type_name, "int16"))
8944 klass = mono_defaults.int16_class;
8945 else if (!strcmp (type_name, "uint16"))
8946 klass = mono_defaults.uint16_class;
8947 else if (!strcmp (type_name, "long"))
8948 klass = mono_defaults.int64_class;
8949 else if (!strcmp (type_name, "ulong"))
8950 klass = mono_defaults.uint64_class;
8951 else if (!strcmp (type_name, "float"))
8952 klass = mono_defaults.single_class;
8953 else if (!strcmp (type_name, "double"))
8954 klass = mono_defaults.double_class;
8955 else if (!strcmp (type_name, "object"))
8956 klass = mono_defaults.object_class;
8957 else if (!strcmp (type_name, "obj"))
8958 klass = mono_defaults.object_class;
8959 else if (!strcmp (type_name, "string"))
8960 klass = mono_defaults.string_class;
8961 else if (!strcmp (type_name, "bool"))
8962 klass = mono_defaults.boolean_class;
8963 else if (!strcmp (type_name, "boolean"))
8964 klass = mono_defaults.boolean_class;
8966 g_error ("%s", type_name);
8967 g_assert_not_reached ();
8969 return &klass->byval_arg;
8973 * LOCKING: Take the corlib image lock.
8975 MonoMethodSignature*
8976 mono_create_icall_signature (const char *sigstr)
8981 MonoMethodSignature *res, *res2;
8982 MonoImage *corlib = mono_defaults.corlib;
8984 mono_image_lock (corlib);
8985 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8986 mono_image_unlock (corlib);
8991 parts = g_strsplit (sigstr, " ", 256);
9000 res = mono_metadata_signature_alloc (corlib, len - 1);
9005 * Under windows, the default pinvoke calling convention is STDCALL but
9008 res->call_convention = MONO_CALL_C;
9011 res->ret = type_from_typename (parts [0]);
9012 for (i = 1; i < len; ++i) {
9013 res->params [i - 1] = type_from_typename (parts [i]);
9018 mono_image_lock (corlib);
9019 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
9021 res = res2; /*Value is allocated in the image pool*/
9023 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
9024 mono_image_unlock (corlib);
9030 mono_find_jit_icall_by_name (const char *name)
9032 MonoJitICallInfo *info;
9033 g_assert (jit_icall_hash_name);
9036 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9037 mono_icall_unlock ();
9042 mono_find_jit_icall_by_addr (gconstpointer addr)
9044 MonoJitICallInfo *info;
9045 g_assert (jit_icall_hash_addr);
9048 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
9049 mono_icall_unlock ();
9055 * mono_get_jit_icall_info:
9057 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
9058 * caller should access it while holding the icall lock.
9061 mono_get_jit_icall_info (void)
9063 return jit_icall_hash_name;
9067 * mono_lookup_jit_icall_symbol:
9069 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
9072 mono_lookup_jit_icall_symbol (const char *name)
9074 MonoJitICallInfo *info;
9075 const char *res = NULL;
9078 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9080 res = info->c_symbol;
9081 mono_icall_unlock ();
9086 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
9089 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
9090 mono_icall_unlock ();
9094 * 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
9095 * icalls without wrappers in some cases.
9098 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
9100 MonoJitICallInfo *info;
9107 if (!jit_icall_hash_name) {
9108 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
9109 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
9112 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
9113 g_warning ("jit icall already defined \"%s\"\n", name);
9114 g_assert_not_reached ();
9117 info = g_new0 (MonoJitICallInfo, 1);
9122 info->c_symbol = c_symbol;
9123 info->no_raise = no_raise;
9126 info->wrapper = func;
9128 info->wrapper = NULL;
9131 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
9132 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
9134 mono_icall_unlock ();
9139 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
9141 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);