5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
9 * Aleksey Kliger (aleksey@xamarin.com)
11 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
12 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
14 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
25 #ifdef HAVE_SYS_TIME_H
31 #if defined (HOST_WIN32)
34 #if defined (HAVE_WCHAR_H)
38 #include "mono/utils/mono-membar.h"
39 #include <mono/metadata/object.h>
40 #include <mono/metadata/threads.h>
41 #include <mono/metadata/threads-types.h>
42 #include <mono/metadata/threadpool-ms.h>
43 #include <mono/metadata/threadpool-ms-io.h>
44 #include <mono/metadata/monitor.h>
45 #include <mono/metadata/reflection.h>
46 #include <mono/metadata/assembly.h>
47 #include <mono/metadata/tabledefs.h>
48 #include <mono/metadata/exception.h>
49 #include <mono/metadata/exception-internals.h>
50 #include <mono/metadata/file-io.h>
51 #include <mono/metadata/console-io.h>
52 #include <mono/metadata/mono-route.h>
53 #include <mono/metadata/socket-io.h>
54 #include <mono/metadata/mono-endian.h>
55 #include <mono/metadata/tokentype.h>
56 #include <mono/metadata/domain-internals.h>
57 #include <mono/metadata/metadata-internals.h>
58 #include <mono/metadata/class-internals.h>
59 #include <mono/metadata/reflection-internals.h>
60 #include <mono/metadata/marshal.h>
61 #include <mono/metadata/gc-internals.h>
62 #include <mono/metadata/mono-gc.h>
63 #include <mono/metadata/rand.h>
64 #include <mono/metadata/sysmath.h>
65 #include <mono/metadata/string-icalls.h>
66 #include <mono/metadata/debug-helpers.h>
67 #include <mono/metadata/process.h>
68 #include <mono/metadata/environment.h>
69 #include <mono/metadata/profiler-private.h>
70 #include <mono/metadata/locales.h>
71 #include <mono/metadata/filewatcher.h>
72 #include <mono/metadata/security.h>
73 #include <mono/metadata/mono-config.h>
74 #include <mono/metadata/cil-coff.h>
75 #include <mono/metadata/number-formatter.h>
76 #include <mono/metadata/security-manager.h>
77 #include <mono/metadata/security-core-clr.h>
78 #include <mono/metadata/mono-perfcounters.h>
79 #include <mono/metadata/mono-debug.h>
80 #include <mono/metadata/mono-ptr-array.h>
81 #include <mono/metadata/verify-internals.h>
82 #include <mono/metadata/runtime.h>
83 #include <mono/metadata/file-mmap.h>
84 #include <mono/metadata/seq-points-data.h>
85 #include <mono/io-layer/io-layer.h>
86 #include <mono/utils/monobitset.h>
87 #include <mono/utils/mono-time.h>
88 #include <mono/utils/mono-proclib.h>
89 #include <mono/utils/mono-string.h>
90 #include <mono/utils/mono-error-internals.h>
91 #include <mono/utils/mono-mmap.h>
92 #include <mono/utils/mono-io-portability.h>
93 #include <mono/utils/mono-digest.h>
94 #include <mono/utils/bsearch.h>
95 #include <mono/utils/mono-os-mutex.h>
96 #include <mono/utils/mono-threads.h>
98 #if defined (HOST_WIN32)
102 #include "decimal-ms.h"
103 #include "number-ms.h"
105 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
106 #include <sys/utsname.h>
109 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
111 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
113 /* Lazy class loading functions */
114 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
115 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
116 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
119 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
122 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
124 static inline MonoBoolean
125 is_generic_parameter (MonoType *type)
127 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
131 mono_class_init_checked (MonoClass *klass, MonoError *error)
133 mono_error_init (error);
135 if (!mono_class_init (klass))
136 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
139 ICALL_EXPORT MonoObject *
140 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
146 MonoObject *result = NULL;
148 ac = (MonoClass *)arr->obj.vtable->klass;
150 esize = mono_array_element_size (ac);
151 ea = (gpointer*)((char*)arr->vector + (pos * esize));
153 if (ac->element_class->valuetype) {
154 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
155 mono_error_set_pending_exception (&error);
157 result = (MonoObject *)*ea;
161 ICALL_EXPORT MonoObject *
162 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
168 MONO_CHECK_ARG_NULL (idxs, NULL);
171 ic = (MonoClass *)io->obj.vtable->klass;
173 ac = (MonoClass *)arr->obj.vtable->klass;
175 g_assert (ic->rank == 1);
176 if (io->bounds != NULL || io->max_length != ac->rank) {
177 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
181 ind = (gint32 *)io->vector;
183 if (arr->bounds == NULL) {
184 if (*ind < 0 || *ind >= arr->max_length) {
185 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
189 return ves_icall_System_Array_GetValueImpl (arr, *ind);
192 for (i = 0; i < ac->rank; i++) {
193 if ((ind [i] < arr->bounds [i].lower_bound) ||
194 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
195 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
200 pos = ind [0] - arr->bounds [0].lower_bound;
201 for (i = 1; i < ac->rank; i++)
202 pos = pos * arr->bounds [i].length + ind [i] -
203 arr->bounds [i].lower_bound;
205 return ves_icall_System_Array_GetValueImpl (arr, pos);
209 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
212 MonoClass *ac, *vc, *ec;
221 mono_error_init (&error);
224 vc = value->vtable->klass;
228 ac = arr->obj.vtable->klass;
229 ec = ac->element_class;
231 esize = mono_array_element_size (ac);
232 ea = (gpointer*)((char*)arr->vector + (pos * esize));
233 va = (gpointer*)((char*)value + sizeof (MonoObject));
235 if (mono_class_is_nullable (ec)) {
236 mono_nullable_init ((guint8*)ea, value, ec);
241 mono_gc_bzero_atomic (ea, esize);
245 #define NO_WIDENING_CONVERSION G_STMT_START{\
246 mono_set_pending_exception (mono_get_exception_argument ( \
247 "value", "not a widening conversion")); \
251 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
252 if (esize < vsize + (extra)) { \
253 mono_set_pending_exception (mono_get_exception_argument ( \
254 "value", "not a widening conversion")); \
259 #define INVALID_CAST G_STMT_START{ \
260 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
261 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
265 /* Check element (destination) type. */
266 switch (ec->byval_arg.type) {
267 case MONO_TYPE_STRING:
268 switch (vc->byval_arg.type) {
269 case MONO_TYPE_STRING:
275 case MONO_TYPE_BOOLEAN:
276 switch (vc->byval_arg.type) {
277 case MONO_TYPE_BOOLEAN:
290 NO_WIDENING_CONVERSION;
299 if (!ec->valuetype) {
300 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
301 if (mono_error_set_pending_exception (&error))
305 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
309 if (mono_object_isinst_checked (value, ec, &error)) {
310 if (ec->has_references)
311 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
313 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
316 if (mono_error_set_pending_exception (&error))
322 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
324 et = ec->byval_arg.type;
325 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
326 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
328 vt = vc->byval_arg.type;
329 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
330 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
332 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
338 case MONO_TYPE_CHAR: \
339 CHECK_WIDENING_CONVERSION(0); \
340 *(etype *) ea = (etype) u64; \
342 /* You can't assign a signed value to an unsigned array. */ \
347 /* You can't assign a floating point number to an integer array. */ \
350 NO_WIDENING_CONVERSION; \
354 #define ASSIGN_SIGNED(etype) G_STMT_START{\
360 CHECK_WIDENING_CONVERSION(0); \
361 *(etype *) ea = (etype) i64; \
363 /* You can assign an unsigned value to a signed array if the array's */ \
364 /* element size is larger than the value size. */ \
369 case MONO_TYPE_CHAR: \
370 CHECK_WIDENING_CONVERSION(1); \
371 *(etype *) ea = (etype) u64; \
373 /* You can't assign a floating point number to an integer array. */ \
376 NO_WIDENING_CONVERSION; \
380 #define ASSIGN_REAL(etype) G_STMT_START{\
384 CHECK_WIDENING_CONVERSION(0); \
385 *(etype *) ea = (etype) r64; \
387 /* All integer values fit into a floating point array, so we don't */ \
388 /* need to CHECK_WIDENING_CONVERSION here. */ \
393 *(etype *) ea = (etype) i64; \
399 case MONO_TYPE_CHAR: \
400 *(etype *) ea = (etype) u64; \
407 u64 = *(guint8 *) va;
410 u64 = *(guint16 *) va;
413 u64 = *(guint32 *) va;
416 u64 = *(guint64 *) va;
422 i64 = *(gint16 *) va;
425 i64 = *(gint32 *) va;
428 i64 = *(gint64 *) va;
431 r64 = *(gfloat *) va;
434 r64 = *(gdouble *) va;
437 u64 = *(guint16 *) va;
439 case MONO_TYPE_BOOLEAN:
440 /* Boolean is only compatible with itself. */
453 NO_WIDENING_CONVERSION;
460 /* If we can't do a direct copy, let's try a widening conversion. */
463 ASSIGN_UNSIGNED (guint16);
465 ASSIGN_UNSIGNED (guint8);
467 ASSIGN_UNSIGNED (guint16);
469 ASSIGN_UNSIGNED (guint32);
471 ASSIGN_UNSIGNED (guint64);
473 ASSIGN_SIGNED (gint8);
475 ASSIGN_SIGNED (gint16);
477 ASSIGN_SIGNED (gint32);
479 ASSIGN_SIGNED (gint64);
481 ASSIGN_REAL (gfloat);
483 ASSIGN_REAL (gdouble);
487 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
491 #undef NO_WIDENING_CONVERSION
492 #undef CHECK_WIDENING_CONVERSION
493 #undef ASSIGN_UNSIGNED
499 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
505 MONO_CHECK_ARG_NULL (idxs,);
507 ic = idxs->obj.vtable->klass;
508 ac = arr->obj.vtable->klass;
510 g_assert (ic->rank == 1);
511 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
512 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
516 ind = (gint32 *)idxs->vector;
518 if (arr->bounds == NULL) {
519 if (*ind < 0 || *ind >= arr->max_length) {
520 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
524 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
528 for (i = 0; i < ac->rank; i++)
529 if ((ind [i] < arr->bounds [i].lower_bound) ||
530 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
531 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
535 pos = ind [0] - arr->bounds [0].lower_bound;
536 for (i = 1; i < ac->rank; i++)
537 pos = pos * arr->bounds [i].length + ind [i] -
538 arr->bounds [i].lower_bound;
540 ves_icall_System_Array_SetValueImpl (arr, value, pos);
543 ICALL_EXPORT MonoArray *
544 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
547 MonoClass *aklass, *klass;
550 gboolean bounded = FALSE;
552 MONO_CHECK_ARG_NULL (type, NULL);
553 MONO_CHECK_ARG_NULL (lengths, NULL);
555 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
557 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
559 for (i = 0; i < mono_array_length (lengths); i++) {
560 if (mono_array_get (lengths, gint32, i) < 0) {
561 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
566 klass = mono_class_from_mono_type (type->type);
567 mono_class_init_checked (klass, &error);
568 if (mono_error_set_pending_exception (&error))
571 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
572 /* vectors are not the same as one dimensional arrays with no-zero bounds */
577 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
579 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
580 for (i = 0; i < aklass->rank; ++i) {
581 sizes [i] = mono_array_get (lengths, guint32, i);
583 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
585 sizes [i + aklass->rank] = 0;
588 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
589 mono_error_set_pending_exception (&error);
594 ICALL_EXPORT MonoArray *
595 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
598 MonoClass *aklass, *klass;
601 gboolean bounded = FALSE;
603 MONO_CHECK_ARG_NULL (type, NULL);
604 MONO_CHECK_ARG_NULL (lengths, NULL);
606 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
608 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
610 for (i = 0; i < mono_array_length (lengths); i++) {
611 if ((mono_array_get (lengths, gint64, i) < 0) ||
612 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
613 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
618 klass = mono_class_from_mono_type (type->type);
619 mono_class_init_checked (klass, &error);
620 if (mono_error_set_pending_exception (&error))
623 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
624 /* vectors are not the same as one dimensional arrays with no-zero bounds */
629 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
631 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
632 for (i = 0; i < aklass->rank; ++i) {
633 sizes [i] = mono_array_get (lengths, guint64, i);
635 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
637 sizes [i + aklass->rank] = 0;
640 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
641 mono_error_set_pending_exception (&error);
647 ves_icall_System_Array_GetRank (MonoObject *arr)
649 return arr->vtable->klass->rank;
653 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
655 gint32 rank = arr->obj.vtable->klass->rank;
658 if ((dimension < 0) || (dimension >= rank)) {
659 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
663 if (arr->bounds == NULL)
664 length = arr->max_length;
666 length = arr->bounds [dimension].length;
668 #ifdef MONO_BIG_ARRAYS
669 if (length > G_MAXINT32) {
670 mono_set_pending_exception (mono_get_exception_overflow ());
678 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
680 gint32 rank = arr->obj.vtable->klass->rank;
682 if ((dimension < 0) || (dimension >= rank)) {
683 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
687 if (arr->bounds == NULL)
688 return arr->max_length;
690 return arr->bounds [dimension].length;
694 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
696 gint32 rank = arr->obj.vtable->klass->rank;
698 if ((dimension < 0) || (dimension >= rank)) {
699 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
703 if (arr->bounds == NULL)
706 return arr->bounds [dimension].lower_bound;
710 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
712 int sz = mono_array_element_size (mono_object_class (arr));
713 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
716 ICALL_EXPORT MonoArray*
717 ves_icall_System_Array_Clone (MonoArray *arr)
720 MonoArray *result = mono_array_clone_checked (arr, &error);
721 mono_error_set_pending_exception (&error);
725 ICALL_EXPORT gboolean
726 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
731 MonoVTable *src_vtable;
732 MonoVTable *dest_vtable;
733 MonoClass *src_class;
734 MonoClass *dest_class;
736 src_vtable = source->obj.vtable;
737 dest_vtable = dest->obj.vtable;
739 if (src_vtable->rank != dest_vtable->rank)
742 if (source->bounds || dest->bounds)
745 /* there's no integer overflow since mono_array_length returns an unsigned integer */
746 if ((dest_idx + length > mono_array_length_fast (dest)) ||
747 (source_idx + length > mono_array_length_fast (source)))
750 src_class = src_vtable->klass->element_class;
751 dest_class = dest_vtable->klass->element_class;
754 * Handle common cases.
757 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
758 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
760 if (src_class == mono_defaults.object_class && dest_class->valuetype)
763 /* Check if we're copying a char[] <==> (u)short[] */
764 if (src_class != dest_class) {
765 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
768 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
769 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
773 if (dest_class->valuetype) {
774 element_size = mono_array_element_size (source->obj.vtable->klass);
775 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
776 if (dest_class->has_references) {
777 mono_value_copy_array (dest, dest_idx, source_addr, length);
779 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
780 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
783 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
790 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
796 ac = (MonoClass *)arr->obj.vtable->klass;
798 esize = mono_array_element_size (ac);
799 ea = (gpointer*)((char*)arr->vector + (pos * esize));
801 mono_gc_memmove_atomic (value, ea, esize);
805 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
811 ac = (MonoClass *)arr->obj.vtable->klass;
812 ec = ac->element_class;
814 esize = mono_array_element_size (ac);
815 ea = (gpointer*)((char*)arr->vector + (pos * esize));
817 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
818 g_assert (esize == sizeof (gpointer));
819 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
821 g_assert (ec->inited);
822 g_assert (esize == mono_class_value_size (ec, NULL));
823 if (ec->has_references)
824 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
826 mono_gc_memmove_atomic (ea, value, esize);
831 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
833 MonoClass *klass = array->obj.vtable->klass;
834 guint32 size = mono_array_element_size (klass);
835 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
837 const char *field_data;
839 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
840 MonoException *exc = mono_get_exception_argument("array",
841 "Cannot initialize array of non-primitive type.");
842 mono_set_pending_exception (exc);
846 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
847 MonoException *exc = mono_get_exception_argument("field_handle",
848 "Field doesn't have an RVA");
849 mono_set_pending_exception (exc);
853 size *= array->max_length;
854 field_data = mono_field_get_data (field_handle);
856 if (size > mono_type_size (field_handle->type, &align)) {
857 MonoException *exc = mono_get_exception_argument("field_handle",
858 "Field not large enough to fill array");
859 mono_set_pending_exception (exc);
863 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
865 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
866 guint ## n *src = (guint ## n *) field_data; \
868 nEnt = (size / sizeof(guint ## n)); \
870 for (i = 0; i < nEnt; i++) { \
871 data[i] = read ## n (&src[i]); \
875 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
877 switch (type->type) {
894 memcpy (mono_array_addr (array, char, 0), field_data, size);
898 memcpy (mono_array_addr (array, char, 0), field_data, size);
903 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
905 return offsetof (MonoString, chars);
908 ICALL_EXPORT MonoObject *
909 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
911 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
915 MonoObject *ret = mono_object_clone_checked (obj, &error);
916 mono_error_set_pending_exception (&error);
923 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
929 MONO_CHECK_ARG_NULL (handle,);
931 klass = mono_class_from_mono_type (handle);
932 MONO_CHECK_ARG (handle, klass,);
934 if (klass->generic_container)
937 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
938 if (!is_ok (&error)) {
939 mono_error_set_pending_exception (&error);
943 /* This will call the type constructor */
944 if (!mono_runtime_class_init_full (vtable, &error))
945 mono_error_set_pending_exception (&error);
949 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
953 mono_image_check_for_module_cctor (image);
954 if (image->has_module_cctor) {
955 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
956 if (!mono_error_ok (&error)) {
957 mono_error_set_pending_exception (&error);
960 /*It's fine to raise the exception here*/
961 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
962 if (!is_ok (&error)) {
963 mono_error_set_pending_exception (&error);
966 if (!mono_runtime_class_init_full (vtable, &error))
967 mono_error_set_pending_exception (&error);
971 ICALL_EXPORT MonoBoolean
972 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
977 /* later make this configurable and per-arch */
978 int min_size = 4096 * 4 * sizeof (void*);
979 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
980 /* if we have no info we are optimistic and assume there is enough room */
984 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
988 current = (guint8 *)&stack_addr;
989 if (current > stack_addr) {
990 if ((current - stack_addr) < min_size)
993 if (current - (stack_addr - stack_size) < min_size)
999 ICALL_EXPORT MonoObject *
1000 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
1003 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
1004 mono_error_set_pending_exception (&error);
1010 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1014 MonoObject **values = NULL;
1017 gint32 result = (int)(gsize)mono_defaults.int32_class;
1018 MonoClassField* field;
1021 klass = mono_object_class (this_obj);
1023 if (mono_class_num_fields (klass) == 0)
1027 * Compute the starting value of the hashcode for fields of primitive
1028 * types, and return the remaining fields in an array to the managed side.
1029 * This way, we can avoid costly reflection operations in managed code.
1032 while ((field = mono_class_get_fields (klass, &iter))) {
1033 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1035 if (mono_field_is_deleted (field))
1037 /* FIXME: Add more types */
1038 switch (field->type->type) {
1040 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1042 case MONO_TYPE_STRING: {
1044 s = *(MonoString**)((guint8*)this_obj + field->offset);
1046 result ^= mono_string_hash (s);
1051 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1052 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1053 if (!is_ok (&error)) {
1054 mono_error_set_pending_exception (&error);
1057 values [count++] = o;
1063 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1064 if (mono_error_set_pending_exception (&error))
1066 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1067 for (i = 0; i < count; ++i)
1068 mono_array_setref (*fields, i, values [i]);
1075 ICALL_EXPORT MonoBoolean
1076 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1080 MonoObject **values = NULL;
1082 MonoClassField* field;
1086 MONO_CHECK_ARG_NULL (that, FALSE);
1088 if (this_obj->vtable != that->vtable)
1091 klass = mono_object_class (this_obj);
1093 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1094 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1097 * Do the comparison for fields of primitive type and return a result if
1098 * possible. Otherwise, return the remaining fields in an array to the
1099 * managed side. This way, we can avoid costly reflection operations in
1104 while ((field = mono_class_get_fields (klass, &iter))) {
1105 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1107 if (mono_field_is_deleted (field))
1109 /* FIXME: Add more types */
1110 switch (field->type->type) {
1113 case MONO_TYPE_BOOLEAN:
1114 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1119 case MONO_TYPE_CHAR:
1120 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1125 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1130 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1134 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1138 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1143 case MONO_TYPE_STRING: {
1144 MonoString *s1, *s2;
1145 guint32 s1len, s2len;
1146 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1147 s2 = *(MonoString**)((guint8*)that + field->offset);
1150 if ((s1 == NULL) || (s2 == NULL))
1152 s1len = mono_string_length (s1);
1153 s2len = mono_string_length (s2);
1157 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1163 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1164 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1165 if (!is_ok (&error)) {
1166 mono_error_set_pending_exception (&error);
1169 values [count++] = o;
1170 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1171 if (!is_ok (&error)) {
1172 mono_error_set_pending_exception (&error);
1175 values [count++] = o;
1178 if (klass->enumtype)
1179 /* enums only have one non-static field */
1185 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1186 if (mono_error_set_pending_exception (&error))
1188 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1189 for (i = 0; i < count; ++i)
1190 mono_array_setref_fast (*fields, i, values [i]);
1197 ICALL_EXPORT MonoReflectionType *
1198 ves_icall_System_Object_GetType (MonoObject *obj)
1201 MonoReflectionType *ret;
1202 #ifndef DISABLE_REMOTING
1203 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1204 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1207 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1209 mono_error_set_pending_exception (&error);
1214 ves_icall_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_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4329 g_hash_table_destroy (properties);
4332 mono_ptr_array_destroy (tmp_array);
4334 mono_error_set_pending_exception (&error);
4340 event_hash (gconstpointer data)
4342 MonoEvent *event = (MonoEvent*)data;
4344 return g_str_hash (event->name);
4348 event_equal (MonoEvent *event1, MonoEvent *event2)
4350 // Events are hide-by-name
4351 return g_str_equal (event1->name, event2->name);
4354 ICALL_EXPORT MonoArray*
4355 ves_icall_RuntimeType_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4359 MonoClass *startklass, *klass;
4365 char *utf8_name = NULL;
4366 int (*compare_func) (const char *s1, const char *s2) = NULL;
4367 GHashTable *events = NULL;
4368 MonoPtrArray tmp_array;
4370 mono_error_init (&error);
4372 domain = mono_object_domain (type);
4373 if (type->type->byref) {
4374 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), 0, &error);
4375 mono_error_set_pending_exception (&error);
4379 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4381 klass = startklass = mono_class_from_mono_type (type->type);
4383 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4385 mono_class_setup_methods (klass);
4386 mono_class_setup_vtable (klass);
4387 if (mono_class_has_failure (klass))
4391 while ((event = mono_class_get_events (klass, &iter))) {
4393 method = event->add;
4395 method = event->remove;
4397 method = event->raise;
4399 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4400 if (bflags & BFLAGS_Public)
4402 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4403 if (bflags & BFLAGS_NonPublic)
4408 if (bflags & BFLAGS_NonPublic)
4414 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4415 if (bflags & BFLAGS_Static)
4416 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4419 if (bflags & BFLAGS_Instance)
4424 if (bflags & BFLAGS_Instance)
4430 if (utf8_name == NULL) {
4431 utf8_name = mono_string_to_utf8_checked (name, &error);
4432 if (!is_ok (&error))
4434 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4437 if (compare_func (event->name, utf8_name))
4441 if (g_hash_table_lookup (events, event))
4444 MonoReflectionEvent *ev_obj;
4445 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4448 mono_ptr_array_append (tmp_array, ev_obj);
4450 g_hash_table_insert (events, event, event);
4452 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4455 g_hash_table_destroy (events);
4457 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array), &error);
4458 if (!is_ok (&error))
4461 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4462 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4464 mono_ptr_array_destroy (tmp_array);
4466 if (utf8_name != NULL)
4472 if (mono_class_has_failure (klass)) {
4473 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4479 g_hash_table_destroy (events);
4480 if (utf8_name != NULL)
4483 mono_ptr_array_destroy (tmp_array);
4485 mono_error_set_pending_exception (&error);
4489 ICALL_EXPORT MonoArray*
4490 ves_icall_RuntimeType_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4493 MonoReflectionType *rt;
4496 MonoArray *res = NULL;
4501 MonoPtrArray tmp_array;
4503 mono_error_init (&error);
4505 domain = ((MonoObject *)type)->vtable->domain;
4506 if (type->type->byref) {
4507 MonoArray *result = mono_array_new_cached (domain, mono_defaults.runtimetype_class, 0, &error);
4508 mono_error_set_pending_exception (&error);
4511 klass = mono_class_from_mono_type (type->type);
4514 * If a nested type is generic, return its generic type definition.
4515 * Note that this means that the return value is essentially the set
4516 * of nested types of the generic type definition of @klass.
4518 * A note in MSDN claims that a generic type definition can have
4519 * nested types that aren't generic. In any case, the container of that
4520 * nested type would be the generic type definition.
4522 if (klass->generic_class)
4523 klass = klass->generic_class->container_class;
4525 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4527 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4529 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4530 if (bflags & BFLAGS_Public)
4533 if (bflags & BFLAGS_NonPublic)
4541 str = mono_string_to_utf8_checked (name, &error);
4542 if (!is_ok (&error))
4544 mono_identifier_unescape_type_name_chars (str);
4547 if (strcmp (nested->name, str))
4551 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4552 if (!is_ok (&error))
4555 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4558 res = mono_array_new_cached (domain, mono_defaults.runtimetype_class, mono_ptr_array_size (tmp_array), &error);
4559 if (!is_ok (&error))
4562 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4563 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4566 mono_ptr_array_destroy (tmp_array);
4570 mono_error_set_pending_exception (&error);
4574 ICALL_EXPORT MonoReflectionType*
4575 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4578 MonoReflectionType *ret;
4580 MonoType *type = NULL;
4581 MonoTypeNameParse info;
4582 gboolean type_resolve;
4584 /* On MS.NET, this does not fire a TypeResolve event */
4585 type_resolve = TRUE;
4586 str = mono_string_to_utf8_checked (name, &error);
4587 if (mono_error_set_pending_exception (&error))
4589 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4590 if (!mono_reflection_parse_type (str, &info)) {
4592 mono_reflection_free_type_info (&info);
4594 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4597 /*g_print ("failed parse\n");*/
4601 if (info.assembly.name) {
4603 mono_reflection_free_type_info (&info);
4605 /* 1.0 and 2.0 throw different exceptions */
4606 if (mono_defaults.generic_ilist_class)
4607 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4609 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4615 if (module != NULL) {
4616 if (module->image) {
4617 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4618 if (!is_ok (&error)) {
4620 mono_reflection_free_type_info (&info);
4621 mono_error_set_pending_exception (&error);
4628 if (assembly_is_dynamic (assembly->assembly)) {
4629 /* Enumerate all modules */
4630 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4634 if (abuilder->modules) {
4635 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4636 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4637 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4638 if (!is_ok (&error)) {
4640 mono_reflection_free_type_info (&info);
4641 mono_error_set_pending_exception (&error);
4649 if (!type && abuilder->loaded_modules) {
4650 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4651 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4652 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4653 if (!is_ok (&error)) {
4655 mono_reflection_free_type_info (&info);
4656 mono_error_set_pending_exception (&error);
4665 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4666 if (!is_ok (&error)) {
4668 mono_reflection_free_type_info (&info);
4669 mono_error_set_pending_exception (&error);
4674 mono_reflection_free_type_info (&info);
4676 MonoException *e = NULL;
4679 e = mono_get_exception_type_load (name, NULL);
4682 mono_set_pending_exception (e);
4686 if (type->type == MONO_TYPE_CLASS) {
4687 MonoClass *klass = mono_type_get_class (type);
4689 /* need to report exceptions ? */
4690 if (throwOnError && mono_class_has_failure (klass)) {
4691 /* report SecurityException (or others) that occured when loading the assembly */
4692 MonoException *exc = mono_class_get_exception_for_failure (klass);
4693 mono_set_pending_exception (exc);
4698 /* g_print ("got it\n"); */
4699 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4700 mono_error_set_pending_exception (&error);
4706 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4709 gchar *shadow_ini_file;
4712 /* Check for shadow-copied assembly */
4713 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4714 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4716 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4717 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4723 g_free (shadow_ini_file);
4724 if (content != NULL) {
4727 *filename = content;
4734 ICALL_EXPORT MonoString *
4735 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4737 MonoDomain *domain = mono_object_domain (assembly);
4738 MonoAssembly *mass = assembly->assembly;
4739 MonoString *res = NULL;
4744 if (g_path_is_absolute (mass->image->name)) {
4745 absolute = g_strdup (mass->image->name);
4746 dirname = g_path_get_dirname (absolute);
4748 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4749 dirname = g_strdup (mass->basedir);
4752 replace_shadow_path (domain, dirname, &absolute);
4757 for (i = strlen (absolute) - 1; i >= 0; i--)
4758 if (absolute [i] == '\\')
4763 uri = g_filename_to_uri (absolute, NULL, NULL);
4765 const char *prepend = "file://";
4767 if (*absolute == '/' && *(absolute + 1) == '/') {
4770 prepend = "file:///";
4773 uri = g_strconcat (prepend, absolute, NULL);
4777 res = mono_string_new (domain, uri);
4784 ICALL_EXPORT MonoBoolean
4785 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4787 MonoAssembly *mass = assembly->assembly;
4789 return mass->in_gac;
4792 ICALL_EXPORT MonoReflectionAssembly*
4793 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4798 MonoImageOpenStatus status;
4799 MonoReflectionAssembly* result = NULL;
4801 name = mono_string_to_utf8_checked (mname, &error);
4802 if (mono_error_set_pending_exception (&error))
4804 res = mono_assembly_load_with_partial_name (name, &status);
4810 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4812 mono_error_set_pending_exception (&error);
4816 ICALL_EXPORT MonoString *
4817 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4819 MonoDomain *domain = mono_object_domain (assembly);
4822 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4827 ICALL_EXPORT MonoBoolean
4828 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4830 return assembly->assembly->ref_only;
4833 ICALL_EXPORT MonoString *
4834 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4836 MonoDomain *domain = mono_object_domain (assembly);
4838 return mono_string_new (domain, assembly->assembly->image->version);
4841 ICALL_EXPORT MonoReflectionMethod*
4842 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4845 MonoReflectionMethod *res = NULL;
4848 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4852 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4853 if (!mono_error_ok (&error))
4856 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4859 if (!mono_error_ok (&error))
4860 mono_error_set_pending_exception (&error);
4864 ICALL_EXPORT MonoReflectionModule*
4865 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4868 MonoReflectionModule *result = NULL;
4869 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4870 if (!mono_error_ok (&error))
4871 mono_error_set_pending_exception (&error);
4875 ICALL_EXPORT MonoArray*
4876 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4879 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4880 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4881 if (mono_error_set_pending_exception (&error))
4886 for (i = 0; i < table->rows; ++i) {
4887 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4888 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4894 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4896 static MonoMethod *create_version = NULL;
4900 mono_error_init (error);
4903 if (!create_version) {
4904 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4905 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4906 g_assert (create_version);
4907 mono_method_desc_free (desc);
4913 args [3] = &revision;
4914 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4915 return_val_if_nok (error, NULL);
4917 mono_runtime_invoke_checked (create_version, result, args, error);
4918 return_val_if_nok (error, NULL);
4923 ICALL_EXPORT MonoArray*
4924 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4928 MonoDomain *domain = mono_object_domain (assembly);
4930 static MonoMethod *create_culture = NULL;
4931 MonoImage *image = assembly->assembly->image;
4935 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4938 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4939 if (mono_error_set_pending_exception (&error))
4943 if (count > 0 && !create_culture) {
4944 MonoMethodDesc *desc = mono_method_desc_new (
4945 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4946 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4947 g_assert (create_culture);
4948 mono_method_desc_free (desc);
4951 for (i = 0; i < count; i++) {
4952 MonoObject *version;
4953 MonoReflectionAssemblyName *aname;
4954 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4956 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4958 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4959 domain, mono_class_get_assembly_name_class (), &error);
4960 if (mono_error_set_pending_exception (&error))
4963 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4965 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4966 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4967 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4968 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4969 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4970 aname->versioncompat = 1; /* SameMachine (default) */
4971 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4973 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4974 if (mono_error_set_pending_exception (&error))
4977 MONO_OBJECT_SETREF (aname, version, version);
4979 if (create_culture) {
4981 MonoBoolean assembly_ref = 1;
4982 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4983 args [1] = &assembly_ref;
4985 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4986 if (mono_error_set_pending_exception (&error))
4989 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4992 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4993 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4994 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4996 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4997 /* public key token isn't copied - the class library will
4998 automatically generate it from the public key if required */
4999 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
5000 if (mono_error_set_pending_exception (&error))
5003 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5004 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
5006 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
5007 if (mono_error_set_pending_exception (&error))
5010 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5011 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
5014 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
5015 if (mono_error_set_pending_exception (&error))
5018 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5021 /* note: this function doesn't return the codebase on purpose (i.e. it can
5022 be used under partial trust as path information isn't present). */
5024 mono_array_setref (result, i, aname);
5029 /* move this in some file in mono/util/ */
5031 g_concat_dir_and_file (const char *dir, const char *file)
5033 g_return_val_if_fail (dir != NULL, NULL);
5034 g_return_val_if_fail (file != NULL, NULL);
5037 * If the directory name doesn't have a / on the end, we need
5038 * to add one so we get a proper path to the file
5040 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
5041 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
5043 return g_strconcat (dir, file, NULL);
5047 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
5050 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5052 guint32 cols [MONO_MANIFEST_SIZE];
5053 guint32 impl, file_idx;
5057 char *n = mono_string_to_utf8_checked (name, &error);
5058 if (mono_error_set_pending_exception (&error))
5061 for (i = 0; i < table->rows; ++i) {
5062 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5063 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5064 if (strcmp (val, n) == 0)
5068 if (i == table->rows)
5071 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
5074 * this code should only be called after obtaining the
5075 * ResourceInfo and handling the other cases.
5077 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
5078 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
5080 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
5085 module = assembly->assembly->image;
5088 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
5089 if (mono_error_set_pending_exception (&error))
5091 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
5093 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
5096 ICALL_EXPORT gboolean
5097 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
5100 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5102 guint32 cols [MONO_MANIFEST_SIZE];
5103 guint32 file_cols [MONO_FILE_SIZE];
5107 n = mono_string_to_utf8_checked (name, &error);
5108 if (mono_error_set_pending_exception (&error))
5110 for (i = 0; i < table->rows; ++i) {
5111 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5112 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5113 if (strcmp (val, n) == 0)
5117 if (i == table->rows)
5120 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
5121 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
5124 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
5125 case MONO_IMPLEMENTATION_FILE:
5126 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5127 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5128 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
5129 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
5130 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
5131 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
5134 info->location = RESOURCE_LOCATION_EMBEDDED;
5137 case MONO_IMPLEMENTATION_ASSEMBLYREF:
5138 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5139 mono_assembly_load_reference (assembly->assembly->image, i - 1);
5140 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
5141 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
5142 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
5144 mono_set_pending_exception (ex);
5147 MonoReflectionAssembly *assm_obj;
5148 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5150 mono_error_set_pending_exception (&error);
5153 MONO_OBJECT_SETREF (info, assembly, assm_obj);
5155 /* Obtain info recursively */
5156 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5157 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5160 case MONO_IMPLEMENTATION_EXP_TYPE:
5161 g_assert_not_reached ();
5169 ICALL_EXPORT MonoObject*
5170 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
5173 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5174 MonoArray *result = NULL;
5179 /* check hash if needed */
5181 n = mono_string_to_utf8_checked (name, &error);
5182 if (mono_error_set_pending_exception (&error))
5185 for (i = 0; i < table->rows; ++i) {
5186 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5187 if (strcmp (val, n) == 0) {
5190 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5191 fn = mono_string_new (mono_object_domain (assembly), n);
5193 return (MonoObject*)fn;
5201 for (i = 0; i < table->rows; ++i) {
5202 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5206 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
5207 if (mono_error_set_pending_exception (&error))
5212 for (i = 0; i < table->rows; ++i) {
5213 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5214 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5215 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5216 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5221 return (MonoObject*)result;
5224 ICALL_EXPORT MonoArray*
5225 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5228 MonoDomain *domain = mono_domain_get();
5231 int i, j, file_count = 0;
5232 MonoImage **modules;
5233 guint32 module_count, real_module_count;
5234 MonoTableInfo *table;
5235 guint32 cols [MONO_FILE_SIZE];
5236 MonoImage *image = assembly->assembly->image;
5238 g_assert (image != NULL);
5239 g_assert (!assembly_is_dynamic (assembly->assembly));
5241 table = &image->tables [MONO_TABLE_FILE];
5242 file_count = table->rows;
5244 modules = image->modules;
5245 module_count = image->module_count;
5247 real_module_count = 0;
5248 for (i = 0; i < module_count; ++i)
5250 real_module_count ++;
5252 klass = mono_class_get_module_class ();
5253 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5254 if (mono_error_set_pending_exception (&error))
5257 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5258 if (mono_error_set_pending_exception (&error))
5261 mono_array_setref (res, 0, image_obj);
5263 for (i = 0; i < module_count; ++i)
5265 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5266 if (mono_error_set_pending_exception (&error))
5268 mono_array_setref (res, j, rm);
5272 for (i = 0; i < file_count; ++i, ++j) {
5273 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5274 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5275 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5276 if (mono_error_set_pending_exception (&error))
5278 mono_array_setref (res, j, rm);
5281 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5283 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5284 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5287 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5288 if (mono_error_set_pending_exception (&error))
5290 mono_array_setref (res, j, rm);
5297 ICALL_EXPORT MonoReflectionMethod*
5298 ves_icall_GetCurrentMethod (void)
5300 MonoReflectionMethod *res = NULL;
5303 MonoMethod *m = mono_method_get_last_managed ();
5306 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5310 while (m->is_inflated)
5311 m = ((MonoMethodInflated*)m)->declaring;
5313 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5314 mono_error_set_pending_exception (&error);
5320 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5323 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5326 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5327 //method is inflated, we should inflate it on the other class
5328 MonoGenericContext ctx;
5329 ctx.method_inst = inflated->context.method_inst;
5330 ctx.class_inst = inflated->context.class_inst;
5331 if (klass->generic_class)
5332 ctx.class_inst = klass->generic_class->context.class_inst;
5333 else if (klass->generic_container)
5334 ctx.class_inst = klass->generic_container->context.class_inst;
5335 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5336 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5340 mono_class_setup_methods (method->klass);
5341 if (mono_class_has_failure (method->klass))
5343 for (i = 0; i < method->klass->method.count; ++i) {
5344 if (method->klass->methods [i] == method) {
5349 mono_class_setup_methods (klass);
5350 if (mono_class_has_failure (klass))
5352 g_assert (offset >= 0 && offset < klass->method.count);
5353 return klass->methods [offset];
5356 ICALL_EXPORT MonoReflectionMethod*
5357 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5359 MonoReflectionMethod *res = NULL;
5363 klass = mono_class_from_mono_type (type);
5364 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5366 if (method->klass != klass) {
5367 method = mono_method_get_equivalent_method (method, klass);
5372 klass = method->klass;
5373 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5374 mono_error_set_pending_exception (&error);
5378 ICALL_EXPORT MonoReflectionMethodBody*
5379 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5382 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5383 mono_error_set_pending_exception (&error);
5387 ICALL_EXPORT MonoReflectionAssembly*
5388 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5391 MonoReflectionAssembly *result;
5392 MonoMethod *dest = NULL;
5394 mono_stack_walk_no_il (get_executing, &dest);
5396 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5398 mono_error_set_pending_exception (&error);
5403 ICALL_EXPORT MonoReflectionAssembly*
5404 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5407 MonoReflectionAssembly *result;
5408 MonoDomain* domain = mono_domain_get ();
5410 if (!domain->entry_assembly)
5413 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5415 mono_error_set_pending_exception (&error);
5419 ICALL_EXPORT MonoReflectionAssembly*
5420 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5425 MonoReflectionAssembly *result;
5428 mono_stack_walk_no_il (get_executing, &dest);
5430 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5434 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5437 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5439 mono_error_set_pending_exception (&error);
5443 ICALL_EXPORT MonoString *
5444 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5445 gboolean assembly_qualified)
5447 MonoDomain *domain = mono_object_domain (object);
5448 MonoTypeNameFormat format;
5453 format = assembly_qualified ?
5454 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5455 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5457 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5459 name = mono_type_get_name_full (object->type, format);
5463 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5468 res = mono_string_new (domain, name);
5475 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5478 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5480 mono_class_init_checked (klass, &error);
5481 mono_error_set_pending_exception (&error);
5482 return mono_security_core_clr_class_level (klass);
5486 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5488 MonoClassField *field = rfield->field;
5489 return mono_security_core_clr_field_level (field, TRUE);
5493 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5495 MonoMethod *method = rfield->method;
5496 return mono_security_core_clr_method_level (method, TRUE);
5500 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)
5502 static MonoMethod *create_culture = NULL;
5506 const char *pkey_ptr;
5508 MonoBoolean assembly_ref = 0;
5510 mono_error_init (error);
5512 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5513 aname->major = name->major;
5514 aname->minor = name->minor;
5515 aname->build = name->build;
5516 aname->flags = name->flags;
5517 aname->revision = name->revision;
5518 aname->hashalg = name->hash_alg;
5519 aname->versioncompat = 1; /* SameMachine (default) */
5520 aname->processor_architecture = name->arch;
5522 if (by_default_version) {
5523 MonoObject *version;
5525 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5526 return_if_nok (error);
5528 MONO_OBJECT_SETREF (aname, version, version);
5532 if (absolute != NULL && *absolute != '\0') {
5533 const gchar *prepend = "file://";
5536 codebase = g_strdup (absolute);
5541 for (i = strlen (codebase) - 1; i >= 0; i--)
5542 if (codebase [i] == '\\')
5545 if (*codebase == '/' && *(codebase + 1) == '/') {
5548 prepend = "file:///";
5552 result = g_strconcat (prepend, codebase, NULL);
5558 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5562 if (!create_culture) {
5563 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5564 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5565 g_assert (create_culture);
5566 mono_method_desc_free (desc);
5569 if (name->culture) {
5570 args [0] = mono_string_new (domain, name->culture);
5571 args [1] = &assembly_ref;
5573 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5574 return_if_nok (error);
5576 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5579 if (name->public_key) {
5580 pkey_ptr = (char*)name->public_key;
5581 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5583 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5584 return_if_nok (error);
5585 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5586 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5587 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5588 } else if (default_publickey) {
5589 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5590 return_if_nok (error);
5591 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5592 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5595 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5596 if (name->public_key_token [0]) {
5600 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5601 return_if_nok (error);
5603 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5604 p = mono_array_addr (keyToken, char, 0);
5606 for (i = 0, j = 0; i < 8; i++) {
5607 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5608 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5611 } else if (default_token) {
5612 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5613 return_if_nok (error);
5614 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5618 ICALL_EXPORT MonoString *
5619 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5621 MonoDomain *domain = mono_object_domain (assembly);
5622 MonoAssembly *mass = assembly->assembly;
5626 name = mono_stringify_assembly_name (&mass->aname);
5627 res = mono_string_new (domain, name);
5634 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5638 MonoAssembly *mass = assembly->assembly;
5640 if (g_path_is_absolute (mass->image->name)) {
5641 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5642 mono_error_set_pending_exception (&error);
5645 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5647 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5648 mono_error_set_pending_exception (&error);
5654 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5658 MonoImageOpenStatus status = MONO_IMAGE_OK;
5661 MonoAssemblyName name;
5664 filename = mono_string_to_utf8_checked (fname, &error);
5665 if (mono_error_set_pending_exception (&error))
5668 dirname = g_path_get_dirname (filename);
5669 replace_shadow_path (mono_domain_get (), dirname, &filename);
5672 image = mono_image_open (filename, &status);
5678 if (status == MONO_IMAGE_IMAGE_INVALID)
5679 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5681 exc = mono_get_exception_file_not_found2 (NULL, fname);
5682 mono_set_pending_exception (exc);
5686 res = mono_assembly_fill_assembly_name (image, &name);
5688 mono_image_close (image);
5690 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5694 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5695 mono_error_set_pending_exception (&error);
5697 mono_image_close (image);
5701 ICALL_EXPORT MonoBoolean
5702 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5703 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5705 MonoBoolean result = FALSE;
5706 MonoDeclSecurityEntry entry;
5708 /* SecurityAction.RequestMinimum */
5709 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5710 *minimum = entry.blob;
5711 *minLength = entry.size;
5714 /* SecurityAction.RequestOptional */
5715 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5716 *optional = entry.blob;
5717 *optLength = entry.size;
5720 /* SecurityAction.RequestRefuse */
5721 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5722 *refused = entry.blob;
5723 *refLength = entry.size;
5731 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5733 guint32 attrs, visibility;
5735 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5736 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5737 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5740 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5746 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5748 MonoReflectionType *rt;
5751 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5754 mono_error_init (error);
5756 /* we start the count from 1 because we skip the special type <Module> */
5759 for (i = 1; i < tdef->rows; ++i) {
5760 if (mono_module_type_is_visible (tdef, image, i + 1))
5764 count = tdef->rows - 1;
5766 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5767 return_val_if_nok (error, NULL);
5768 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5769 return_val_if_nok (error, NULL);
5771 for (i = 1; i < tdef->rows; ++i) {
5772 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5773 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5776 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5777 return_val_if_nok (error, NULL);
5779 mono_array_setref (res, count, rt);
5781 MonoException *ex = mono_error_convert_to_exception (error);
5782 mono_array_setref (*exceptions, count, ex);
5791 ICALL_EXPORT MonoArray*
5792 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5795 MonoArray *res = NULL;
5796 MonoArray *exceptions = NULL;
5797 MonoImage *image = NULL;
5798 MonoTableInfo *table = NULL;
5801 int i, len, ex_count;
5803 domain = mono_object_domain (assembly);
5805 g_assert (!assembly_is_dynamic (assembly->assembly));
5806 image = assembly->assembly->image;
5807 table = &image->tables [MONO_TABLE_FILE];
5808 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5809 if (mono_error_set_pending_exception (&error))
5812 /* Append data from all modules in the assembly */
5813 for (i = 0; i < table->rows; ++i) {
5814 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5815 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5820 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5821 if (mono_error_set_pending_exception (&error))
5825 /* Append the new types to the end of the array */
5826 if (mono_array_length (res2) > 0) {
5828 MonoArray *res3, *ex3;
5830 len1 = mono_array_length (res);
5831 len2 = mono_array_length (res2);
5833 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5834 if (mono_error_set_pending_exception (&error))
5836 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5837 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5840 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5841 if (mono_error_set_pending_exception (&error))
5843 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5844 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5851 /* the ReflectionTypeLoadException must have all the types (Types property),
5852 * NULL replacing types which throws an exception. The LoaderException must
5853 * contain all exceptions for NULL items.
5856 len = mono_array_length (res);
5859 for (i = 0; i < len; i++) {
5860 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5864 klass = mono_type_get_class (t->type);
5865 if ((klass != NULL) && mono_class_has_failure (klass)) {
5866 /* keep the class in the list */
5867 list = g_list_append (list, klass);
5868 /* and replace Type with NULL */
5869 mono_array_setref (res, i, NULL);
5876 if (list || ex_count) {
5878 MonoException *exc = NULL;
5879 MonoArray *exl = NULL;
5880 int j, length = g_list_length (list) + ex_count;
5882 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5883 if (mono_error_set_pending_exception (&error)) {
5887 /* Types for which mono_class_get_checked () succeeded */
5888 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5889 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5890 mono_array_setref (exl, i, exc);
5892 /* Types for which it don't */
5893 for (j = 0; j < mono_array_length (exceptions); ++j) {
5894 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5896 g_assert (i < length);
5897 mono_array_setref (exl, i, exc);
5904 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5905 if (!is_ok (&error)) {
5906 mono_error_set_pending_exception (&error);
5909 mono_set_pending_exception (exc);
5916 ICALL_EXPORT gboolean
5917 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5920 MonoAssemblyName aname;
5921 MonoDomain *domain = mono_object_domain (name);
5923 gboolean is_version_defined;
5924 gboolean is_token_defined;
5926 aname.public_key = NULL;
5927 val = mono_string_to_utf8_checked (assname, &error);
5928 if (mono_error_set_pending_exception (&error))
5931 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5932 g_free ((guint8*) aname.public_key);
5937 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5938 mono_error_set_pending_exception (&error);
5940 mono_assembly_name_free (&aname);
5941 g_free ((guint8*) aname.public_key);
5947 ICALL_EXPORT MonoReflectionType*
5948 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5951 MonoReflectionType *ret;
5952 MonoDomain *domain = mono_object_domain (module);
5955 g_assert (module->image);
5957 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5958 /* These images do not have a global type */
5961 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5962 if (!mono_error_ok (&error)) {
5963 mono_error_set_pending_exception (&error);
5967 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5968 if (!mono_error_ok (&error)) {
5969 mono_error_set_pending_exception (&error);
5977 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5979 /*if (module->image)
5980 mono_image_close (module->image);*/
5983 ICALL_EXPORT MonoString*
5984 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5986 MonoDomain *domain = mono_object_domain (module);
5988 g_assert (module->image);
5989 return mono_string_new (domain, module->image->guid);
5992 ICALL_EXPORT gpointer
5993 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5996 if (module->image && module->image->is_module_handle)
5997 return module->image->raw_data;
6000 return (gpointer) (-1);
6004 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
6006 if (image_is_dynamic (image)) {
6007 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
6008 *pe_kind = dyn->pe_kind;
6009 *machine = dyn->machine;
6012 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
6013 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
6018 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
6020 return (image->md_version_major << 16) | (image->md_version_minor);
6023 ICALL_EXPORT MonoArray*
6024 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
6027 MonoArray *exceptions;
6030 if (!module->image) {
6031 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
6032 mono_error_set_pending_exception (&error);
6037 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
6038 if (mono_error_set_pending_exception (&error))
6041 for (i = 0; i < mono_array_length (exceptions); ++i) {
6042 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
6044 mono_set_pending_exception (ex);
6053 mono_memberref_is_method (MonoImage *image, guint32 token)
6055 if (!image_is_dynamic (image)) {
6056 guint32 cols [MONO_MEMBERREF_SIZE];
6058 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
6059 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
6060 mono_metadata_decode_blob_size (sig, &sig);
6061 return (*sig != 0x6);
6064 MonoClass *handle_class;
6066 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
6067 mono_error_cleanup (&error); /* just probing, ignore error */
6071 return mono_defaults.methodhandle_class == handle_class;
6076 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
6079 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
6080 mono_array_addr (type_args, MonoType*, 0));
6082 context->class_inst = NULL;
6084 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
6085 mono_array_addr (method_args, MonoType*, 0));
6087 context->method_inst = NULL;
6090 ICALL_EXPORT MonoType*
6091 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6094 int table = mono_metadata_token_table (token);
6095 int index = mono_metadata_token_index (token);
6096 MonoGenericContext context;
6099 *resolve_error = ResolveTokenError_Other;
6101 /* Validate token */
6102 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
6103 (table != MONO_TABLE_TYPESPEC)) {
6104 *resolve_error = ResolveTokenError_BadTable;
6108 if (image_is_dynamic (image)) {
6109 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
6110 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6111 mono_error_cleanup (&error);
6112 return klass ? &klass->byval_arg : NULL;
6115 init_generic_context_from_args (&context, type_args, method_args);
6116 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6117 mono_error_cleanup (&error);
6118 return klass ? &klass->byval_arg : NULL;
6121 if ((index <= 0) || (index > image->tables [table].rows)) {
6122 *resolve_error = ResolveTokenError_OutOfRange;
6126 init_generic_context_from_args (&context, type_args, method_args);
6127 klass = mono_class_get_checked (image, token, &error);
6129 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
6130 if (!mono_error_ok (&error)) {
6131 mono_error_set_pending_exception (&error);
6136 return &klass->byval_arg;
6141 ICALL_EXPORT MonoMethod*
6142 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6145 int table = mono_metadata_token_table (token);
6146 int index = mono_metadata_token_index (token);
6147 MonoGenericContext context;
6150 *resolve_error = ResolveTokenError_Other;
6152 /* Validate token */
6153 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
6154 (table != MONO_TABLE_MEMBERREF)) {
6155 *resolve_error = ResolveTokenError_BadTable;
6159 if (image_is_dynamic (image)) {
6160 if (table == MONO_TABLE_METHOD) {
6161 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6162 mono_error_cleanup (&error);
6166 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
6167 *resolve_error = ResolveTokenError_BadTable;
6171 init_generic_context_from_args (&context, type_args, method_args);
6172 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6173 mono_error_cleanup (&error);
6177 if ((index <= 0) || (index > image->tables [table].rows)) {
6178 *resolve_error = ResolveTokenError_OutOfRange;
6181 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6182 *resolve_error = ResolveTokenError_BadTable;
6186 init_generic_context_from_args (&context, type_args, method_args);
6187 method = mono_get_method_checked (image, token, NULL, &context, &error);
6188 mono_error_set_pending_exception (&error);
6193 ICALL_EXPORT MonoString*
6194 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6197 int index = mono_metadata_token_index (token);
6199 *resolve_error = ResolveTokenError_Other;
6201 /* Validate token */
6202 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6203 *resolve_error = ResolveTokenError_BadTable;
6207 if (image_is_dynamic (image)) {
6208 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6209 mono_error_cleanup (&error);
6213 if ((index <= 0) || (index >= image->heap_us.size)) {
6214 *resolve_error = ResolveTokenError_OutOfRange;
6218 /* FIXME: What to do if the index points into the middle of a string ? */
6220 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
6221 mono_error_set_pending_exception (&error);
6225 ICALL_EXPORT MonoClassField*
6226 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6230 int table = mono_metadata_token_table (token);
6231 int index = mono_metadata_token_index (token);
6232 MonoGenericContext context;
6233 MonoClassField *field;
6235 *resolve_error = ResolveTokenError_Other;
6237 /* Validate token */
6238 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6239 *resolve_error = ResolveTokenError_BadTable;
6243 if (image_is_dynamic (image)) {
6244 if (table == MONO_TABLE_FIELD) {
6245 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6246 mono_error_cleanup (&error);
6250 if (mono_memberref_is_method (image, token)) {
6251 *resolve_error = ResolveTokenError_BadTable;
6255 init_generic_context_from_args (&context, type_args, method_args);
6256 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6257 mono_error_cleanup (&error);
6261 if ((index <= 0) || (index > image->tables [table].rows)) {
6262 *resolve_error = ResolveTokenError_OutOfRange;
6265 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6266 *resolve_error = ResolveTokenError_BadTable;
6270 init_generic_context_from_args (&context, type_args, method_args);
6271 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6272 mono_error_set_pending_exception (&error);
6278 ICALL_EXPORT MonoObject*
6279 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6283 int table = mono_metadata_token_table (token);
6285 *error = ResolveTokenError_Other;
6288 case MONO_TABLE_TYPEDEF:
6289 case MONO_TABLE_TYPEREF:
6290 case MONO_TABLE_TYPESPEC: {
6291 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6293 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6294 mono_error_set_pending_exception (&merror);
6301 case MONO_TABLE_METHOD:
6302 case MONO_TABLE_METHODSPEC: {
6303 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6305 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6306 mono_error_set_pending_exception (&merror);
6312 case MONO_TABLE_FIELD: {
6313 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6315 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6316 mono_error_set_pending_exception (&merror);
6322 case MONO_TABLE_MEMBERREF:
6323 if (mono_memberref_is_method (image, token)) {
6324 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6326 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6327 mono_error_set_pending_exception (&merror);
6334 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6336 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6337 mono_error_set_pending_exception (&merror);
6346 *error = ResolveTokenError_BadTable;
6352 ICALL_EXPORT MonoArray*
6353 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6356 int table = mono_metadata_token_table (token);
6357 int idx = mono_metadata_token_index (token);
6358 MonoTableInfo *tables = image->tables;
6363 *resolve_error = ResolveTokenError_OutOfRange;
6365 /* FIXME: Support other tables ? */
6366 if (table != MONO_TABLE_STANDALONESIG)
6369 if (image_is_dynamic (image))
6372 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6375 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6377 ptr = mono_metadata_blob_heap (image, sig);
6378 len = mono_metadata_decode_blob_size (ptr, &ptr);
6380 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6381 if (mono_error_set_pending_exception (&error))
6383 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6387 ICALL_EXPORT MonoReflectionType*
6388 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6391 MonoReflectionType *ret;
6393 int isbyref = 0, rank;
6395 char *str = mono_string_to_utf8_checked (smodifiers, &error);
6396 if (mono_error_set_pending_exception (&error))
6399 klass = mono_class_from_mono_type (tb->type.type);
6401 /* logic taken from mono_reflection_parse_type(): keep in sync */
6405 if (isbyref) { /* only one level allowed by the spec */
6414 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6415 mono_error_set_pending_exception (&error);
6419 klass = mono_ptr_class_get (&klass->byval_arg);
6420 mono_class_init (klass);
6431 else if (*p != '*') { /* '*' means unknown lower bound */
6442 klass = mono_array_class_get (klass, rank);
6443 mono_class_init (klass);
6452 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6453 mono_error_set_pending_exception (&error);
6458 ICALL_EXPORT MonoBoolean
6459 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6465 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6471 check_for_invalid_type (MonoClass *klass, MonoError *error)
6476 mono_error_init (error);
6478 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6481 name = mono_type_get_full_name (klass);
6482 str = mono_string_new (mono_domain_get (), name);
6484 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6487 ICALL_EXPORT MonoReflectionType *
6488 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6491 MonoReflectionType *ret;
6492 MonoClass *klass, *aklass;
6494 klass = mono_class_from_mono_type (type->type);
6495 check_for_invalid_type (klass, &error);
6496 mono_error_set_pending_exception (&error);
6498 if (rank == 0) //single dimentional array
6499 aklass = mono_array_class_get (klass, 1);
6501 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6503 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6504 mono_error_set_pending_exception (&error);
6509 ICALL_EXPORT MonoReflectionType *
6510 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6513 MonoReflectionType *ret;
6516 klass = mono_class_from_mono_type (type->type);
6517 mono_class_init_checked (klass, &error);
6518 if (mono_error_set_pending_exception (&error))
6521 check_for_invalid_type (klass, &error);
6522 if (mono_error_set_pending_exception (&error))
6525 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6526 mono_error_set_pending_exception (&error);
6531 ICALL_EXPORT MonoReflectionType *
6532 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6535 MonoReflectionType *ret;
6536 MonoClass *klass, *pklass;
6538 klass = mono_class_from_mono_type (type->type);
6539 mono_class_init_checked (klass, &error);
6540 if (mono_error_set_pending_exception (&error))
6542 check_for_invalid_type (klass, &error);
6543 if (mono_error_set_pending_exception (&error))
6546 pklass = mono_ptr_class_get (type->type);
6548 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6549 mono_error_set_pending_exception (&error);
6554 ICALL_EXPORT MonoObject *
6555 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6556 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6559 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6560 MonoObject *delegate;
6562 MonoMethod *method = info->method;
6564 mono_class_init_checked (delegate_class, &error);
6565 if (mono_error_set_pending_exception (&error))
6568 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6569 /* FIXME improve this exception message */
6570 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6572 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6573 mono_error_set_pending_exception (&error);
6577 if (mono_security_core_clr_enabled ()) {
6578 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6579 if (throwOnBindFailure)
6580 mono_error_set_pending_exception (&error);
6582 mono_error_cleanup (&error);
6587 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6588 if (mono_error_set_pending_exception (&error))
6591 if (method_is_dynamic (method)) {
6592 /* Creating a trampoline would leak memory */
6593 func = mono_compile_method_checked (method, &error);
6594 if (mono_error_set_pending_exception (&error))
6597 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6598 method = mono_object_get_virtual_method (target, method);
6599 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6600 if (mono_error_set_pending_exception (&error))
6602 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6605 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6606 if (mono_error_set_pending_exception (&error))
6611 ICALL_EXPORT MonoMulticastDelegate *
6612 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6615 MonoMulticastDelegate *ret;
6617 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6619 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6620 if (mono_error_set_pending_exception (&error))
6623 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6628 ICALL_EXPORT MonoReflectionMethod*
6629 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6631 MonoReflectionMethod *ret = NULL;
6633 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6634 mono_error_set_pending_exception (&error);
6640 static inline gint32
6641 mono_array_get_byte_length (MonoArray *array)
6647 klass = array->obj.vtable->klass;
6649 if (array->bounds == NULL)
6650 length = array->max_length;
6653 for (i = 0; i < klass->rank; ++ i)
6654 length *= array->bounds [i].length;
6657 switch (klass->element_class->byval_arg.type) {
6660 case MONO_TYPE_BOOLEAN:
6664 case MONO_TYPE_CHAR:
6672 return length * sizeof (gpointer);
6683 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6685 return mono_array_get_byte_length (array);
6689 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6691 return mono_array_get (array, gint8, idx);
6695 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6697 mono_array_set (array, gint8, idx, value);
6700 ICALL_EXPORT MonoBoolean
6701 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6703 guint8 *src_buf, *dest_buf;
6706 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6710 g_assert (count >= 0);
6712 /* This is called directly from the class libraries without going through the managed wrapper */
6713 MONO_CHECK_ARG_NULL (src, FALSE);
6714 MONO_CHECK_ARG_NULL (dest, FALSE);
6716 /* watch out for integer overflow */
6717 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6720 src_buf = (guint8 *)src->vector + src_offset;
6721 dest_buf = (guint8 *)dest->vector + dest_offset;
6724 memcpy (dest_buf, src_buf, count);
6726 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6731 #ifndef DISABLE_REMOTING
6732 ICALL_EXPORT MonoObject *
6733 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6736 MonoDomain *domain = mono_object_domain (this_obj);
6738 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6739 MonoTransparentProxy *tp;
6743 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6744 if (mono_error_set_pending_exception (&error))
6747 tp = (MonoTransparentProxy*) res;
6749 MONO_OBJECT_SETREF (tp, rp, rp);
6750 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6751 klass = mono_class_from_mono_type (type);
6753 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6754 mono_class_setup_vtable (klass);
6755 if (mono_class_has_failure (klass)) {
6756 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6760 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6761 if (mono_error_set_pending_exception (&error))
6763 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6764 if (mono_error_set_pending_exception (&error))
6767 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6768 if (mono_error_set_pending_exception (&error))
6773 ICALL_EXPORT MonoReflectionType *
6774 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6777 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6778 mono_error_set_pending_exception (&error);
6784 /* System.Environment */
6787 ves_icall_System_Environment_get_UserName (void)
6789 /* using glib is more portable */
6790 return mono_string_new (mono_domain_get (), g_get_user_name ());
6794 ICALL_EXPORT MonoString *
6795 ves_icall_System_Environment_get_MachineName (void)
6797 #if defined (HOST_WIN32)
6802 len = MAX_COMPUTERNAME_LENGTH + 1;
6803 buf = g_new (gunichar2, len);
6806 if (GetComputerName (buf, (PDWORD) &len)) {
6808 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6809 mono_error_set_pending_exception (&error);
6814 #elif !defined(DISABLE_SOCKETS)
6818 #if defined _SC_HOST_NAME_MAX
6819 n = sysconf (_SC_HOST_NAME_MAX);
6823 buf = g_malloc (n+1);
6825 if (gethostname (buf, n) == 0){
6827 result = mono_string_new (mono_domain_get (), buf);
6834 return mono_string_new (mono_domain_get (), "mono");
6839 ves_icall_System_Environment_get_Platform (void)
6841 #if defined (TARGET_WIN32)
6844 #elif defined(__MACH__)
6847 // Notice that the value is hidden from user code, and only exposed
6848 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6849 // define and making assumptions based on Unix/128/4 values before there
6850 // was a MacOS define. Lots of code would assume that not-Unix meant
6851 // Windows, but in this case, it would be OSX.
6860 ICALL_EXPORT MonoString *
6861 ves_icall_System_Environment_get_NewLine (void)
6863 #if defined (HOST_WIN32)
6864 return mono_string_new (mono_domain_get (), "\r\n");
6866 return mono_string_new (mono_domain_get (), "\n");
6870 ICALL_EXPORT MonoBoolean
6871 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6873 #if SIZEOF_VOID_P == 8
6877 gboolean isWow64Process = FALSE;
6878 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6879 return (MonoBoolean)isWow64Process;
6881 #elif defined(HAVE_SYS_UTSNAME_H)
6882 struct utsname name;
6884 if (uname (&name) >= 0) {
6885 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6892 ICALL_EXPORT MonoString *
6893 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6902 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6903 if (mono_error_set_pending_exception (&error))
6905 value = g_getenv (utf8_name);
6912 return mono_string_new (mono_domain_get (), value);
6916 * There is no standard way to get at environ.
6919 #ifndef __MINGW32_VERSION
6920 #if defined(__APPLE__)
6921 #if defined (TARGET_OSX)
6922 /* Apple defines this in crt_externs.h but doesn't provide that header for
6923 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6924 * in fact exist on all implementations (so far)
6926 gchar ***_NSGetEnviron(void);
6927 #define environ (*_NSGetEnviron())
6929 static char *mono_environ[1] = { NULL };
6930 #define environ mono_environ
6931 #endif /* defined (TARGET_OSX) */
6939 ICALL_EXPORT MonoArray *
6940 ves_icall_System_Environment_GetCoomandLineArgs (void)
6943 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6944 mono_error_set_pending_exception (&error);
6948 ICALL_EXPORT MonoArray *
6949 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6961 env_strings = GetEnvironmentStrings();
6964 env_string = env_strings;
6965 while (*env_string != '\0') {
6966 /* weird case that MS seems to skip */
6967 if (*env_string != '=')
6969 while (*env_string != '\0')
6975 domain = mono_domain_get ();
6976 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6977 if (mono_error_set_pending_exception (&error))
6982 env_string = env_strings;
6983 while (*env_string != '\0') {
6984 /* weird case that MS seems to skip */
6985 if (*env_string != '=') {
6986 equal_str = wcschr(env_string, '=');
6987 g_assert(equal_str);
6989 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6990 if (mono_error_set_pending_exception (&error))
6993 mono_array_setref (names, n, str);
6996 while (*env_string != '\0')
7001 FreeEnvironmentStrings (env_strings);
7015 for (e = environ; *e != 0; ++ e)
7018 domain = mono_domain_get ();
7019 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
7020 if (mono_error_set_pending_exception (&error))
7024 for (e = environ; *e != 0; ++ e) {
7025 parts = g_strsplit (*e, "=", 2);
7027 str = mono_string_new (domain, *parts);
7028 mono_array_setref (names, n, str);
7041 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
7044 gunichar2 *utf16_name, *utf16_value;
7046 gchar *utf8_name, *utf8_value;
7051 utf16_name = mono_string_to_utf16 (name);
7052 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7053 SetEnvironmentVariable (utf16_name, NULL);
7054 g_free (utf16_name);
7058 utf16_value = mono_string_to_utf16 (value);
7060 SetEnvironmentVariable (utf16_name, utf16_value);
7062 g_free (utf16_name);
7063 g_free (utf16_value);
7065 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
7066 if (mono_error_set_pending_exception (&error))
7069 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7070 g_unsetenv (utf8_name);
7075 utf8_value = mono_string_to_utf8_checked (value, &error);
7076 if (!mono_error_ok (&error)) {
7078 mono_error_set_pending_exception (&error);
7081 g_setenv (utf8_name, utf8_value, TRUE);
7084 g_free (utf8_value);
7089 ves_icall_System_Environment_Exit (int result)
7091 mono_environment_exitcode_set (result);
7093 /* FIXME: There are some cleanup hangs that should be worked out, but
7094 * if the program is going to exit, everything will be cleaned up when
7095 * NaCl exits anyway.
7097 #ifndef __native_client__
7098 if (!mono_runtime_try_shutdown ())
7099 mono_thread_exit ();
7101 /* Suspend all managed threads since the runtime is going away */
7102 mono_thread_suspend_all_other_threads ();
7104 mono_runtime_quit ();
7107 /* we may need to do some cleanup here... */
7111 ICALL_EXPORT MonoString*
7112 ves_icall_System_Environment_GetGacPath (void)
7114 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
7117 ICALL_EXPORT MonoString*
7118 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
7120 #if defined (HOST_WIN32)
7121 #ifndef CSIDL_FLAG_CREATE
7122 #define CSIDL_FLAG_CREATE 0x8000
7125 WCHAR path [MAX_PATH];
7126 /* Create directory if no existing */
7127 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
7132 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
7133 mono_error_set_pending_exception (&error);
7137 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7139 return mono_string_new (mono_domain_get (), "");
7142 ICALL_EXPORT MonoArray *
7143 ves_icall_System_Environment_GetLogicalDrives (void)
7146 gunichar2 buf [256], *ptr, *dname;
7148 guint initial_size = 127, size = 128;
7151 MonoString *drivestr;
7152 MonoDomain *domain = mono_domain_get ();
7158 while (size > initial_size) {
7159 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
7160 if (size > initial_size) {
7163 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7164 initial_size = size;
7178 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7179 if (mono_error_set_pending_exception (&error))
7186 while (*u16) { u16++; len ++; }
7187 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7188 if (mono_error_set_pending_exception (&error))
7191 mono_array_setref (result, ndrives++, drivestr);
7202 ICALL_EXPORT MonoString *
7203 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7206 gunichar2 volume_name [MAX_PATH + 1];
7208 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7210 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
7211 mono_error_set_pending_exception (&error);
7215 ICALL_EXPORT MonoString *
7216 ves_icall_System_Environment_InternalGetHome (void)
7218 return mono_string_new (mono_domain_get (), g_get_home_dir ());
7221 static const char *encodings [] = {
7223 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7224 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7225 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7227 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7228 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7229 "x_unicode_2_0_utf_7",
7231 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7232 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7234 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7237 "unicodefffe", "utf_16be",
7244 * Returns the internal codepage, if the value of "int_code_page" is
7245 * 1 at entry, and we can not compute a suitable code page number,
7246 * returns the code page as a string
7248 ICALL_EXPORT MonoString*
7249 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
7254 char *codepage = NULL;
7256 int want_name = *int_code_page;
7259 *int_code_page = -1;
7261 g_get_charset (&cset);
7262 c = codepage = strdup (cset);
7263 for (c = codepage; *c; c++){
7264 if (isascii (*c) && isalpha (*c))
7269 /* g_print ("charset: %s\n", cset); */
7271 /* handle some common aliases */
7274 for (i = 0; p != 0; ){
7277 p = encodings [++i];
7280 if (strcmp (p, codepage) == 0){
7281 *int_code_page = code;
7284 p = encodings [++i];
7287 if (strstr (codepage, "utf_8") != NULL)
7288 *int_code_page |= 0x10000000;
7291 if (want_name && *int_code_page == -1)
7292 return mono_string_new (mono_domain_get (), cset);
7297 ICALL_EXPORT MonoBoolean
7298 ves_icall_System_Environment_get_HasShutdownStarted (void)
7300 if (mono_runtime_is_shutting_down ())
7303 if (mono_domain_is_unloading (mono_domain_get ()))
7310 ves_icall_System_Environment_BroadcastSettingChange (void)
7313 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7319 ves_icall_System_Environment_get_TickCount (void)
7321 /* this will overflow after ~24 days */
7322 return (gint32) (mono_msec_boottime () & 0xffffffff);
7326 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7332 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
7333 MonoReflectionMethod *method,
7334 MonoArray *out_args)
7337 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args, &error);
7338 mono_error_set_pending_exception (&error);
7341 #ifndef DISABLE_REMOTING
7342 ICALL_EXPORT MonoBoolean
7343 ves_icall_IsTransparentProxy (MonoObject *proxy)
7348 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7354 ICALL_EXPORT MonoReflectionMethod *
7355 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7356 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7358 MonoReflectionMethod *ret = NULL;
7363 MonoMethod **vtable;
7364 MonoMethod *res = NULL;
7366 MONO_CHECK_ARG_NULL (rtype, NULL);
7367 MONO_CHECK_ARG_NULL (rmethod, NULL);
7369 method = rmethod->method;
7370 klass = mono_class_from_mono_type (rtype->type);
7371 mono_class_init_checked (klass, &error);
7372 if (mono_error_set_pending_exception (&error))
7375 if (MONO_CLASS_IS_INTERFACE (klass))
7378 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7381 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7382 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7388 mono_class_setup_vtable (klass);
7389 vtable = klass->vtable;
7391 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7392 gboolean variance_used = FALSE;
7393 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7394 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7396 res = vtable [offs + method->slot];
7398 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7401 if (method->slot != -1)
7402 res = vtable [method->slot];
7408 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7409 mono_error_set_pending_exception (&error);
7414 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7420 klass = mono_class_from_mono_type (type->type);
7421 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7422 if (!is_ok (&error)) {
7423 mono_error_set_pending_exception (&error);
7427 mono_vtable_set_is_remote (vtable, enable);
7430 #else /* DISABLE_REMOTING */
7433 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7435 g_assert_not_reached ();
7440 ICALL_EXPORT MonoObject *
7441 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7448 domain = mono_object_domain (type);
7449 klass = mono_class_from_mono_type (type->type);
7450 mono_class_init_checked (klass, &error);
7451 if (mono_error_set_pending_exception (&error))
7454 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7455 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7459 if (klass->rank >= 1) {
7460 g_assert (klass->rank == 1);
7461 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7462 mono_error_set_pending_exception (&error);
7465 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7466 if (!is_ok (&error)) {
7467 mono_error_set_pending_exception (&error);
7470 /* Bypass remoting object creation check */
7471 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7472 mono_error_set_pending_exception (&error);
7478 ICALL_EXPORT MonoString *
7479 ves_icall_System_IO_get_temp_path (void)
7481 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7484 #ifndef PLATFORM_NO_DRIVEINFO
7485 ICALL_EXPORT MonoBoolean
7486 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7487 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7491 ULARGE_INTEGER wapi_free_bytes_avail;
7492 ULARGE_INTEGER wapi_total_number_of_bytes;
7493 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7495 *error = ERROR_SUCCESS;
7496 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7497 &wapi_total_number_of_free_bytes);
7500 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7501 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7502 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7504 *free_bytes_avail = 0;
7505 *total_number_of_bytes = 0;
7506 *total_number_of_free_bytes = 0;
7507 *error = GetLastError ();
7513 ICALL_EXPORT guint32
7514 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7516 return GetDriveType (mono_string_chars (root_path_name));
7520 ICALL_EXPORT gpointer
7521 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7524 gpointer result = mono_compile_method_checked (method, &error);
7525 mono_error_set_pending_exception (&error);
7529 ICALL_EXPORT MonoString *
7530 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7535 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7537 #if defined (HOST_WIN32)
7538 /* Avoid mixing '/' and '\\' */
7541 for (i = strlen (path) - 1; i >= 0; i--)
7542 if (path [i] == '/')
7546 mcpath = mono_string_new (mono_domain_get (), path);
7552 /* this is an icall */
7554 get_bundled_app_config (void)
7557 const gchar *app_config;
7560 gchar *config_file_name, *config_file_path;
7561 gsize len, config_file_path_length, config_ext_length;
7564 domain = mono_domain_get ();
7565 file = domain->setup->configuration_file;
7566 if (!file || file->length == 0)
7569 // Retrieve config file and remove the extension
7570 config_file_name = mono_string_to_utf8_checked (file, &error);
7571 if (mono_error_set_pending_exception (&error))
7573 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7574 if (!config_file_path)
7575 config_file_path = config_file_name;
7577 config_file_path_length = strlen (config_file_path);
7578 config_ext_length = strlen (".config");
7579 if (config_file_path_length <= config_ext_length)
7582 len = config_file_path_length - config_ext_length;
7583 module = (gchar *)g_malloc0 (len + 1);
7584 memcpy (module, config_file_path, len);
7585 // Get the config file from the module name
7586 app_config = mono_config_string_for_assembly_file (module);
7589 if (config_file_name != config_file_path)
7590 g_free (config_file_name);
7591 g_free (config_file_path);
7596 return mono_string_new (mono_domain_get (), app_config);
7600 get_bundled_machine_config (void)
7602 const gchar *machine_config;
7604 machine_config = mono_get_machine_config ();
7606 if (!machine_config)
7609 return mono_string_new (mono_domain_get (), machine_config);
7612 ICALL_EXPORT MonoString *
7613 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7618 path = g_path_get_dirname (mono_get_config_dir ());
7620 #if defined (HOST_WIN32)
7621 /* Avoid mixing '/' and '\\' */
7624 for (i = strlen (path) - 1; i >= 0; i--)
7625 if (path [i] == '/')
7629 ipath = mono_string_new (mono_domain_get (), path);
7635 ICALL_EXPORT gboolean
7636 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7638 MonoPEResourceDataEntry *entry;
7641 if (!assembly || !result || !size)
7646 image = assembly->assembly->image;
7647 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7651 *result = mono_image_rva_map (image, entry->rde_data_offset);
7656 *size = entry->rde_size;
7661 ICALL_EXPORT MonoBoolean
7662 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7664 return mono_is_debugger_attached ();
7667 ICALL_EXPORT MonoBoolean
7668 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7670 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7671 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7677 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7679 if (mono_get_runtime_callbacks ()->debug_log)
7680 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7684 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7686 #if defined (HOST_WIN32)
7687 OutputDebugString (mono_string_chars (message));
7689 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7693 /* Only used for value types */
7694 ICALL_EXPORT MonoObject *
7695 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7702 domain = mono_object_domain (type);
7703 klass = mono_class_from_mono_type (type->type);
7704 mono_class_init_checked (klass, &error);
7705 if (mono_error_set_pending_exception (&error))
7708 if (mono_class_is_nullable (klass))
7709 /* No arguments -> null */
7712 result = mono_object_new_checked (domain, klass, &error);
7713 mono_error_set_pending_exception (&error);
7717 ICALL_EXPORT MonoReflectionMethod *
7718 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7720 MonoReflectionMethod *ret = NULL;
7723 MonoClass *klass, *parent;
7724 MonoGenericContext *generic_inst = NULL;
7725 MonoMethod *method = m->method;
7726 MonoMethod *result = NULL;
7729 if (method->klass == NULL)
7732 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7733 MONO_CLASS_IS_INTERFACE (method->klass) ||
7734 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7737 slot = mono_method_get_vtable_slot (method);
7741 klass = method->klass;
7742 if (klass->generic_class) {
7743 generic_inst = mono_class_get_context (klass);
7744 klass = klass->generic_class->container_class;
7748 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7749 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7750 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7751 or klass is the generic container class and generic_inst is the instantiation.
7753 when we go to the parent, if the parent is an open constructed type, we need to
7754 replace the type parameters by the definitions from the generic_inst, and then take it
7755 apart again into the klass and the generic_inst.
7757 For cases like this:
7758 class C<T> : B<T, int> {
7759 public override void Foo () { ... }
7761 class B<U,V> : A<HashMap<U,V>> {
7762 public override void Foo () { ... }
7765 public virtual void Foo () { ... }
7768 if at each iteration the parent isn't open, we can skip inflating it. if at some
7769 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7772 MonoGenericContext *parent_inst = NULL;
7773 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7774 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7775 if (!mono_error_ok (&error)) {
7776 mono_error_set_pending_exception (&error);
7780 if (parent->generic_class) {
7781 parent_inst = mono_class_get_context (parent);
7782 parent = parent->generic_class->container_class;
7785 mono_class_setup_vtable (parent);
7786 if (parent->vtable_size <= slot)
7789 generic_inst = parent_inst;
7792 klass = klass->parent;
7795 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7796 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7797 if (!mono_error_ok (&error)) {
7798 mono_error_set_pending_exception (&error);
7802 generic_inst = NULL;
7804 if (klass->generic_class) {
7805 generic_inst = mono_class_get_context (klass);
7806 klass = klass->generic_class->container_class;
7812 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7813 if (!mono_error_ok (&error)) {
7814 mono_error_set_pending_exception (&error);
7819 if (klass == method->klass)
7822 /*This is possible if definition == FALSE.
7823 * Do it here to be really sure we don't read invalid memory.
7825 if (slot >= klass->vtable_size)
7828 mono_class_setup_vtable (klass);
7830 result = klass->vtable [slot];
7831 if (result == NULL) {
7832 /* It is an abstract method */
7833 gpointer iter = NULL;
7834 while ((result = mono_class_get_methods (klass, &iter)))
7835 if (result->slot == slot)
7842 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7843 mono_error_set_pending_exception (&error);
7847 ICALL_EXPORT MonoString*
7848 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7850 MonoMethod *method = m->method;
7852 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7857 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7859 iter->sig = *(MonoMethodSignature**)argsp;
7861 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7862 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7865 /* FIXME: it's not documented what start is exactly... */
7869 iter->args = argsp + sizeof (gpointer);
7871 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7873 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7876 ICALL_EXPORT MonoTypedRef
7877 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7879 guint32 i, arg_size;
7883 i = iter->sig->sentinelpos + iter->next_arg;
7885 g_assert (i < iter->sig->param_count);
7887 res.type = iter->sig->params [i];
7888 res.klass = mono_class_from_mono_type (res.type);
7889 arg_size = mono_type_stack_size (res.type, &align);
7890 #if defined(__arm__) || defined(__mips__)
7891 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7893 res.value = iter->args;
7894 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7895 /* Values are stored as 8 byte register sized objects, but 'value'
7896 * is dereferenced as a pointer in other routines.
7898 res.value = (char*)res.value + 4;
7900 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7901 if (arg_size <= sizeof (gpointer)) {
7903 int padding = arg_size - mono_type_size (res.type, &dummy);
7904 res.value = (guint8*)res.value + padding;
7907 iter->args = (char*)iter->args + arg_size;
7910 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7915 ICALL_EXPORT MonoTypedRef
7916 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7918 guint32 i, arg_size;
7922 i = iter->sig->sentinelpos + iter->next_arg;
7924 g_assert (i < iter->sig->param_count);
7926 while (i < iter->sig->param_count) {
7927 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7929 res.type = iter->sig->params [i];
7930 res.klass = mono_class_from_mono_type (res.type);
7931 /* FIXME: endianess issue... */
7932 arg_size = mono_type_stack_size (res.type, &align);
7933 #if defined(__arm__) || defined(__mips__)
7934 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7936 res.value = iter->args;
7937 iter->args = (char*)iter->args + arg_size;
7939 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7942 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7950 ICALL_EXPORT MonoType*
7951 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7955 i = iter->sig->sentinelpos + iter->next_arg;
7957 g_assert (i < iter->sig->param_count);
7959 return iter->sig->params [i];
7962 ICALL_EXPORT MonoObject*
7963 mono_TypedReference_ToObject (MonoTypedRef* tref)
7966 MonoObject *result = NULL;
7967 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7968 MonoObject** objp = (MonoObject **)tref->value;
7972 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7973 mono_error_set_pending_exception (&error);
7977 ICALL_EXPORT MonoTypedRef
7978 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7981 MonoReflectionField *f;
7983 MonoType *ftype = NULL;
7987 memset (&res, 0, sizeof (res));
7990 g_assert (mono_array_length (fields) > 0);
7992 klass = target->vtable->klass;
7994 for (i = 0; i < mono_array_length (fields); ++i) {
7995 f = mono_array_get (fields, MonoReflectionField*, i);
7997 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
8000 if (f->field->parent != klass) {
8001 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
8005 p = (guint8*)target + f->field->offset;
8007 p += f->field->offset - sizeof (MonoObject);
8008 klass = mono_class_from_mono_type (f->field->type);
8009 ftype = f->field->type;
8013 res.klass = mono_class_from_mono_type (ftype);
8020 prelink_method (MonoMethod *method, MonoError *error)
8022 const char *exc_class, *exc_arg;
8024 mono_error_init (error);
8025 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
8027 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
8029 mono_error_set_exception_instance (error,
8030 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
8033 /* create the wrapper, too? */
8037 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
8041 prelink_method (method->method, &error);
8042 mono_error_set_pending_exception (&error);
8046 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
8049 MonoClass *klass = mono_class_from_mono_type (type->type);
8051 gpointer iter = NULL;
8053 mono_class_init_checked (klass, &error);
8054 if (mono_error_set_pending_exception (&error))
8057 while ((m = mono_class_get_methods (klass, &iter))) {
8058 prelink_method (m, &error);
8059 if (mono_error_set_pending_exception (&error))
8064 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
8066 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
8067 gint32 const **exponents,
8068 gunichar2 const **digitLowerTable,
8069 gunichar2 const **digitUpperTable,
8070 gint64 const **tenPowersList,
8071 gint32 const **decHexDigits)
8073 *mantissas = Formatter_MantissaBitsTable;
8074 *exponents = Formatter_TensExponentTable;
8075 *digitLowerTable = Formatter_DigitLowerTable;
8076 *digitUpperTable = Formatter_DigitUpperTable;
8077 *tenPowersList = Formatter_TenPowersList;
8078 *decHexDigits = Formatter_DecHexDigits;
8082 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
8083 * and avoid useless allocations.
8086 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
8088 MonoReflectionType *rt;
8092 mono_error_init (error);
8093 for (i = 0; i < type->num_mods; ++i) {
8094 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
8099 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
8100 return_val_if_nok (error, NULL);
8102 for (i = 0; i < type->num_mods; ++i) {
8103 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
8104 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
8105 return_val_if_nok (error, NULL);
8107 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8108 return_val_if_nok (error, NULL);
8110 mono_array_setref (res, count, rt);
8117 ICALL_EXPORT MonoArray*
8118 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
8121 MonoType *type = param->ClassImpl->type;
8122 MonoClass *member_class = mono_object_class (param->MemberImpl);
8123 MonoMethod *method = NULL;
8126 MonoMethodSignature *sig;
8129 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8130 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8131 method = rmethod->method;
8132 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
8133 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8134 if (!(method = prop->property->get))
8135 method = prop->property->set;
8138 char *type_name = mono_type_get_full_name (member_class);
8139 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
8140 MonoException *ex = mono_get_exception_not_supported (msg);
8143 mono_set_pending_exception (ex);
8147 image = method->klass->image;
8148 pos = param->PositionImpl;
8149 sig = mono_method_signature (method);
8153 type = sig->params [pos];
8155 res = type_array_from_modifiers (image, type, optional, &error);
8156 mono_error_set_pending_exception (&error);
8161 get_property_type (MonoProperty *prop)
8163 MonoMethodSignature *sig;
8165 sig = mono_method_signature (prop->get);
8167 } else if (prop->set) {
8168 sig = mono_method_signature (prop->set);
8169 return sig->params [sig->param_count - 1];
8174 ICALL_EXPORT MonoArray*
8175 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
8178 MonoType *type = get_property_type (property->property);
8179 MonoImage *image = property->klass->image;
8184 res = type_array_from_modifiers (image, type, optional, &error);
8185 mono_error_set_pending_exception (&error);
8190 *Construct a MonoType suited to be used to decode a constant blob object.
8192 * @type is the target type which will be constructed
8193 * @blob_type is the blob type, for example, that comes from the constant table
8194 * @real_type is the expected constructed type.
8197 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8199 type->type = blob_type;
8200 type->data.klass = NULL;
8201 if (blob_type == MONO_TYPE_CLASS)
8202 type->data.klass = mono_defaults.object_class;
8203 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8204 /* For enums, we need to use the base type */
8205 type->type = MONO_TYPE_VALUETYPE;
8206 type->data.klass = mono_class_from_mono_type (real_type);
8208 type->data.klass = mono_class_from_mono_type (real_type);
8211 ICALL_EXPORT MonoObject*
8212 property_info_get_default_value (MonoReflectionProperty *property)
8216 MonoProperty *prop = property->property;
8217 MonoType *type = get_property_type (prop);
8218 MonoDomain *domain = mono_object_domain (property);
8219 MonoTypeEnum def_type;
8220 const char *def_value;
8223 mono_class_init (prop->parent);
8225 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8226 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8230 def_value = mono_class_get_property_default_value (prop, &def_type);
8232 mono_type_from_blob_type (&blob_type, def_type, type);
8233 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8235 mono_error_set_pending_exception (&error);
8239 ICALL_EXPORT MonoBoolean
8240 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8243 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8244 MonoCustomAttrInfo *cinfo;
8247 mono_class_init_checked (attr_class, &error);
8248 if (mono_error_set_pending_exception (&error))
8251 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8252 if (!is_ok (&error)) {
8253 mono_error_set_pending_exception (&error);
8258 found = mono_custom_attrs_has_attr (cinfo, attr_class);
8260 mono_custom_attrs_free (cinfo);
8264 ICALL_EXPORT MonoArray*
8265 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8267 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8272 mono_class_init_checked (attr_class, &error);
8273 if (mono_error_set_pending_exception (&error))
8277 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8278 if (!mono_error_ok (&error)) {
8279 mono_error_set_pending_exception (&error);
8286 ICALL_EXPORT MonoArray*
8287 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8291 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8292 mono_error_set_pending_exception (&error);
8297 ICALL_EXPORT MonoString*
8298 ves_icall_Mono_Runtime_GetDisplayName (void)
8301 MonoString *display_name;
8303 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8304 display_name = mono_string_new (mono_domain_get (), info);
8306 return display_name;
8309 ICALL_EXPORT MonoString*
8310 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8313 MonoString *message;
8317 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8318 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8321 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8323 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8324 if (mono_error_set_pending_exception (&error))
8331 ICALL_EXPORT gpointer
8332 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8334 return GetCurrentProcess ();
8337 ICALL_EXPORT MonoBoolean
8338 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8340 return GetExitCodeProcess (handle, (guint32*) exitcode);
8343 ICALL_EXPORT MonoBoolean
8344 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8346 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8347 return CloseHandle (handle);
8349 return CloseProcess (handle);
8353 ICALL_EXPORT MonoBoolean
8354 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8356 return TerminateProcess (handle, exitcode);
8360 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8362 return WaitForInputIdle (handle, milliseconds);
8365 ICALL_EXPORT MonoBoolean
8366 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8368 return GetProcessWorkingSetSize (handle, min, max);
8371 ICALL_EXPORT MonoBoolean
8372 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8374 return SetProcessWorkingSetSize (handle, min, max);
8377 ICALL_EXPORT MonoBoolean
8378 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8380 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8384 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8386 return mono_process_current_pid ();
8390 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8392 return GetPriorityClass (handle);
8395 ICALL_EXPORT MonoBoolean
8396 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8398 return SetPriorityClass (handle, priorityClass);
8401 #ifndef DISABLE_ICALL_TABLES
8403 #define ICALL_TYPE(id,name,first)
8404 #define ICALL(id,name,func) Icall_ ## id,
8407 #include "metadata/icall-def.h"
8413 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8414 #define ICALL(id,name,func)
8416 #include "metadata/icall-def.h"
8422 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8423 #define ICALL(id,name,func)
8425 guint16 first_icall;
8428 static const IcallTypeDesc
8429 icall_type_descs [] = {
8430 #include "metadata/icall-def.h"
8434 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8437 #define ICALL_TYPE(id,name,first)
8440 #ifdef HAVE_ARRAY_ELEM_INIT
8441 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8442 #define MSGSTRFIELD1(line) str##line
8444 static const struct msgstrtn_t {
8445 #define ICALL(id,name,func)
8447 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8448 #include "metadata/icall-def.h"
8450 } icall_type_names_str = {
8451 #define ICALL_TYPE(id,name,first) (name),
8452 #include "metadata/icall-def.h"
8455 static const guint16 icall_type_names_idx [] = {
8456 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8457 #include "metadata/icall-def.h"
8460 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8462 static const struct msgstr_t {
8464 #define ICALL_TYPE(id,name,first)
8465 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8466 #include "metadata/icall-def.h"
8468 } icall_names_str = {
8469 #define ICALL(id,name,func) (name),
8470 #include "metadata/icall-def.h"
8473 static const guint16 icall_names_idx [] = {
8474 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8475 #include "metadata/icall-def.h"
8478 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8484 #define ICALL_TYPE(id,name,first) name,
8485 #define ICALL(id,name,func)
8486 static const char* const
8487 icall_type_names [] = {
8488 #include "metadata/icall-def.h"
8492 #define icall_type_name_get(id) (icall_type_names [(id)])
8496 #define ICALL_TYPE(id,name,first)
8497 #define ICALL(id,name,func) name,
8498 static const char* const
8500 #include "metadata/icall-def.h"
8503 #define icall_name_get(id) icall_names [(id)]
8505 #endif /* !HAVE_ARRAY_ELEM_INIT */
8509 #define ICALL_TYPE(id,name,first)
8510 #define ICALL(id,name,func) func,
8511 static const gconstpointer
8512 icall_functions [] = {
8513 #include "metadata/icall-def.h"
8517 #ifdef ENABLE_ICALL_SYMBOL_MAP
8520 #define ICALL_TYPE(id,name,first)
8521 #define ICALL(id,name,func) #func,
8522 static const gconstpointer
8523 icall_symbols [] = {
8524 #include "metadata/icall-def.h"
8529 #endif /* DISABLE_ICALL_TABLES */
8531 static mono_mutex_t icall_mutex;
8532 static GHashTable *icall_hash = NULL;
8533 static GHashTable *jit_icall_hash_name = NULL;
8534 static GHashTable *jit_icall_hash_addr = NULL;
8537 mono_icall_init (void)
8539 #ifndef DISABLE_ICALL_TABLES
8542 /* check that tables are sorted: disable in release */
8545 const char *prev_class = NULL;
8546 const char *prev_method;
8548 for (i = 0; i < Icall_type_num; ++i) {
8549 const IcallTypeDesc *desc;
8552 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8553 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8554 prev_class = icall_type_name_get (i);
8555 desc = &icall_type_descs [i];
8556 num_icalls = icall_desc_num_icalls (desc);
8557 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8558 for (j = 0; j < num_icalls; ++j) {
8559 const char *methodn = icall_name_get (desc->first_icall + j);
8560 if (prev_method && strcmp (prev_method, methodn) >= 0)
8561 g_print ("method %s should come before method %s\n", methodn, prev_method);
8562 prev_method = methodn;
8568 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8569 mono_os_mutex_init (&icall_mutex);
8573 mono_icall_lock (void)
8575 mono_locks_os_acquire (&icall_mutex, IcallLock);
8579 mono_icall_unlock (void)
8581 mono_locks_os_release (&icall_mutex, IcallLock);
8585 mono_icall_cleanup (void)
8587 g_hash_table_destroy (icall_hash);
8588 g_hash_table_destroy (jit_icall_hash_name);
8589 g_hash_table_destroy (jit_icall_hash_addr);
8590 mono_os_mutex_destroy (&icall_mutex);
8594 * mono_add_internal_call:
8595 * @name: method specification to surface to the managed world
8596 * @method: pointer to a C method to invoke when the method is called
8598 * This method surfaces the C function pointed by @method as a method
8599 * that has been surfaced in managed code with the method specified in
8600 * @name as an internal call.
8602 * Internal calls are surfaced to all app domains loaded and they are
8603 * accessibly by a type with the specified name.
8605 * You must provide a fully qualified type name, that is namespaces
8606 * and type name, followed by a colon and the method name, with an
8607 * optional signature to bind.
8609 * For example, the following are all valid declarations:
8611 * "MyApp.Services.ScriptService:Accelerate"
8612 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8614 * You use method parameters in cases where there might be more than
8615 * one surface method to managed code. That way you can register different
8616 * internal calls for different method overloads.
8618 * The internal calls are invoked with no marshalling. This means that .NET
8619 * types like System.String are exposed as `MonoString *` parameters. This is
8620 * different than the way that strings are surfaced in P/Invoke.
8622 * For more information on how the parameters are marshalled, see the
8623 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8626 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8627 * reference for more information on the format of method descriptions.
8630 mono_add_internal_call (const char *name, gconstpointer method)
8634 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8636 mono_icall_unlock ();
8639 #ifndef DISABLE_ICALL_TABLES
8641 #ifdef HAVE_ARRAY_ELEM_INIT
8643 compare_method_imap (const void *key, const void *elem)
8645 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8646 return strcmp (key, method_name);
8650 find_method_icall (const IcallTypeDesc *imap, const char *name)
8652 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);
8655 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8659 compare_class_imap (const void *key, const void *elem)
8661 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8662 return strcmp (key, class_name);
8665 static const IcallTypeDesc*
8666 find_class_icalls (const char *name)
8668 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);
8671 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8674 #else /* HAVE_ARRAY_ELEM_INIT */
8677 compare_method_imap (const void *key, const void *elem)
8679 const char** method_name = (const char**)elem;
8680 return strcmp (key, *method_name);
8684 find_method_icall (const IcallTypeDesc *imap, const char *name)
8686 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8689 return (gpointer)icall_functions [(nameslot - icall_names)];
8693 compare_class_imap (const void *key, const void *elem)
8695 const char** class_name = (const char**)elem;
8696 return strcmp (key, *class_name);
8699 static const IcallTypeDesc*
8700 find_class_icalls (const char *name)
8702 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8705 return &icall_type_descs [nameslot - icall_type_names];
8708 #endif /* HAVE_ARRAY_ELEM_INIT */
8710 #endif /* DISABLE_ICALL_TABLES */
8713 * we should probably export this as an helper (handle nested types).
8714 * Returns the number of chars written in buf.
8717 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8719 int nspacelen, cnamelen;
8720 nspacelen = strlen (klass->name_space);
8721 cnamelen = strlen (klass->name);
8722 if (nspacelen + cnamelen + 2 > bufsize)
8725 memcpy (buf, klass->name_space, nspacelen);
8726 buf [nspacelen ++] = '.';
8728 memcpy (buf + nspacelen, klass->name, cnamelen);
8729 buf [nspacelen + cnamelen] = 0;
8730 return nspacelen + cnamelen;
8733 #ifdef DISABLE_ICALL_TABLES
8735 no_icall_table (void)
8737 g_assert_not_reached ();
8742 mono_lookup_internal_call (MonoMethod *method)
8747 int typelen = 0, mlen, siglen;
8749 #ifndef DISABLE_ICALL_TABLES
8750 const IcallTypeDesc *imap = NULL;
8753 g_assert (method != NULL);
8755 if (method->is_inflated)
8756 method = ((MonoMethodInflated *) method)->declaring;
8758 if (method->klass->nested_in) {
8759 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8763 mname [pos++] = '/';
8766 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8772 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8777 #ifndef DISABLE_ICALL_TABLES
8778 imap = find_class_icalls (mname);
8781 mname [typelen] = ':';
8782 mname [typelen + 1] = ':';
8784 mlen = strlen (method->name);
8785 memcpy (mname + typelen + 2, method->name, mlen);
8786 sigstart = mname + typelen + 2 + mlen;
8789 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8790 siglen = strlen (tmpsig);
8791 if (typelen + mlen + siglen + 6 > sizeof (mname))
8794 memcpy (sigstart + 1, tmpsig, siglen);
8795 sigstart [siglen + 1] = ')';
8796 sigstart [siglen + 2] = 0;
8801 res = g_hash_table_lookup (icall_hash, mname);
8803 mono_icall_unlock ();;
8806 /* try without signature */
8808 res = g_hash_table_lookup (icall_hash, mname);
8810 mono_icall_unlock ();
8814 #ifdef DISABLE_ICALL_TABLES
8815 mono_icall_unlock ();
8816 /* Fail only when the result is actually used */
8817 /* mono_marshal_get_native_wrapper () depends on this */
8818 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8819 return ves_icall_System_String_ctor_RedirectToCreateString;
8821 return no_icall_table;
8823 /* it wasn't found in the static call tables */
8825 mono_icall_unlock ();
8828 res = find_method_icall (imap, sigstart - mlen);
8830 mono_icall_unlock ();
8833 /* try _with_ signature */
8835 res = find_method_icall (imap, sigstart - mlen);
8837 mono_icall_unlock ();
8841 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8842 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8843 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8844 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8845 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");
8846 g_print ("If you see other errors or faults after this message they are probably related\n");
8847 g_print ("and you need to fix your mono install first.\n");
8849 mono_icall_unlock ();
8855 #ifdef ENABLE_ICALL_SYMBOL_MAP
8857 func_cmp (gconstpointer key, gconstpointer p)
8859 return (gsize)key - (gsize)*(gsize*)p;
8864 * mono_lookup_icall_symbol:
8866 * Given the icall METHOD, returns its C symbol.
8869 mono_lookup_icall_symbol (MonoMethod *m)
8871 #ifdef DISABLE_ICALL_TABLES
8872 g_assert_not_reached ();
8875 #ifdef ENABLE_ICALL_SYMBOL_MAP
8879 static gconstpointer *functions_sorted;
8880 static const char**symbols_sorted;
8881 static gboolean inited;
8886 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8887 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8888 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8889 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8890 /* Bubble sort the two arrays */
8894 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8895 if (functions_sorted [i] > functions_sorted [i + 1]) {
8898 tmp = functions_sorted [i];
8899 functions_sorted [i] = functions_sorted [i + 1];
8900 functions_sorted [i + 1] = tmp;
8901 tmp = symbols_sorted [i];
8902 symbols_sorted [i] = symbols_sorted [i + 1];
8903 symbols_sorted [i + 1] = tmp;
8910 func = mono_lookup_internal_call (m);
8913 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8917 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8919 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8920 g_assert_not_reached ();
8927 type_from_typename (char *type_name)
8929 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8931 if (!strcmp (type_name, "int"))
8932 klass = mono_defaults.int_class;
8933 else if (!strcmp (type_name, "ptr"))
8934 klass = mono_defaults.int_class;
8935 else if (!strcmp (type_name, "void"))
8936 klass = mono_defaults.void_class;
8937 else if (!strcmp (type_name, "int32"))
8938 klass = mono_defaults.int32_class;
8939 else if (!strcmp (type_name, "uint32"))
8940 klass = mono_defaults.uint32_class;
8941 else if (!strcmp (type_name, "int8"))
8942 klass = mono_defaults.sbyte_class;
8943 else if (!strcmp (type_name, "uint8"))
8944 klass = mono_defaults.byte_class;
8945 else if (!strcmp (type_name, "int16"))
8946 klass = mono_defaults.int16_class;
8947 else if (!strcmp (type_name, "uint16"))
8948 klass = mono_defaults.uint16_class;
8949 else if (!strcmp (type_name, "long"))
8950 klass = mono_defaults.int64_class;
8951 else if (!strcmp (type_name, "ulong"))
8952 klass = mono_defaults.uint64_class;
8953 else if (!strcmp (type_name, "float"))
8954 klass = mono_defaults.single_class;
8955 else if (!strcmp (type_name, "double"))
8956 klass = mono_defaults.double_class;
8957 else if (!strcmp (type_name, "object"))
8958 klass = mono_defaults.object_class;
8959 else if (!strcmp (type_name, "obj"))
8960 klass = mono_defaults.object_class;
8961 else if (!strcmp (type_name, "string"))
8962 klass = mono_defaults.string_class;
8963 else if (!strcmp (type_name, "bool"))
8964 klass = mono_defaults.boolean_class;
8965 else if (!strcmp (type_name, "boolean"))
8966 klass = mono_defaults.boolean_class;
8968 g_error ("%s", type_name);
8969 g_assert_not_reached ();
8971 return &klass->byval_arg;
8975 * LOCKING: Take the corlib image lock.
8977 MonoMethodSignature*
8978 mono_create_icall_signature (const char *sigstr)
8983 MonoMethodSignature *res, *res2;
8984 MonoImage *corlib = mono_defaults.corlib;
8986 mono_image_lock (corlib);
8987 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8988 mono_image_unlock (corlib);
8993 parts = g_strsplit (sigstr, " ", 256);
9002 res = mono_metadata_signature_alloc (corlib, len - 1);
9007 * Under windows, the default pinvoke calling convention is STDCALL but
9010 res->call_convention = MONO_CALL_C;
9013 res->ret = type_from_typename (parts [0]);
9014 for (i = 1; i < len; ++i) {
9015 res->params [i - 1] = type_from_typename (parts [i]);
9020 mono_image_lock (corlib);
9021 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
9023 res = res2; /*Value is allocated in the image pool*/
9025 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
9026 mono_image_unlock (corlib);
9032 mono_find_jit_icall_by_name (const char *name)
9034 MonoJitICallInfo *info;
9035 g_assert (jit_icall_hash_name);
9038 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9039 mono_icall_unlock ();
9044 mono_find_jit_icall_by_addr (gconstpointer addr)
9046 MonoJitICallInfo *info;
9047 g_assert (jit_icall_hash_addr);
9050 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
9051 mono_icall_unlock ();
9057 * mono_get_jit_icall_info:
9059 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
9060 * caller should access it while holding the icall lock.
9063 mono_get_jit_icall_info (void)
9065 return jit_icall_hash_name;
9069 * mono_lookup_jit_icall_symbol:
9071 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
9074 mono_lookup_jit_icall_symbol (const char *name)
9076 MonoJitICallInfo *info;
9077 const char *res = NULL;
9080 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9082 res = info->c_symbol;
9083 mono_icall_unlock ();
9088 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
9091 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
9092 mono_icall_unlock ();
9096 * 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
9097 * icalls without wrappers in some cases.
9100 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
9102 MonoJitICallInfo *info;
9109 if (!jit_icall_hash_name) {
9110 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
9111 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
9114 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
9115 g_warning ("jit icall already defined \"%s\"\n", name);
9116 g_assert_not_reached ();
9119 info = g_new0 (MonoJitICallInfo, 1);
9124 info->c_symbol = c_symbol;
9125 info->no_raise = no_raise;
9128 info->wrapper = func;
9130 info->wrapper = NULL;
9133 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
9134 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
9136 mono_icall_unlock ();
9141 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
9143 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);