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 mono_error_raise_exception (&error);
570 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
571 /* vectors are not the same as one dimensional arrays with no-zero bounds */
576 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
578 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
579 for (i = 0; i < aklass->rank; ++i) {
580 sizes [i] = mono_array_get (lengths, guint32, i);
582 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
584 sizes [i + aklass->rank] = 0;
587 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
588 mono_error_set_pending_exception (&error);
593 ICALL_EXPORT MonoArray *
594 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
597 MonoClass *aklass, *klass;
600 gboolean bounded = FALSE;
602 MONO_CHECK_ARG_NULL (type, NULL);
603 MONO_CHECK_ARG_NULL (lengths, NULL);
605 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
607 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
609 for (i = 0; i < mono_array_length (lengths); i++) {
610 if ((mono_array_get (lengths, gint64, i) < 0) ||
611 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
612 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
617 klass = mono_class_from_mono_type (type->type);
618 mono_class_init_checked (klass, &error);
619 mono_error_raise_exception (&error);
621 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
622 /* vectors are not the same as one dimensional arrays with no-zero bounds */
627 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
629 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
630 for (i = 0; i < aklass->rank; ++i) {
631 sizes [i] = mono_array_get (lengths, guint64, i);
633 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
635 sizes [i + aklass->rank] = 0;
638 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
639 mono_error_set_pending_exception (&error);
645 ves_icall_System_Array_GetRank (MonoObject *arr)
647 return arr->vtable->klass->rank;
651 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
653 gint32 rank = arr->obj.vtable->klass->rank;
656 if ((dimension < 0) || (dimension >= rank)) {
657 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
661 if (arr->bounds == NULL)
662 length = arr->max_length;
664 length = arr->bounds [dimension].length;
666 #ifdef MONO_BIG_ARRAYS
667 if (length > G_MAXINT32) {
668 mono_set_pending_exception (mono_get_exception_overflow ());
676 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
678 gint32 rank = arr->obj.vtable->klass->rank;
680 if ((dimension < 0) || (dimension >= rank)) {
681 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
685 if (arr->bounds == NULL)
686 return arr->max_length;
688 return arr->bounds [dimension].length;
692 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
694 gint32 rank = arr->obj.vtable->klass->rank;
696 if ((dimension < 0) || (dimension >= rank)) {
697 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
701 if (arr->bounds == NULL)
704 return arr->bounds [dimension].lower_bound;
708 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
710 int sz = mono_array_element_size (mono_object_class (arr));
711 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
714 ICALL_EXPORT gboolean
715 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
720 MonoVTable *src_vtable;
721 MonoVTable *dest_vtable;
722 MonoClass *src_class;
723 MonoClass *dest_class;
725 src_vtable = source->obj.vtable;
726 dest_vtable = dest->obj.vtable;
728 if (src_vtable->rank != dest_vtable->rank)
731 if (source->bounds || dest->bounds)
734 /* there's no integer overflow since mono_array_length returns an unsigned integer */
735 if ((dest_idx + length > mono_array_length_fast (dest)) ||
736 (source_idx + length > mono_array_length_fast (source)))
739 src_class = src_vtable->klass->element_class;
740 dest_class = dest_vtable->klass->element_class;
743 * Handle common cases.
746 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
747 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
749 if (src_class == mono_defaults.object_class && dest_class->valuetype)
752 /* Check if we're copying a char[] <==> (u)short[] */
753 if (src_class != dest_class) {
754 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
757 /* 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. */
758 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
762 if (dest_class->valuetype) {
763 element_size = mono_array_element_size (source->obj.vtable->klass);
764 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
765 if (dest_class->has_references) {
766 mono_value_copy_array (dest, dest_idx, source_addr, length);
768 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
769 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
772 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
779 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
785 ac = (MonoClass *)arr->obj.vtable->klass;
787 esize = mono_array_element_size (ac);
788 ea = (gpointer*)((char*)arr->vector + (pos * esize));
790 mono_gc_memmove_atomic (value, ea, esize);
794 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
800 ac = (MonoClass *)arr->obj.vtable->klass;
801 ec = ac->element_class;
803 esize = mono_array_element_size (ac);
804 ea = (gpointer*)((char*)arr->vector + (pos * esize));
806 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
807 g_assert (esize == sizeof (gpointer));
808 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
810 g_assert (ec->inited);
811 g_assert (esize == mono_class_value_size (ec, NULL));
812 if (ec->has_references)
813 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
815 mono_gc_memmove_atomic (ea, value, esize);
820 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
822 MonoClass *klass = array->obj.vtable->klass;
823 guint32 size = mono_array_element_size (klass);
824 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
826 const char *field_data;
828 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
829 MonoException *exc = mono_get_exception_argument("array",
830 "Cannot initialize array of non-primitive type.");
831 mono_set_pending_exception (exc);
835 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
836 MonoException *exc = mono_get_exception_argument("field_handle",
837 "Field doesn't have an RVA");
838 mono_set_pending_exception (exc);
842 size *= array->max_length;
843 field_data = mono_field_get_data (field_handle);
845 if (size > mono_type_size (field_handle->type, &align)) {
846 MonoException *exc = mono_get_exception_argument("field_handle",
847 "Field not large enough to fill array");
848 mono_set_pending_exception (exc);
852 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
854 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
855 guint ## n *src = (guint ## n *) field_data; \
857 nEnt = (size / sizeof(guint ## n)); \
859 for (i = 0; i < nEnt; i++) { \
860 data[i] = read ## n (&src[i]); \
864 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
866 switch (type->type) {
883 memcpy (mono_array_addr (array, char, 0), field_data, size);
887 memcpy (mono_array_addr (array, char, 0), field_data, size);
892 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
894 return offsetof (MonoString, chars);
897 ICALL_EXPORT MonoObject *
898 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
900 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
904 MonoObject *ret = mono_object_clone_checked (obj, &error);
905 mono_error_set_pending_exception (&error);
912 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
918 MONO_CHECK_ARG_NULL (handle,);
920 klass = mono_class_from_mono_type (handle);
921 MONO_CHECK_ARG (handle, klass,);
923 if (klass->generic_container)
926 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
927 if (!is_ok (&error)) {
928 mono_error_set_pending_exception (&error);
932 /* This will call the type constructor */
933 if (!mono_runtime_class_init_full (vtable, &error))
934 mono_error_set_pending_exception (&error);
938 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
942 mono_image_check_for_module_cctor (image);
943 if (image->has_module_cctor) {
944 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
945 if (!mono_error_ok (&error)) {
946 mono_error_set_pending_exception (&error);
949 /*It's fine to raise the exception here*/
950 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
951 if (!is_ok (&error)) {
952 mono_error_set_pending_exception (&error);
955 if (!mono_runtime_class_init_full (vtable, &error))
956 mono_error_set_pending_exception (&error);
960 ICALL_EXPORT MonoBoolean
961 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
966 /* later make this configurable and per-arch */
967 int min_size = 4096 * 4 * sizeof (void*);
968 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
969 /* if we have no info we are optimistic and assume there is enough room */
973 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
977 current = (guint8 *)&stack_addr;
978 if (current > stack_addr) {
979 if ((current - stack_addr) < min_size)
982 if (current - (stack_addr - stack_size) < min_size)
988 ICALL_EXPORT MonoObject *
989 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
992 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
993 mono_error_set_pending_exception (&error);
999 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1003 MonoObject **values = NULL;
1006 gint32 result = (int)(gsize)mono_defaults.int32_class;
1007 MonoClassField* field;
1010 klass = mono_object_class (this_obj);
1012 if (mono_class_num_fields (klass) == 0)
1016 * Compute the starting value of the hashcode for fields of primitive
1017 * types, and return the remaining fields in an array to the managed side.
1018 * This way, we can avoid costly reflection operations in managed code.
1021 while ((field = mono_class_get_fields (klass, &iter))) {
1022 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1024 if (mono_field_is_deleted (field))
1026 /* FIXME: Add more types */
1027 switch (field->type->type) {
1029 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1031 case MONO_TYPE_STRING: {
1033 s = *(MonoString**)((guint8*)this_obj + field->offset);
1035 result ^= mono_string_hash (s);
1040 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1041 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1042 if (!is_ok (&error)) {
1043 mono_error_set_pending_exception (&error);
1046 values [count++] = o;
1052 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1053 for (i = 0; i < count; ++i)
1054 mono_array_setref (*fields, i, values [i]);
1061 ICALL_EXPORT MonoBoolean
1062 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1066 MonoObject **values = NULL;
1068 MonoClassField* field;
1072 MONO_CHECK_ARG_NULL (that, FALSE);
1074 if (this_obj->vtable != that->vtable)
1077 klass = mono_object_class (this_obj);
1079 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1080 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1083 * Do the comparison for fields of primitive type and return a result if
1084 * possible. Otherwise, return the remaining fields in an array to the
1085 * managed side. This way, we can avoid costly reflection operations in
1090 while ((field = mono_class_get_fields (klass, &iter))) {
1091 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1093 if (mono_field_is_deleted (field))
1095 /* FIXME: Add more types */
1096 switch (field->type->type) {
1099 case MONO_TYPE_BOOLEAN:
1100 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1105 case MONO_TYPE_CHAR:
1106 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1111 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1116 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1120 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1124 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1129 case MONO_TYPE_STRING: {
1130 MonoString *s1, *s2;
1131 guint32 s1len, s2len;
1132 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1133 s2 = *(MonoString**)((guint8*)that + field->offset);
1136 if ((s1 == NULL) || (s2 == NULL))
1138 s1len = mono_string_length (s1);
1139 s2len = mono_string_length (s2);
1143 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1149 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1150 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1151 if (!is_ok (&error)) {
1152 mono_error_set_pending_exception (&error);
1155 values [count++] = o;
1156 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1157 if (!is_ok (&error)) {
1158 mono_error_set_pending_exception (&error);
1161 values [count++] = o;
1164 if (klass->enumtype)
1165 /* enums only have one non-static field */
1171 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1172 for (i = 0; i < count; ++i)
1173 mono_array_setref_fast (*fields, i, values [i]);
1180 ICALL_EXPORT MonoReflectionType *
1181 ves_icall_System_Object_GetType (MonoObject *obj)
1184 MonoReflectionType *ret;
1185 #ifndef DISABLE_REMOTING
1186 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1187 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1190 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1192 mono_error_raise_exception (&error);
1198 ves_icall_MonoType_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1200 mtype->type = &obj->vtable->klass->byval_arg;
1201 g_assert (mtype->type->type);
1205 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1207 MONO_CHECK_ARG_NULL (obj, 0);
1210 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1211 mono_error_raise_exception (&error);
1216 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1217 MonoReflectionMethod *method,
1218 MonoArray *opt_param_types)
1220 MONO_CHECK_ARG_NULL (method, 0);
1223 gint32 result = mono_image_create_method_token (
1224 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1225 mono_error_raise_exception (&error);
1230 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1233 mono_image_create_pefile (mb, file, &error);
1234 mono_error_raise_exception (&error);
1238 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1241 if (!mono_image_build_metadata (mb, &error))
1242 mono_error_raise_exception (&error);
1246 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1248 mono_image_register_token (mb->dynamic_image, token, obj);
1251 ICALL_EXPORT MonoObject*
1252 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1256 mono_loader_lock ();
1257 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1258 mono_loader_unlock ();
1263 ICALL_EXPORT MonoReflectionModule*
1264 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1267 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1268 mono_error_set_pending_exception (&error);
1272 ICALL_EXPORT MonoArray*
1273 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
1276 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
1277 mono_error_set_pending_exception (&error);
1282 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1284 MonoMethod **dest = (MonoMethod **)data;
1286 /* skip unmanaged frames */
1302 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1304 MonoMethod **dest = (MonoMethod **)data;
1306 /* skip unmanaged frames */
1311 if (!strcmp (m->klass->name_space, "System.Reflection"))
1320 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1322 MonoMethod **dest = (MonoMethod **)data;
1324 /* skip unmanaged frames */
1328 if (m->wrapper_type != MONO_WRAPPER_NONE)
1331 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1345 static MonoReflectionType *
1346 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1348 MonoMethod *m, *dest;
1350 MonoType *type = NULL;
1351 MonoAssembly *assembly = NULL;
1352 gboolean type_resolve = FALSE;
1354 mono_error_init (error);
1357 * We must compute the calling assembly as type loading must happen under a metadata context.
1358 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1359 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1361 m = mono_method_get_last_managed ();
1364 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1369 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1370 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1371 * to crash. This only seems to happen in some strange remoting
1372 * scenarios and I was unable to figure out what's happening there.
1373 * Dec 10, 2005 - Martin.
1377 assembly = dest->klass->image->assembly;
1378 type_resolve = TRUE;
1380 g_warning (G_STRLOC);
1383 if (info->assembly.name)
1384 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1388 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1389 type = mono_reflection_get_type_checked (assembly->image, info, ignoreCase, &type_resolve, error);
1390 return_val_if_nok (error, NULL);
1393 if (!info->assembly.name && !type) {
1395 type = mono_reflection_get_type_checked (NULL, info, ignoreCase, &type_resolve, error);
1396 return_val_if_nok (error, NULL);
1398 if (assembly && !type && type_resolve) {
1399 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1400 type = mono_reflection_get_type_checked (assembly->image, info, ignoreCase, &type_resolve, error);
1401 return_val_if_nok (error, NULL);
1407 return mono_type_get_object_checked (mono_domain_get (), type, error);
1410 ICALL_EXPORT MonoReflectionType*
1411 ves_icall_System_Type_internal_from_name (MonoString *name,
1412 MonoBoolean throwOnError,
1413 MonoBoolean ignoreCase)
1416 char *str = mono_string_to_utf8 (name);
1417 MonoTypeNameParse info;
1418 MonoReflectionType *type;
1421 parsedOk = mono_reflection_parse_type (str, &info);
1423 /* mono_reflection_parse_type() mangles the string */
1425 mono_reflection_free_type_info (&info);
1428 mono_set_pending_exception (mono_get_exception_argument("typeName", "failed parse"));
1433 type = type_from_parsed_name (&info, ignoreCase, &error);
1435 mono_reflection_free_type_info (&info);
1438 if (!mono_error_ok (&error)) {
1440 mono_error_set_pending_exception (&error);
1442 mono_error_cleanup (&error);
1447 MonoException *e = NULL;
1450 e = mono_get_exception_type_load (name, NULL);
1452 mono_loader_clear_error ();
1454 mono_set_pending_exception (e);
1463 ICALL_EXPORT MonoReflectionType*
1464 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1467 MonoReflectionType *ret;
1468 MonoDomain *domain = mono_domain_get ();
1470 ret = mono_type_get_object_checked (domain, handle, &error);
1471 mono_error_raise_exception (&error);
1476 /* System.TypeCode */
1495 TYPECODE_STRING = 18
1498 ICALL_EXPORT guint32
1499 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1501 int t = type->type->type;
1503 if (type->type->byref)
1504 return TYPECODE_OBJECT;
1508 case MONO_TYPE_VOID:
1509 return TYPECODE_OBJECT;
1510 case MONO_TYPE_BOOLEAN:
1511 return TYPECODE_BOOLEAN;
1513 return TYPECODE_BYTE;
1515 return TYPECODE_SBYTE;
1517 return TYPECODE_UINT16;
1519 return TYPECODE_INT16;
1520 case MONO_TYPE_CHAR:
1521 return TYPECODE_CHAR;
1525 return TYPECODE_OBJECT;
1527 return TYPECODE_UINT32;
1529 return TYPECODE_INT32;
1531 return TYPECODE_UINT64;
1533 return TYPECODE_INT64;
1535 return TYPECODE_SINGLE;
1537 return TYPECODE_DOUBLE;
1538 case MONO_TYPE_VALUETYPE: {
1539 MonoClass *klass = type->type->data.klass;
1541 if (klass->enumtype) {
1542 t = mono_class_enum_basetype (klass)->type;
1544 } else if (mono_is_corlib_image (klass->image)) {
1545 if (strcmp (klass->name_space, "System") == 0) {
1546 if (strcmp (klass->name, "Decimal") == 0)
1547 return TYPECODE_DECIMAL;
1548 else if (strcmp (klass->name, "DateTime") == 0)
1549 return TYPECODE_DATETIME;
1552 return TYPECODE_OBJECT;
1554 case MONO_TYPE_STRING:
1555 return TYPECODE_STRING;
1556 case MONO_TYPE_SZARRAY:
1557 case MONO_TYPE_ARRAY:
1558 case MONO_TYPE_OBJECT:
1560 case MONO_TYPE_MVAR:
1561 case MONO_TYPE_TYPEDBYREF:
1562 return TYPECODE_OBJECT;
1563 case MONO_TYPE_CLASS:
1565 MonoClass *klass = type->type->data.klass;
1566 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1567 if (strcmp (klass->name, "DBNull") == 0)
1568 return TYPECODE_DBNULL;
1571 return TYPECODE_OBJECT;
1572 case MONO_TYPE_GENERICINST:
1573 return TYPECODE_OBJECT;
1575 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1581 mono_type_is_primitive (MonoType *type)
1583 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1584 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1588 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1590 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1591 return mono_class_enum_basetype (type->data.klass);
1592 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1593 return mono_class_enum_basetype (type->data.generic_class->container_class);
1597 ICALL_EXPORT guint32
1598 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1603 g_assert (type != NULL);
1605 klass = mono_class_from_mono_type (type->type);
1606 klassc = mono_class_from_mono_type (c->type);
1608 if (type->type->byref ^ c->type->byref)
1611 if (type->type->byref) {
1612 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1613 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1615 klass = mono_class_from_mono_type (t);
1616 klassc = mono_class_from_mono_type (ot);
1618 if (mono_type_is_primitive (t)) {
1619 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1620 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1621 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1622 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1623 return t->type == ot->type;
1625 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1628 if (klass->valuetype)
1629 return klass == klassc;
1630 return klass->valuetype == klassc->valuetype;
1633 return mono_class_is_assignable_from (klass, klassc);
1636 ICALL_EXPORT guint32
1637 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1640 MonoClass *klass = mono_class_from_mono_type (type->type);
1641 mono_class_init_checked (klass, &error);
1642 if (!is_ok (&error)) {
1643 mono_error_set_pending_exception (&error);
1646 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1647 mono_error_set_pending_exception (&error);
1651 ICALL_EXPORT guint32
1652 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1654 MonoClass *klass = mono_class_from_mono_type (type->type);
1655 return klass->flags;
1658 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1659 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1662 MonoClass *klass = field->field->parent;
1663 MonoMarshalType *info;
1667 if (klass->generic_container ||
1668 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1671 ftype = mono_field_get_type (field->field);
1672 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1675 info = mono_marshal_load_type_info (klass);
1677 for (i = 0; i < info->num_fields; ++i) {
1678 if (info->fields [i].field == field->field) {
1679 if (!info->fields [i].mspec)
1682 MonoReflectionMarshalAsAttribute* obj;
1683 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1684 if (!mono_error_ok (&error))
1685 mono_error_set_pending_exception (&error);
1694 ICALL_EXPORT MonoReflectionField*
1695 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1698 gboolean found = FALSE;
1705 klass = handle->parent;
1707 klass = mono_class_from_mono_type (type);
1709 /* Check that the field belongs to the class */
1710 for (k = klass; k; k = k->parent) {
1711 if (k == handle->parent) {
1718 /* The managed code will throw the exception */
1722 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1723 mono_error_raise_exception (&error);
1727 ICALL_EXPORT MonoArray*
1728 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1731 MonoType *type = mono_field_get_type_checked (field->field, &error);
1734 if (!mono_error_ok (&error)) {
1735 mono_error_set_pending_exception (&error);
1739 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1740 mono_error_raise_exception (&error);
1745 vell_icall_get_method_attributes (MonoMethod *method)
1747 return method->flags;
1751 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1754 MonoReflectionType *rt;
1755 MonoDomain *domain = mono_domain_get ();
1756 MonoMethodSignature* sig;
1758 sig = mono_method_signature_checked (method, &error);
1759 if (!mono_error_ok (&error)) {
1760 mono_error_set_pending_exception (&error);
1764 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1765 if (!mono_error_ok (&error)) {
1766 mono_error_set_pending_exception (&error);
1770 MONO_STRUCT_SETREF (info, parent, rt);
1772 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1773 if (!mono_error_ok (&error)) {
1774 mono_error_set_pending_exception (&error);
1778 MONO_STRUCT_SETREF (info, ret, rt);
1780 info->attrs = method->flags;
1781 info->implattrs = method->iflags;
1782 if (sig->call_convention == MONO_CALL_DEFAULT)
1783 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1785 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1790 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1793 ICALL_EXPORT MonoArray*
1794 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1797 MonoDomain *domain = mono_domain_get ();
1799 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1800 mono_error_set_pending_exception (&error);
1804 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1805 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1808 MonoDomain *domain = mono_domain_get ();
1809 MonoReflectionMarshalAsAttribute* res = NULL;
1810 MonoMarshalSpec **mspecs;
1813 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1814 mono_method_get_marshal_info (method, mspecs);
1817 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1818 if (!mono_error_ok (&error)) {
1819 mono_error_set_pending_exception (&error);
1824 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1826 mono_metadata_free_marshal_spec (mspecs [i]);
1833 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1835 MonoClass *parent = field->field->parent;
1836 if (!parent->size_inited)
1837 mono_class_init (parent);
1838 mono_class_setup_fields_locking (parent);
1840 return field->field->offset - sizeof (MonoObject);
1843 ICALL_EXPORT MonoReflectionType*
1844 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1847 MonoReflectionType *ret;
1850 parent = declaring? field->field->parent: field->klass;
1852 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1853 mono_error_raise_exception (&error);
1859 ICALL_EXPORT MonoObject *
1860 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1863 MonoClass *fklass = field->klass;
1864 MonoClassField *cf = field->field;
1865 MonoDomain *domain = mono_object_domain (field);
1867 if (fklass->image->assembly->ref_only) {
1868 mono_set_pending_exception (mono_get_exception_invalid_operation (
1869 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1873 if (mono_security_core_clr_enabled () &&
1874 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1875 mono_error_set_pending_exception (&error);
1879 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1880 mono_error_set_pending_exception (&error);
1885 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1888 MonoClassField *cf = field->field;
1892 if (field->klass->image->assembly->ref_only) {
1893 mono_set_pending_exception (mono_get_exception_invalid_operation (
1894 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1898 if (mono_security_core_clr_enabled () &&
1899 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1900 mono_error_set_pending_exception (&error);
1904 type = mono_field_get_type_checked (cf, &error);
1905 if (!mono_error_ok (&error)) {
1906 mono_error_set_pending_exception (&error);
1910 v = (gchar *) value;
1912 switch (type->type) {
1915 case MONO_TYPE_BOOLEAN:
1918 case MONO_TYPE_CHAR:
1927 case MONO_TYPE_VALUETYPE:
1930 v += sizeof (MonoObject);
1932 case MONO_TYPE_STRING:
1933 case MONO_TYPE_OBJECT:
1934 case MONO_TYPE_CLASS:
1935 case MONO_TYPE_ARRAY:
1936 case MONO_TYPE_SZARRAY:
1939 case MONO_TYPE_GENERICINST: {
1940 MonoGenericClass *gclass = type->data.generic_class;
1941 g_assert (!gclass->context.class_inst->is_open);
1943 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1944 MonoClass *nklass = mono_class_from_mono_type (type);
1945 MonoObject *nullable;
1948 * Convert the boxed vtype into a Nullable structure.
1949 * This is complicated by the fact that Nullables have
1950 * a variable structure.
1952 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1953 if (!mono_error_ok (&error)) {
1954 mono_error_set_pending_exception (&error);
1958 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1960 v = (gchar *)mono_object_unbox (nullable);
1963 if (gclass->container_class->valuetype && (v != NULL))
1964 v += sizeof (MonoObject);
1968 g_error ("type 0x%x not handled in "
1969 "ves_icall_FieldInfo_SetValueInternal", type->type);
1974 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1975 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
1976 if (!is_ok (&error)) {
1977 mono_error_set_pending_exception (&error);
1980 if (!vtable->initialized) {
1981 if (!mono_runtime_class_init_full (vtable, &error)) {
1982 mono_error_set_pending_exception (&error);
1986 mono_field_static_set_value (vtable, cf, v);
1988 mono_field_set_value (obj, cf, v);
1993 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2002 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2003 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2007 if (MONO_TYPE_IS_REFERENCE (f->type))
2008 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2010 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2013 ICALL_EXPORT MonoObject *
2014 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2016 MonoObject *o = NULL;
2017 MonoClassField *field = rfield->field;
2019 MonoDomain *domain = mono_object_domain (rfield);
2021 MonoTypeEnum def_type;
2022 const char *def_value;
2026 mono_class_init (field->parent);
2028 t = mono_field_get_type_checked (field, &error);
2029 if (!mono_error_ok (&error)) {
2030 mono_error_set_pending_exception (&error);
2034 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2035 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2039 if (image_is_dynamic (field->parent->image)) {
2040 MonoClass *klass = field->parent;
2041 int fidx = field - klass->fields;
2043 g_assert (fidx >= 0 && fidx < klass->field.count);
2044 g_assert (klass->ext);
2045 g_assert (klass->ext->field_def_values);
2046 def_type = klass->ext->field_def_values [fidx].def_type;
2047 def_value = klass->ext->field_def_values [fidx].data;
2048 if (def_type == MONO_TYPE_END) {
2049 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2053 def_value = mono_class_get_field_default_value (field, &def_type);
2054 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2056 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2061 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2065 case MONO_TYPE_BOOLEAN:
2068 case MONO_TYPE_CHAR:
2076 case MONO_TYPE_R8: {
2079 /* boxed value type */
2080 t = g_new0 (MonoType, 1);
2082 klass = mono_class_from_mono_type (t);
2084 o = mono_object_new_checked (domain, klass, &error);
2085 if (!mono_error_ok (&error)) {
2086 mono_error_set_pending_exception (&error);
2089 v = ((gchar *) o) + sizeof (MonoObject);
2090 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2093 case MONO_TYPE_STRING:
2094 case MONO_TYPE_CLASS:
2095 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2098 g_assert_not_reached ();
2104 ICALL_EXPORT MonoReflectionType*
2105 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2108 MonoReflectionType *ret;
2111 type = mono_field_get_type_checked (ref_field->field, &error);
2112 if (!mono_error_ok (&error)) {
2113 mono_error_set_pending_exception (&error);
2117 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2118 if (!mono_error_ok (&error)) {
2119 mono_error_set_pending_exception (&error);
2126 /* From MonoProperty.cs */
2128 PInfo_Attributes = 1,
2129 PInfo_GetMethod = 1 << 1,
2130 PInfo_SetMethod = 1 << 2,
2131 PInfo_ReflectedType = 1 << 3,
2132 PInfo_DeclaringType = 1 << 4,
2137 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2140 MonoReflectionType *rt;
2141 MonoReflectionMethod *rm;
2142 MonoDomain *domain = mono_object_domain (property);
2143 const MonoProperty *pproperty = property->property;
2145 if ((req_info & PInfo_ReflectedType) != 0) {
2146 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2147 mono_error_raise_exception (&error);
2149 MONO_STRUCT_SETREF (info, parent, rt);
2151 if ((req_info & PInfo_DeclaringType) != 0) {
2152 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2153 mono_error_raise_exception (&error);
2155 MONO_STRUCT_SETREF (info, declaring_type, rt);
2158 if ((req_info & PInfo_Name) != 0)
2159 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2161 if ((req_info & PInfo_Attributes) != 0)
2162 info->attrs = pproperty->attrs;
2164 if ((req_info & PInfo_GetMethod) != 0) {
2165 if (pproperty->get &&
2166 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2167 pproperty->get->klass == property->klass)) {
2168 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2169 mono_error_raise_exception (&error);
2174 MONO_STRUCT_SETREF (info, get, rm);
2176 if ((req_info & PInfo_SetMethod) != 0) {
2177 if (pproperty->set &&
2178 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2179 pproperty->set->klass == property->klass)) {
2180 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2181 mono_error_raise_exception (&error);
2186 MONO_STRUCT_SETREF (info, set, rm);
2189 * There may be other methods defined for properties, though, it seems they are not exposed
2190 * in the reflection API
2195 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2198 MonoReflectionType *rt;
2199 MonoReflectionMethod *rm;
2200 MonoDomain *domain = mono_object_domain (event);
2202 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2203 mono_error_raise_exception (&error);
2205 MONO_STRUCT_SETREF (info, reflected_type, rt);
2207 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2208 mono_error_raise_exception (&error);
2210 MONO_STRUCT_SETREF (info, declaring_type, rt);
2212 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2213 info->attrs = event->event->attrs;
2215 if (event->event->add) {
2216 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2217 mono_error_raise_exception (&error);
2222 MONO_STRUCT_SETREF (info, add_method, rm);
2224 if (event->event->remove) {
2225 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2226 mono_error_raise_exception (&error);
2231 MONO_STRUCT_SETREF (info, remove_method, rm);
2233 if (event->event->raise) {
2234 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2235 mono_error_raise_exception (&error);
2240 MONO_STRUCT_SETREF (info, raise_method, rm);
2242 #ifndef MONO_SMALL_CONFIG
2243 if (event->event->other) {
2245 while (event->event->other [n])
2247 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2249 for (i = 0; i < n; i++) {
2250 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2251 mono_error_raise_exception (&error);
2252 mono_array_setref (info->other_methods, i, rm);
2259 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2264 mono_class_setup_interfaces (klass, error);
2265 if (!mono_error_ok (error))
2268 for (i = 0; i < klass->interface_count; i++) {
2269 ic = klass->interfaces [i];
2270 g_hash_table_insert (ifaces, ic, ic);
2272 collect_interfaces (ic, ifaces, error);
2273 if (!mono_error_ok (error))
2279 MonoArray *iface_array;
2280 MonoGenericContext *context;
2284 } FillIfaceArrayData;
2287 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2289 MonoReflectionType *rt;
2290 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2291 MonoClass *ic = (MonoClass *)key;
2292 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2294 if (!mono_error_ok (data->error))
2297 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2298 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2299 if (!mono_error_ok (data->error))
2303 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2304 if (!mono_error_ok (data->error))
2307 mono_array_setref (data->iface_array, data->next_idx++, rt);
2310 mono_metadata_free_type (inflated);
2314 get_interfaces_hash (gconstpointer v1)
2316 MonoClass *k = (MonoClass*)v1;
2318 return k->type_token;
2321 ICALL_EXPORT MonoArray*
2322 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2325 MonoClass *klass = mono_class_from_mono_type (type->type);
2327 FillIfaceArrayData data = { 0 };
2330 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2332 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2333 data.context = mono_class_get_context (klass);
2334 klass = klass->generic_class->container_class;
2337 for (parent = klass; parent; parent = parent->parent) {
2338 mono_class_setup_interfaces (parent, &error);
2339 if (!mono_error_ok (&error))
2341 collect_interfaces (parent, iface_hash, &error);
2342 if (!mono_error_ok (&error))
2346 data.error = &error;
2347 data.domain = mono_object_domain (type);
2349 len = g_hash_table_size (iface_hash);
2351 g_hash_table_destroy (iface_hash);
2352 if (!data.domain->empty_types)
2353 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2354 return data.domain->empty_types;
2357 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2358 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2359 if (!mono_error_ok (&error))
2362 g_hash_table_destroy (iface_hash);
2363 return data.iface_array;
2366 g_hash_table_destroy (iface_hash);
2367 mono_error_set_pending_exception (&error);
2372 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2374 gboolean variance_used;
2375 MonoClass *klass = mono_class_from_mono_type (type->type);
2376 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2377 MonoReflectionMethod *member;
2380 int i = 0, len, ioffset;
2384 mono_class_init_checked (klass, &error);
2385 mono_error_raise_exception (&error);
2386 mono_class_init_checked (iclass, &error);
2387 mono_error_raise_exception (&error);
2389 mono_class_setup_vtable (klass);
2391 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2395 len = mono_class_num_methods (iclass);
2396 domain = mono_object_domain (type);
2397 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2398 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2400 while ((method = mono_class_get_methods (iclass, &iter))) {
2401 member = mono_method_get_object_checked (domain, method, iclass, &error);
2402 mono_error_raise_exception (&error);
2403 mono_array_setref (*methods, i, member);
2404 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2405 mono_error_raise_exception (&error);
2406 mono_array_setref (*targets, i, member);
2413 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2416 MonoClass *klass = mono_class_from_mono_type (type->type);
2418 mono_class_init_checked (klass, &error);
2419 mono_error_raise_exception (&error);
2421 if (image_is_dynamic (klass->image)) {
2422 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2423 *packing = tb->packing_size;
2424 *size = tb->class_size;
2426 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2430 ICALL_EXPORT MonoReflectionType*
2431 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2434 MonoReflectionType *ret;
2437 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2438 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2439 mono_error_raise_exception (&error);
2444 klass = mono_class_from_mono_type (type->type);
2445 mono_class_init_checked (klass, &error);
2446 mono_error_raise_exception (&error);
2448 // GetElementType should only return a type for:
2449 // Array Pointer PassedByRef
2450 if (type->type->byref)
2451 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2452 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2453 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2454 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2455 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2459 mono_error_raise_exception (&error);
2464 ICALL_EXPORT MonoReflectionType*
2465 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2468 MonoReflectionType *ret;
2470 if (type->type->byref)
2473 MonoClass *klass = mono_class_from_mono_type (type->type);
2477 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2478 mono_error_raise_exception (&error);
2483 ICALL_EXPORT MonoBoolean
2484 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2486 return type->type->type == MONO_TYPE_PTR;
2489 ICALL_EXPORT MonoBoolean
2490 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2492 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)));
2495 ICALL_EXPORT MonoBoolean
2496 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2498 return type->type->byref;
2501 ICALL_EXPORT MonoBoolean
2502 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2505 MonoClass *klass = mono_class_from_mono_type (type->type);
2506 mono_class_init_checked (klass, &error);
2507 mono_error_raise_exception (&error);
2509 return mono_class_is_com_object (klass);
2512 ICALL_EXPORT guint32
2513 ves_icall_reflection_get_token (MonoObject* obj)
2516 guint32 result = mono_reflection_get_token_checked (obj, &error);
2517 mono_error_set_pending_exception (&error);
2521 ICALL_EXPORT MonoReflectionModule*
2522 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2525 MonoReflectionModule *result = NULL;
2526 MonoClass *klass = mono_class_from_mono_type (type->type);
2527 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2528 if (!mono_error_ok (&error))
2529 mono_error_set_pending_exception (&error);
2533 ICALL_EXPORT MonoReflectionAssembly*
2534 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2537 MonoDomain *domain = mono_domain_get ();
2538 MonoClass *klass = mono_class_from_mono_type (type->type);
2539 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2541 mono_error_set_pending_exception (&error);
2545 ICALL_EXPORT MonoReflectionType*
2546 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2549 MonoReflectionType *ret;
2550 MonoDomain *domain = mono_domain_get ();
2553 if (type->type->byref)
2555 if (type->type->type == MONO_TYPE_VAR) {
2556 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2557 klass = param ? param->owner.klass : NULL;
2558 } else if (type->type->type == MONO_TYPE_MVAR) {
2559 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2560 klass = param ? param->owner.method->klass : NULL;
2562 klass = mono_class_from_mono_type (type->type)->nested_in;
2568 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2569 mono_error_raise_exception (&error);
2574 ICALL_EXPORT MonoString*
2575 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2577 MonoDomain *domain = mono_domain_get ();
2578 MonoClass *klass = mono_class_from_mono_type (type->type);
2580 if (type->type->byref) {
2581 char *n = g_strdup_printf ("%s&", klass->name);
2582 MonoString *res = mono_string_new (domain, n);
2588 return mono_string_new (domain, klass->name);
2592 ICALL_EXPORT MonoString*
2593 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2595 MonoDomain *domain = mono_domain_get ();
2596 MonoClass *klass = mono_class_from_mono_type (type->type);
2598 while (klass->nested_in)
2599 klass = klass->nested_in;
2601 if (klass->name_space [0] == '\0')
2604 return mono_string_new (domain, klass->name_space);
2608 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2612 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2613 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2617 klass = mono_class_from_mono_type (type->type);
2623 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2626 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2630 ICALL_EXPORT MonoArray*
2631 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2634 MonoReflectionType *rt;
2636 MonoClass *klass, *pklass;
2637 MonoDomain *domain = mono_object_domain (type);
2640 klass = mono_class_from_mono_type (type->type);
2642 if (klass->generic_container) {
2643 MonoGenericContainer *container = klass->generic_container;
2644 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2645 for (i = 0; i < container->type_argc; ++i) {
2646 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2648 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2649 mono_error_raise_exception (&error);
2651 mono_array_setref (res, i, rt);
2653 } else if (klass->generic_class) {
2654 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2655 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2656 for (i = 0; i < inst->type_argc; ++i) {
2657 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2658 mono_error_raise_exception (&error);
2660 mono_array_setref (res, i, rt);
2668 ICALL_EXPORT gboolean
2669 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2673 if (!IS_MONOTYPE (type))
2676 if (type->type->byref)
2679 klass = mono_class_from_mono_type (type->type);
2680 return klass->generic_container != NULL;
2683 ICALL_EXPORT MonoReflectionType*
2684 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2687 MonoReflectionType *ret;
2690 if (type->type->byref)
2693 klass = mono_class_from_mono_type (type->type);
2695 if (klass->generic_container) {
2696 return type; /* check this one */
2698 if (klass->generic_class) {
2699 MonoClass *generic_class = klass->generic_class->container_class;
2702 tb = mono_class_get_ref_info (generic_class);
2704 if (generic_class->wastypebuilder && tb)
2705 return (MonoReflectionType *)tb;
2707 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2708 mono_error_raise_exception (&error);
2716 ICALL_EXPORT MonoReflectionType*
2717 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2720 MonoReflectionType *ret;
2722 MonoType *geninst, **types;
2725 g_assert (IS_MONOTYPE (type));
2726 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2727 mono_error_raise_exception (&error);
2729 count = mono_array_length (type_array);
2730 types = g_new0 (MonoType *, count);
2732 for (i = 0; i < count; i++) {
2733 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2734 types [i] = t->type;
2737 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2740 mono_error_set_pending_exception (&error);
2744 klass = mono_class_from_mono_type (geninst);
2746 /*we might inflate to the GTD*/
2747 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2748 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2752 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2753 mono_error_raise_exception (&error);
2758 ICALL_EXPORT gboolean
2759 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2763 if (!IS_MONOTYPE (type))
2766 if (type->type->byref)
2769 klass = mono_class_from_mono_type (type->type);
2770 return klass->generic_class != NULL || klass->generic_container != NULL;
2774 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2776 if (!IS_MONOTYPE (type))
2779 if (is_generic_parameter (type->type))
2780 return mono_type_get_generic_param_num (type->type);
2784 ICALL_EXPORT GenericParameterAttributes
2785 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2787 g_assert (IS_MONOTYPE (type));
2788 g_assert (is_generic_parameter (type->type));
2789 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2792 ICALL_EXPORT MonoArray *
2793 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2796 MonoReflectionType *rt;
2797 MonoGenericParamInfo *param_info;
2803 g_assert (IS_MONOTYPE (type));
2805 domain = mono_object_domain (type);
2806 param_info = mono_generic_param_info (type->type->data.generic_param);
2807 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2810 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2811 for (i = 0; i < count; i++) {
2812 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2813 mono_error_raise_exception (&error);
2815 mono_array_setref (res, i, rt);
2822 ICALL_EXPORT MonoBoolean
2823 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2825 return is_generic_parameter (type->type);
2828 ICALL_EXPORT MonoBoolean
2829 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2831 return is_generic_parameter (tb->type.type);
2835 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2836 MonoReflectionType *t)
2838 enumtype->type = t->type;
2841 ICALL_EXPORT MonoReflectionMethod*
2842 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2843 MonoReflectionMethod* generic)
2850 MonoReflectionMethod *ret = NULL;
2852 domain = ((MonoObject *)type)->vtable->domain;
2854 klass = mono_class_from_mono_type (type->type);
2855 mono_class_init_checked (klass, &error);
2856 mono_error_raise_exception (&error);
2859 while ((method = mono_class_get_methods (klass, &iter))) {
2860 if (method->token == generic->method->token) {
2861 ret = mono_method_get_object_checked (domain, method, klass, &error);
2862 mono_error_raise_exception (&error);
2869 ICALL_EXPORT MonoReflectionMethod *
2870 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2873 MonoType *type = ref_type->type;
2875 MonoReflectionMethod *ret = NULL;
2877 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2878 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2881 if (type->type == MONO_TYPE_VAR)
2884 method = mono_type_get_generic_param_owner (type)->owner.method;
2887 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2888 if (!mono_error_ok (&error))
2889 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2893 ICALL_EXPORT MonoBoolean
2894 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2896 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2900 ICALL_EXPORT MonoBoolean
2901 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2903 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2908 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2910 MonoDomain *domain = mono_domain_get ();
2911 MonoImage *image = method->method->klass->image;
2912 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2913 MonoTableInfo *tables = image->tables;
2914 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2915 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2916 guint32 im_cols [MONO_IMPLMAP_SIZE];
2917 guint32 scope_token;
2918 const char *import = NULL;
2919 const char *scope = NULL;
2921 if (image_is_dynamic (image)) {
2922 MonoReflectionMethodAux *method_aux =
2923 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2925 import = method_aux->dllentry;
2926 scope = method_aux->dll;
2929 if (!import || !scope) {
2930 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2935 if (piinfo->implmap_idx) {
2936 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2938 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2939 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2940 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2941 scope = mono_metadata_string_heap (image, scope_token);
2945 *flags = piinfo->piflags;
2946 *entry_point = mono_string_new (domain, import);
2947 *dll_name = mono_string_new (domain, scope);
2950 ICALL_EXPORT MonoReflectionMethod *
2951 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2953 MonoMethodInflated *imethod;
2955 MonoReflectionMethod *ret = NULL;
2958 if (method->method->is_generic)
2961 if (!method->method->is_inflated)
2964 imethod = (MonoMethodInflated *) method->method;
2966 result = imethod->declaring;
2967 /* Not a generic method. */
2968 if (!result->is_generic)
2971 if (image_is_dynamic (method->method->klass->image)) {
2972 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2973 MonoReflectionMethod *res;
2976 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2977 * the dynamic case as well ?
2979 mono_image_lock ((MonoImage*)image);
2980 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2981 mono_image_unlock ((MonoImage*)image);
2987 if (imethod->context.class_inst) {
2988 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2989 /*Generic methods gets the context of the GTD.*/
2990 if (mono_class_get_context (klass)) {
2991 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2992 if (!mono_error_ok (&error))
2997 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2999 if (!mono_error_ok (&error))
3000 mono_error_set_pending_exception (&error);
3004 ICALL_EXPORT gboolean
3005 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3007 return mono_method_signature (method->method)->generic_param_count != 0;
3010 ICALL_EXPORT gboolean
3011 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3013 return method->method->is_generic;
3016 ICALL_EXPORT MonoArray*
3017 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3020 MonoReflectionType *rt;
3025 domain = mono_object_domain (method);
3027 if (method->method->is_inflated) {
3028 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3031 count = inst->type_argc;
3032 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3034 for (i = 0; i < count; i++) {
3035 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3036 mono_error_raise_exception (&error);
3038 mono_array_setref (res, i, rt);
3045 count = mono_method_signature (method->method)->generic_param_count;
3046 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3048 for (i = 0; i < count; i++) {
3049 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3050 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3051 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3053 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3054 mono_error_raise_exception (&error);
3056 mono_array_setref (res, i, rt);
3062 ICALL_EXPORT MonoObject *
3063 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3067 * Invoke from reflection is supposed to always be a virtual call (the API
3068 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3069 * greater flexibility.
3071 MonoMethod *m = method->method;
3072 MonoMethodSignature *sig = mono_method_signature (m);
3075 void *obj = this_arg;
3079 if (mono_security_core_clr_enabled () &&
3080 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3081 mono_error_set_pending_exception (&error);
3085 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3086 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3087 mono_error_cleanup (&error); /* FIXME does this make sense? */
3088 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3093 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3094 if (!is_ok (&error)) {
3095 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3098 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3099 char *target_name = mono_type_get_full_name (m->klass);
3100 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3101 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3103 g_free (target_name);
3107 m = mono_object_get_virtual_method (this_arg, m);
3108 /* must pass the pointer to the value for valuetype methods */
3109 if (m->klass->valuetype)
3110 obj = mono_object_unbox (this_arg);
3111 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3112 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3117 if (sig->ret->byref) {
3118 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"));
3122 pcount = params? mono_array_length (params): 0;
3123 if (pcount != sig->param_count) {
3124 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3128 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3129 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."));
3133 image = m->klass->image;
3134 if (image->assembly->ref_only) {
3135 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."));
3139 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3140 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3144 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3148 intptr_t *lower_bounds;
3149 pcount = mono_array_length (params);
3150 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3151 /* Note: the synthetized array .ctors have int32 as argument type */
3152 for (i = 0; i < pcount; ++i)
3153 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3155 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3156 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3157 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3158 if (!mono_error_ok (&error)) {
3159 mono_error_set_pending_exception (&error);
3163 for (i = 0; i < mono_array_length (arr); ++i) {
3164 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3165 if (!mono_error_ok (&error)) {
3166 mono_error_set_pending_exception (&error);
3169 mono_array_setref_fast (arr, i, subarray);
3171 return (MonoObject*)arr;
3174 if (m->klass->rank == pcount) {
3175 /* Only lengths provided. */
3176 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3177 if (!mono_error_ok (&error)) {
3178 mono_error_set_pending_exception (&error);
3182 return (MonoObject*)arr;
3184 g_assert (pcount == (m->klass->rank * 2));
3185 /* The arguments are lower-bound-length pairs */
3186 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3188 for (i = 0; i < pcount / 2; ++i) {
3189 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3190 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3193 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3194 if (!mono_error_ok (&error)) {
3195 mono_error_set_pending_exception (&error);
3199 return (MonoObject*)arr;
3202 return mono_runtime_invoke_array (m, obj, params, NULL);
3205 #ifndef DISABLE_REMOTING
3206 ICALL_EXPORT MonoObject *
3207 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3210 MonoDomain *domain = mono_object_domain (method);
3211 MonoMethod *m = method->method;
3212 MonoMethodSignature *sig = mono_method_signature (m);
3213 MonoArray *out_args;
3215 int i, j, outarg_count = 0;
3217 if (m->klass == mono_defaults.object_class) {
3218 if (!strcmp (m->name, "FieldGetter")) {
3219 MonoClass *k = this_arg->vtable->klass;
3223 /* If this is a proxy, then it must be a CBO */
3224 if (k == mono_defaults.transparent_proxy_class) {
3225 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3226 this_arg = tp->rp->unwrapped_server;
3227 g_assert (this_arg);
3228 k = this_arg->vtable->klass;
3231 name = mono_array_get (params, MonoString *, 1);
3232 str = mono_string_to_utf8 (name);
3235 MonoClassField* field = mono_class_get_field_from_name (k, str);
3237 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3238 if (field_klass->valuetype) {
3239 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3240 mono_error_set_pending_exception (&error);
3241 /* fallthru to cleanup */
3243 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3245 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3246 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3247 mono_array_setref (out_args, 0, result);
3255 g_assert_not_reached ();
3257 } else if (!strcmp (m->name, "FieldSetter")) {
3258 MonoClass *k = this_arg->vtable->klass;
3264 /* If this is a proxy, then it must be a CBO */
3265 if (k == mono_defaults.transparent_proxy_class) {
3266 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3267 this_arg = tp->rp->unwrapped_server;
3268 g_assert (this_arg);
3269 k = this_arg->vtable->klass;
3272 name = mono_array_get (params, MonoString *, 1);
3273 str = mono_string_to_utf8 (name);
3276 MonoClassField* field = mono_class_get_field_from_name (k, str);
3278 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3279 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3281 if (field_klass->valuetype) {
3282 size = mono_type_size (field->type, &align);
3283 g_assert (size == mono_class_value_size (field_klass, NULL));
3284 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3286 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3289 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3290 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3300 g_assert_not_reached ();
3305 for (i = 0; i < mono_array_length (params); i++) {
3306 if (sig->params [i]->byref)
3310 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3312 /* handle constructors only for objects already allocated */
3313 if (!strcmp (method->method->name, ".ctor"))
3314 g_assert (this_arg);
3316 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3317 g_assert (!method->method->klass->valuetype);
3318 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3320 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3321 if (sig->params [i]->byref) {
3323 arg = mono_array_get (params, gpointer, i);
3324 mono_array_setref (out_args, j, arg);
3329 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3336 read_enum_value (const char *mem, int type)
3339 case MONO_TYPE_BOOLEAN:
3341 return *(guint8*)mem;
3343 return *(gint8*)mem;
3344 case MONO_TYPE_CHAR:
3346 return read16 (mem);
3348 return (gint16) read16 (mem);
3350 return read32 (mem);
3352 return (gint32) read32 (mem);
3355 return read64 (mem);
3357 g_assert_not_reached ();
3363 write_enum_value (char *mem, int type, guint64 value)
3367 case MONO_TYPE_I1: {
3368 guint8 *p = (guint8*)mem;
3373 case MONO_TYPE_I2: {
3374 guint16 *p = (guint16 *)mem;
3379 case MONO_TYPE_I4: {
3380 guint32 *p = (guint32 *)mem;
3385 case MONO_TYPE_I8: {
3386 guint64 *p = (guint64 *)mem;
3391 g_assert_not_reached ();
3396 ICALL_EXPORT MonoObject *
3397 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3405 domain = mono_object_domain (enumType);
3406 enumc = mono_class_from_mono_type (enumType->type);
3408 mono_class_init_checked (enumc, &error);
3409 mono_error_raise_exception (&error);
3411 etype = mono_class_enum_basetype (enumc);
3413 res = mono_object_new_checked (domain, enumc, &error);
3414 mono_error_raise_exception (&error);
3415 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3420 ICALL_EXPORT MonoBoolean
3421 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3423 int size = mono_class_value_size (a->vtable->klass, NULL);
3424 guint64 a_val = 0, b_val = 0;
3426 memcpy (&a_val, mono_object_unbox (a), size);
3427 memcpy (&b_val, mono_object_unbox (b), size);
3429 return (a_val & b_val) == b_val;
3432 ICALL_EXPORT MonoObject *
3433 ves_icall_System_Enum_get_value (MonoObject *eobj)
3445 g_assert (eobj->vtable->klass->enumtype);
3447 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3448 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3449 mono_error_raise_exception (&error);
3450 dst = (char *)res + sizeof (MonoObject);
3451 src = (char *)eobj + sizeof (MonoObject);
3452 size = mono_class_value_size (enumc, NULL);
3454 memcpy (dst, src, size);
3459 ICALL_EXPORT MonoReflectionType *
3460 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3463 MonoReflectionType *ret;
3467 klass = mono_class_from_mono_type (type->type);
3468 mono_class_init_checked (klass, &error);
3469 mono_error_raise_exception (&error);
3471 etype = mono_class_enum_basetype (klass);
3473 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3477 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3478 mono_error_raise_exception (&error);
3484 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3486 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3487 gpointer odata = (char *)other + sizeof (MonoObject);
3488 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3489 g_assert (basetype);
3494 if (eobj->vtable->klass != other->vtable->klass)
3497 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3498 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3499 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3502 return me > other ? 1 : -1; \
3505 switch (basetype->type) {
3507 COMPARE_ENUM_VALUES (guint8);
3509 COMPARE_ENUM_VALUES (gint8);
3510 case MONO_TYPE_CHAR:
3512 COMPARE_ENUM_VALUES (guint16);
3514 COMPARE_ENUM_VALUES (gint16);
3516 COMPARE_ENUM_VALUES (guint32);
3518 COMPARE_ENUM_VALUES (gint32);
3520 COMPARE_ENUM_VALUES (guint64);
3522 COMPARE_ENUM_VALUES (gint64);
3526 #undef COMPARE_ENUM_VALUES
3527 /* indicates that the enum was of an unsupported unerlying type */
3532 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3534 gpointer data = (char *)eobj + sizeof (MonoObject);
3535 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3536 g_assert (basetype);
3538 switch (basetype->type) {
3539 case MONO_TYPE_I1: {
3540 gint8 value = *((gint8*)data);
3541 return ((int)value ^ (int)value << 8);
3544 return *((guint8*)data);
3545 case MONO_TYPE_CHAR:
3547 return *((guint16*)data);
3549 case MONO_TYPE_I2: {
3550 gint16 value = *((gint16*)data);
3551 return ((int)(guint16)value | (((int)value) << 16));
3554 return *((guint32*)data);
3556 return *((gint32*)data);
3558 case MONO_TYPE_I8: {
3559 gint64 value = *((gint64*)data);
3560 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3563 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3568 ICALL_EXPORT MonoBoolean
3569 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3572 MonoDomain *domain = mono_object_domain (type);
3573 MonoClass *enumc = mono_class_from_mono_type (type->type);
3574 guint j = 0, nvalues;
3576 MonoClassField *field;
3578 guint64 field_value, previous_value = 0;
3579 gboolean sorted = TRUE;
3581 mono_class_init_checked (enumc, &error);
3582 mono_error_raise_exception (&error);
3584 if (!enumc->enumtype) {
3585 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3589 base_type = mono_class_enum_basetype (enumc)->type;
3591 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3592 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3593 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3596 while ((field = mono_class_get_fields (enumc, &iter))) {
3598 MonoTypeEnum def_type;
3600 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3602 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3604 if (mono_field_is_deleted (field))
3606 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3608 p = mono_class_get_field_default_value (field, &def_type);
3609 /* len = */ mono_metadata_decode_blob_size (p, &p);
3611 field_value = read_enum_value (p, base_type);
3612 mono_array_set (*values, guint64, j, field_value);
3614 if (previous_value > field_value)
3617 previous_value = field_value;
3625 BFLAGS_IgnoreCase = 1,
3626 BFLAGS_DeclaredOnly = 2,
3627 BFLAGS_Instance = 4,
3629 BFLAGS_Public = 0x10,
3630 BFLAGS_NonPublic = 0x20,
3631 BFLAGS_FlattenHierarchy = 0x40,
3632 BFLAGS_InvokeMethod = 0x100,
3633 BFLAGS_CreateInstance = 0x200,
3634 BFLAGS_GetField = 0x400,
3635 BFLAGS_SetField = 0x800,
3636 BFLAGS_GetProperty = 0x1000,
3637 BFLAGS_SetProperty = 0x2000,
3638 BFLAGS_ExactBinding = 0x10000,
3639 BFLAGS_SuppressChangeType = 0x20000,
3640 BFLAGS_OptionalParamBinding = 0x40000
3643 ICALL_EXPORT MonoArray*
3644 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3648 MonoClass *startklass, *klass, *refklass;
3653 char *utf8_name = NULL;
3654 int (*compare_func) (const char *s1, const char *s2) = NULL;
3655 MonoClassField *field;
3656 MonoPtrArray tmp_array;
3658 domain = ((MonoObject *)type)->vtable->domain;
3659 if (type->type->byref)
3660 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3662 klass = startklass = mono_class_from_mono_type (type->type);
3663 refklass = mono_class_from_mono_type (reftype->type);
3665 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3668 if (mono_class_has_failure (klass)) {
3669 mono_ptr_array_destroy (tmp_array);
3670 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3675 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3676 guint32 flags = mono_field_get_flags (field);
3678 if (mono_field_is_deleted_with_flags (field, flags))
3680 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3681 if (bflags & BFLAGS_Public)
3683 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3684 if (bflags & BFLAGS_NonPublic) {
3691 if (flags & FIELD_ATTRIBUTE_STATIC) {
3692 if (bflags & BFLAGS_Static)
3693 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3696 if (bflags & BFLAGS_Instance)
3704 if (utf8_name == NULL) {
3705 utf8_name = mono_string_to_utf8 (name);
3706 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3709 if (compare_func (mono_field_get_name (field), utf8_name))
3713 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3714 if (!mono_error_ok (&error))
3716 mono_ptr_array_append (tmp_array, member);
3718 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3721 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3723 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3724 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3726 mono_ptr_array_destroy (tmp_array);
3728 if (utf8_name != NULL)
3733 mono_ptr_array_destroy (tmp_array);
3734 mono_error_raise_exception (&error);
3735 g_assert_not_reached ();
3739 method_nonpublic (MonoMethod* method, gboolean start_klass)
3741 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3742 case METHOD_ATTRIBUTE_ASSEM:
3743 return (start_klass || mono_defaults.generic_ilist_class);
3744 case METHOD_ATTRIBUTE_PRIVATE:
3746 case METHOD_ATTRIBUTE_PUBLIC:
3754 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3757 MonoClass *startklass;
3761 /*FIXME, use MonoBitSet*/
3762 guint32 method_slots_default [8];
3763 guint32 *method_slots = NULL;
3764 int (*compare_func) (const char *s1, const char *s2) = NULL;
3766 array = g_ptr_array_new ();
3771 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3773 /* An optimization for calls made from Delegate:CreateDelegate () */
3774 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3775 method = mono_get_delegate_invoke (klass);
3776 if (mono_loader_get_last_error ())
3779 g_ptr_array_add (array, method);
3783 mono_class_setup_methods (klass);
3784 mono_class_setup_vtable (klass);
3785 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3788 if (is_generic_parameter (&klass->byval_arg))
3789 nslots = mono_class_get_vtable_size (klass->parent);
3791 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3792 if (nslots >= sizeof (method_slots_default) * 8) {
3793 method_slots = g_new0 (guint32, nslots / 32 + 1);
3795 method_slots = method_slots_default;
3796 memset (method_slots, 0, sizeof (method_slots_default));
3799 mono_class_setup_methods (klass);
3800 mono_class_setup_vtable (klass);
3801 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3805 while ((method = mono_class_get_methods (klass, &iter))) {
3807 if (method->slot != -1) {
3808 g_assert (method->slot < nslots);
3809 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3811 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3812 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3815 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3817 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3818 if (bflags & BFLAGS_Public)
3820 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3826 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3827 if (bflags & BFLAGS_Static)
3828 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3831 if (bflags & BFLAGS_Instance)
3839 if (compare_func (name, method->name))
3844 g_ptr_array_add (array, method);
3846 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3848 if (method_slots != method_slots_default)
3849 g_free (method_slots);
3854 if (method_slots != method_slots_default)
3855 g_free (method_slots);
3856 g_ptr_array_free (array, TRUE);
3858 if (mono_class_has_failure (klass)) {
3859 *ex = mono_class_get_exception_for_failure (klass);
3861 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3862 mono_loader_clear_error ();
3867 ICALL_EXPORT MonoArray*
3868 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3870 static MonoClass *MethodInfo_array;
3874 MonoVTable *array_vtable;
3875 MonoException *ex = NULL;
3876 const char *mname = NULL;
3877 GPtrArray *method_array;
3878 MonoClass *klass, *refklass;
3881 mono_error_init (&error);
3883 if (!MethodInfo_array) {
3884 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3885 mono_memory_barrier ();
3886 MethodInfo_array = klass;
3889 klass = mono_class_from_mono_type (type->type);
3890 refklass = mono_class_from_mono_type (reftype->type);
3891 domain = ((MonoObject *)type)->vtable->domain;
3892 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3893 if (!is_ok (&error)) {
3894 mono_error_set_pending_exception (&error);
3897 if (type->type->byref) {
3898 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3899 mono_error_set_pending_exception (&error);
3905 mname = mono_string_to_utf8 (name);
3907 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3908 g_free ((char*)mname);
3910 mono_set_pending_exception (ex);
3914 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3915 if (!mono_error_ok (&error)) {
3916 mono_error_set_pending_exception (&error);
3920 for (i = 0; i < method_array->len; ++i) {
3921 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3922 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3923 if (!mono_error_ok (&error))
3925 mono_array_setref (res, i, rm);
3929 g_ptr_array_free (method_array, TRUE);
3930 if (!mono_error_ok (&error))
3931 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3935 ICALL_EXPORT MonoArray*
3936 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3939 MonoClass *startklass, *klass, *refklass;
3944 gpointer iter = NULL;
3945 MonoPtrArray tmp_array;
3948 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3950 domain = ((MonoObject *)type)->vtable->domain;
3951 if (type->type->byref)
3952 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3953 klass = startklass = mono_class_from_mono_type (type->type);
3954 refklass = mono_class_from_mono_type (reftype->type);
3956 mono_class_setup_methods (klass);
3957 if (mono_class_has_failure (klass)) {
3958 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3963 while ((method = mono_class_get_methods (klass, &iter))) {
3965 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3967 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3968 if (bflags & BFLAGS_Public)
3971 if (bflags & BFLAGS_NonPublic)
3977 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3978 if (bflags & BFLAGS_Static)
3979 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3982 if (bflags & BFLAGS_Instance)
3988 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3989 if (!mono_error_ok (&error)) {
3990 mono_error_set_pending_exception (&error);
3994 mono_ptr_array_append (tmp_array, member);
3997 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
3999 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4000 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4002 mono_ptr_array_destroy (tmp_array);
4008 property_hash (gconstpointer data)
4010 MonoProperty *prop = (MonoProperty*)data;
4012 return g_str_hash (prop->name);
4016 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
4018 if (method1->is_inflated)
4019 method1 = ((MonoMethodInflated*) method1)->declaring;
4020 if (method2->is_inflated)
4021 method2 = ((MonoMethodInflated*) method2)->declaring;
4023 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4027 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4029 // Properties are hide-by-name-and-signature
4030 if (!g_str_equal (prop1->name, prop2->name))
4033 /* If we see a property in a generic method, we want to
4034 compare the generic signatures, not the inflated signatures
4035 because we might conflate two properties that were
4039 public T this[T t] { getter { return t; } } // method 1
4040 public U this[U u] { getter { return u; } } // method 2
4043 If we see int Foo<int,int>::Item[int] we need to know if
4044 the indexer came from method 1 or from method 2, and we
4045 shouldn't conflate them. (Bugzilla 36283)
4047 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
4050 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4057 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4062 return method_nonpublic (accessor, start_klass);
4065 ICALL_EXPORT MonoArray*
4066 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4070 MonoClass *startklass, *klass;
4076 gchar *propname = NULL;
4077 int (*compare_func) (const char *s1, const char *s2) = NULL;
4079 GHashTable *properties = NULL;
4080 MonoPtrArray tmp_array;
4082 mono_error_init (&error);
4084 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4086 domain = ((MonoObject *)type)->vtable->domain;
4087 if (type->type->byref)
4088 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
4089 klass = startklass = mono_class_from_mono_type (type->type);
4092 propname = mono_string_to_utf8 (name);
4093 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4096 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4098 mono_class_setup_methods (klass);
4099 mono_class_setup_vtable (klass);
4100 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4104 while ((prop = mono_class_get_properties (klass, &iter))) {
4110 flags = method->flags;
4113 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4114 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4115 if (bflags & BFLAGS_Public)
4117 } else if (bflags & BFLAGS_NonPublic) {
4118 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4119 property_accessor_nonpublic(prop->set, startklass == klass)) {
4126 if (flags & METHOD_ATTRIBUTE_STATIC) {
4127 if (bflags & BFLAGS_Static)
4128 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4131 if (bflags & BFLAGS_Instance)
4140 if (compare_func (propname, prop->name))
4144 if (g_hash_table_lookup (properties, prop))
4147 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4150 mono_ptr_array_append (tmp_array, pr);
4152 g_hash_table_insert (properties, prop, prop);
4154 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4157 g_hash_table_destroy (properties);
4160 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4161 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4162 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4164 mono_ptr_array_destroy (tmp_array);
4171 if (mono_class_has_failure (klass)) {
4172 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4174 mono_error_set_from_loader_error (&error);
4175 mono_loader_clear_error ();
4180 g_hash_table_destroy (properties);
4183 mono_ptr_array_destroy (tmp_array);
4185 mono_error_set_pending_exception (&error);
4191 event_hash (gconstpointer data)
4193 MonoEvent *event = (MonoEvent*)data;
4195 return g_str_hash (event->name);
4199 event_equal (MonoEvent *event1, MonoEvent *event2)
4201 // Events are hide-by-name
4202 return g_str_equal (event1->name, event2->name);
4205 ICALL_EXPORT MonoArray*
4206 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4210 MonoClass *startklass, *klass;
4216 char *utf8_name = NULL;
4217 int (*compare_func) (const char *s1, const char *s2) = NULL;
4218 GHashTable *events = NULL;
4219 MonoPtrArray tmp_array;
4221 mono_error_init (&error);
4223 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4225 domain = mono_object_domain (type);
4226 if (type->type->byref)
4227 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4228 klass = startklass = mono_class_from_mono_type (type->type);
4230 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4232 mono_class_setup_methods (klass);
4233 mono_class_setup_vtable (klass);
4234 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4238 while ((event = mono_class_get_events (klass, &iter))) {
4240 method = event->add;
4242 method = event->remove;
4244 method = event->raise;
4246 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4247 if (bflags & BFLAGS_Public)
4249 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4250 if (bflags & BFLAGS_NonPublic)
4255 if (bflags & BFLAGS_NonPublic)
4261 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4262 if (bflags & BFLAGS_Static)
4263 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4266 if (bflags & BFLAGS_Instance)
4271 if (bflags & BFLAGS_Instance)
4277 if (utf8_name == NULL) {
4278 utf8_name = mono_string_to_utf8 (name);
4279 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4282 if (compare_func (event->name, utf8_name))
4286 if (g_hash_table_lookup (events, event))
4289 MonoReflectionEvent *ev_obj;
4290 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4293 mono_ptr_array_append (tmp_array, ev_obj);
4295 g_hash_table_insert (events, event, event);
4297 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4300 g_hash_table_destroy (events);
4302 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4304 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4305 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4307 mono_ptr_array_destroy (tmp_array);
4309 if (utf8_name != NULL)
4315 if (mono_class_has_failure (klass)) {
4316 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4318 mono_error_set_from_loader_error (&error);
4319 mono_loader_clear_error ();
4325 g_hash_table_destroy (events);
4326 if (utf8_name != NULL)
4329 mono_ptr_array_destroy (tmp_array);
4331 mono_error_set_pending_exception (&error);
4335 ICALL_EXPORT MonoArray*
4336 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4339 MonoReflectionType *rt;
4347 MonoPtrArray tmp_array;
4349 domain = ((MonoObject *)type)->vtable->domain;
4350 if (type->type->byref)
4351 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4352 klass = mono_class_from_mono_type (type->type);
4355 * If a nested type is generic, return its generic type definition.
4356 * Note that this means that the return value is essentially the set
4357 * of nested types of the generic type definition of @klass.
4359 * A note in MSDN claims that a generic type definition can have
4360 * nested types that aren't generic. In any case, the container of that
4361 * nested type would be the generic type definition.
4363 if (klass->generic_class)
4364 klass = klass->generic_class->container_class;
4366 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4368 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4370 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4371 if (bflags & BFLAGS_Public)
4374 if (bflags & BFLAGS_NonPublic)
4382 str = mono_string_to_utf8 (name);
4383 mono_identifier_unescape_type_name_chars (str);
4386 if (strcmp (nested->name, str))
4390 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4391 mono_error_raise_exception (&error);
4393 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4396 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4398 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4399 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4401 mono_ptr_array_destroy (tmp_array);
4408 ICALL_EXPORT MonoReflectionType*
4409 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4412 MonoReflectionType *ret;
4414 MonoType *type = NULL;
4415 MonoTypeNameParse info;
4416 gboolean type_resolve;
4418 /* On MS.NET, this does not fire a TypeResolve event */
4419 type_resolve = TRUE;
4420 str = mono_string_to_utf8 (name);
4421 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4422 if (!mono_reflection_parse_type (str, &info)) {
4424 mono_reflection_free_type_info (&info);
4426 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4429 /*g_print ("failed parse\n");*/
4433 if (info.assembly.name) {
4435 mono_reflection_free_type_info (&info);
4437 /* 1.0 and 2.0 throw different exceptions */
4438 if (mono_defaults.generic_ilist_class)
4439 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4441 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4447 if (module != NULL) {
4448 if (module->image) {
4449 type = mono_reflection_get_type_checked (module->image, &info, ignoreCase, &type_resolve, &error);
4450 if (!is_ok (&error)) {
4452 mono_reflection_free_type_info (&info);
4453 mono_error_set_pending_exception (&error);
4460 if (assembly_is_dynamic (assembly->assembly)) {
4461 /* Enumerate all modules */
4462 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4466 if (abuilder->modules) {
4467 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4468 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4469 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4470 if (!is_ok (&error)) {
4472 mono_reflection_free_type_info (&info);
4473 mono_error_set_pending_exception (&error);
4481 if (!type && abuilder->loaded_modules) {
4482 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4483 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4484 type = mono_reflection_get_type_checked (mod->image, &info, ignoreCase, &type_resolve, &error);
4485 if (!is_ok (&error)) {
4487 mono_reflection_free_type_info (&info);
4488 mono_error_set_pending_exception (&error);
4497 type = mono_reflection_get_type_checked (assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4498 if (!is_ok (&error)) {
4500 mono_reflection_free_type_info (&info);
4501 mono_error_set_pending_exception (&error);
4506 mono_reflection_free_type_info (&info);
4508 MonoException *e = NULL;
4511 e = mono_get_exception_type_load (name, NULL);
4513 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4514 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4516 mono_loader_clear_error ();
4519 mono_set_pending_exception (e);
4521 } else if (mono_loader_get_last_error ()) {
4523 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4526 mono_loader_clear_error ();
4529 if (type->type == MONO_TYPE_CLASS) {
4530 MonoClass *klass = mono_type_get_class (type);
4532 /* need to report exceptions ? */
4533 if (throwOnError && mono_class_has_failure (klass)) {
4534 /* report SecurityException (or others) that occured when loading the assembly */
4535 MonoException *exc = mono_class_get_exception_for_failure (klass);
4536 mono_loader_clear_error ();
4537 mono_set_pending_exception (exc);
4542 /* g_print ("got it\n"); */
4543 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4544 mono_error_set_pending_exception (&error);
4550 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4553 gchar *shadow_ini_file;
4556 /* Check for shadow-copied assembly */
4557 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4558 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4560 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4561 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4567 g_free (shadow_ini_file);
4568 if (content != NULL) {
4571 *filename = content;
4578 ICALL_EXPORT MonoString *
4579 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4581 MonoDomain *domain = mono_object_domain (assembly);
4582 MonoAssembly *mass = assembly->assembly;
4583 MonoString *res = NULL;
4588 if (g_path_is_absolute (mass->image->name)) {
4589 absolute = g_strdup (mass->image->name);
4590 dirname = g_path_get_dirname (absolute);
4592 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4593 dirname = g_strdup (mass->basedir);
4596 replace_shadow_path (domain, dirname, &absolute);
4601 for (i = strlen (absolute) - 1; i >= 0; i--)
4602 if (absolute [i] == '\\')
4607 uri = g_filename_to_uri (absolute, NULL, NULL);
4609 const char *prepend = "file://";
4611 if (*absolute == '/' && *(absolute + 1) == '/') {
4614 prepend = "file:///";
4617 uri = g_strconcat (prepend, absolute, NULL);
4621 res = mono_string_new (domain, uri);
4628 ICALL_EXPORT MonoBoolean
4629 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4631 MonoAssembly *mass = assembly->assembly;
4633 return mass->in_gac;
4636 ICALL_EXPORT MonoReflectionAssembly*
4637 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4642 MonoImageOpenStatus status;
4643 MonoReflectionAssembly* result = NULL;
4645 name = mono_string_to_utf8 (mname);
4646 res = mono_assembly_load_with_partial_name (name, &status);
4652 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4654 mono_error_set_pending_exception (&error);
4658 ICALL_EXPORT MonoString *
4659 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4661 MonoDomain *domain = mono_object_domain (assembly);
4664 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4669 ICALL_EXPORT MonoBoolean
4670 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4672 return assembly->assembly->ref_only;
4675 ICALL_EXPORT MonoString *
4676 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4678 MonoDomain *domain = mono_object_domain (assembly);
4680 return mono_string_new (domain, assembly->assembly->image->version);
4683 ICALL_EXPORT MonoReflectionMethod*
4684 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4687 MonoReflectionMethod *res = NULL;
4690 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4694 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4695 if (!mono_error_ok (&error))
4698 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4701 if (!mono_error_ok (&error))
4702 mono_error_set_pending_exception (&error);
4706 ICALL_EXPORT MonoReflectionModule*
4707 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4710 MonoReflectionModule *result = NULL;
4711 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4712 if (!mono_error_ok (&error))
4713 mono_error_set_pending_exception (&error);
4717 ICALL_EXPORT MonoArray*
4718 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4720 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4721 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4725 for (i = 0; i < table->rows; ++i) {
4726 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4727 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4733 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4735 static MonoMethod *create_version = NULL;
4739 mono_error_init (error);
4742 if (!create_version) {
4743 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4744 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4745 g_assert (create_version);
4746 mono_method_desc_free (desc);
4752 args [3] = &revision;
4753 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4754 return_val_if_nok (error, NULL);
4756 mono_runtime_invoke_checked (create_version, result, args, error);
4757 return_val_if_nok (error, NULL);
4762 ICALL_EXPORT MonoArray*
4763 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4767 MonoDomain *domain = mono_object_domain (assembly);
4769 static MonoMethod *create_culture = NULL;
4770 MonoImage *image = assembly->assembly->image;
4774 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4777 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4779 if (count > 0 && !create_culture) {
4780 MonoMethodDesc *desc = mono_method_desc_new (
4781 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4782 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4783 g_assert (create_culture);
4784 mono_method_desc_free (desc);
4787 for (i = 0; i < count; i++) {
4788 MonoObject *version;
4789 MonoReflectionAssemblyName *aname;
4790 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4792 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4794 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4795 domain, mono_class_get_assembly_name_class (), &error);
4796 mono_error_raise_exception (&error);
4798 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4800 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4801 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4802 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4803 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4804 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4805 aname->versioncompat = 1; /* SameMachine (default) */
4806 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4808 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4809 mono_error_raise_exception (&error);
4811 MONO_OBJECT_SETREF (aname, version, version);
4813 if (create_culture) {
4815 MonoBoolean assembly_ref = 1;
4816 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4817 args [1] = &assembly_ref;
4819 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4820 mono_error_raise_exception (&error);
4822 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4825 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4826 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4827 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4829 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4830 /* public key token isn't copied - the class library will
4831 automatically generate it from the public key if required */
4832 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4833 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4835 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4836 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4839 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4842 /* note: this function doesn't return the codebase on purpose (i.e. it can
4843 be used under partial trust as path information isn't present). */
4845 mono_array_setref (result, i, aname);
4850 /* move this in some file in mono/util/ */
4852 g_concat_dir_and_file (const char *dir, const char *file)
4854 g_return_val_if_fail (dir != NULL, NULL);
4855 g_return_val_if_fail (file != NULL, NULL);
4858 * If the directory name doesn't have a / on the end, we need
4859 * to add one so we get a proper path to the file
4861 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4862 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4864 return g_strconcat (dir, file, NULL);
4868 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4871 char *n = mono_string_to_utf8 (name);
4872 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4874 guint32 cols [MONO_MANIFEST_SIZE];
4875 guint32 impl, file_idx;
4879 for (i = 0; i < table->rows; ++i) {
4880 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4881 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4882 if (strcmp (val, n) == 0)
4886 if (i == table->rows)
4889 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4892 * this code should only be called after obtaining the
4893 * ResourceInfo and handling the other cases.
4895 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4896 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4898 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4903 module = assembly->assembly->image;
4906 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4907 mono_error_raise_exception (&error);
4908 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4910 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4913 ICALL_EXPORT gboolean
4914 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4917 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4919 guint32 cols [MONO_MANIFEST_SIZE];
4920 guint32 file_cols [MONO_FILE_SIZE];
4924 n = mono_string_to_utf8 (name);
4925 for (i = 0; i < table->rows; ++i) {
4926 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4927 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4928 if (strcmp (val, n) == 0)
4932 if (i == table->rows)
4935 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4936 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4939 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4940 case MONO_IMPLEMENTATION_FILE:
4941 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4942 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4943 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4944 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4945 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4946 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4949 info->location = RESOURCE_LOCATION_EMBEDDED;
4952 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4953 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4954 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4955 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4956 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4957 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4959 mono_set_pending_exception (ex);
4962 MonoReflectionAssembly *assm_obj;
4963 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4965 mono_error_set_pending_exception (&error);
4968 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4970 /* Obtain info recursively */
4971 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4972 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4975 case MONO_IMPLEMENTATION_EXP_TYPE:
4976 g_assert_not_reached ();
4984 ICALL_EXPORT MonoObject*
4985 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4987 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4988 MonoArray *result = NULL;
4993 /* check hash if needed */
4995 n = mono_string_to_utf8 (name);
4996 for (i = 0; i < table->rows; ++i) {
4997 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4998 if (strcmp (val, n) == 0) {
5001 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5002 fn = mono_string_new (mono_object_domain (assembly), n);
5004 return (MonoObject*)fn;
5012 for (i = 0; i < table->rows; ++i) {
5013 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5017 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
5020 for (i = 0; i < table->rows; ++i) {
5021 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5022 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5023 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5024 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5029 return (MonoObject*)result;
5032 ICALL_EXPORT MonoArray*
5033 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5036 MonoDomain *domain = mono_domain_get();
5039 int i, j, file_count = 0;
5040 MonoImage **modules;
5041 guint32 module_count, real_module_count;
5042 MonoTableInfo *table;
5043 guint32 cols [MONO_FILE_SIZE];
5044 MonoImage *image = assembly->assembly->image;
5046 g_assert (image != NULL);
5047 g_assert (!assembly_is_dynamic (assembly->assembly));
5049 table = &image->tables [MONO_TABLE_FILE];
5050 file_count = table->rows;
5052 modules = image->modules;
5053 module_count = image->module_count;
5055 real_module_count = 0;
5056 for (i = 0; i < module_count; ++i)
5058 real_module_count ++;
5060 klass = mono_class_get_module_class ();
5061 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
5063 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5064 mono_error_raise_exception (&error);
5065 mono_array_setref (res, 0, image_obj);
5067 for (i = 0; i < module_count; ++i)
5069 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5070 mono_error_raise_exception (&error);
5071 mono_array_setref (res, j, rm);
5075 for (i = 0; i < file_count; ++i, ++j) {
5076 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5077 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5078 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5079 mono_error_raise_exception (&error);
5080 mono_array_setref (res, j, rm);
5083 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5085 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5086 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5089 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5090 mono_error_raise_exception (&error);
5091 mono_array_setref (res, j, rm);
5098 ICALL_EXPORT MonoReflectionMethod*
5099 ves_icall_GetCurrentMethod (void)
5101 MonoReflectionMethod *res = NULL;
5104 MonoMethod *m = mono_method_get_last_managed ();
5107 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5111 while (m->is_inflated)
5112 m = ((MonoMethodInflated*)m)->declaring;
5114 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5115 mono_error_raise_exception (&error);
5121 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5124 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5127 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5128 //method is inflated, we should inflate it on the other class
5129 MonoGenericContext ctx;
5130 ctx.method_inst = inflated->context.method_inst;
5131 ctx.class_inst = inflated->context.class_inst;
5132 if (klass->generic_class)
5133 ctx.class_inst = klass->generic_class->context.class_inst;
5134 else if (klass->generic_container)
5135 ctx.class_inst = klass->generic_container->context.class_inst;
5136 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5137 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5141 mono_class_setup_methods (method->klass);
5142 if (mono_class_has_failure (method->klass))
5144 for (i = 0; i < method->klass->method.count; ++i) {
5145 if (method->klass->methods [i] == method) {
5150 mono_class_setup_methods (klass);
5151 if (mono_class_has_failure (klass))
5153 g_assert (offset >= 0 && offset < klass->method.count);
5154 return klass->methods [offset];
5157 ICALL_EXPORT MonoReflectionMethod*
5158 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5160 MonoReflectionMethod *res = NULL;
5164 klass = mono_class_from_mono_type (type);
5165 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5167 if (method->klass != klass) {
5168 method = mono_method_get_equivalent_method (method, klass);
5173 klass = method->klass;
5174 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5175 mono_error_raise_exception (&error);
5179 ICALL_EXPORT MonoReflectionMethodBody*
5180 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5183 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5184 mono_error_set_pending_exception (&error);
5188 ICALL_EXPORT MonoReflectionAssembly*
5189 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5192 MonoReflectionAssembly *result;
5193 MonoMethod *dest = NULL;
5195 mono_stack_walk_no_il (get_executing, &dest);
5197 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5199 mono_error_set_pending_exception (&error);
5204 ICALL_EXPORT MonoReflectionAssembly*
5205 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5208 MonoReflectionAssembly *result;
5209 MonoDomain* domain = mono_domain_get ();
5211 if (!domain->entry_assembly)
5214 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5216 mono_error_set_pending_exception (&error);
5220 ICALL_EXPORT MonoReflectionAssembly*
5221 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5226 MonoReflectionAssembly *result;
5229 mono_stack_walk_no_il (get_executing, &dest);
5231 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5235 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5238 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5240 mono_error_set_pending_exception (&error);
5244 ICALL_EXPORT MonoString *
5245 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5246 gboolean assembly_qualified)
5248 MonoDomain *domain = mono_object_domain (object);
5249 MonoTypeNameFormat format;
5254 format = assembly_qualified ?
5255 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5256 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5258 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5260 name = mono_type_get_name_full (object->type, format);
5264 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5269 res = mono_string_new (domain, name);
5276 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5279 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5281 mono_class_init_checked (klass, &error);
5282 mono_error_raise_exception (&error);
5283 return mono_security_core_clr_class_level (klass);
5287 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5289 MonoClassField *field = rfield->field;
5290 return mono_security_core_clr_field_level (field, TRUE);
5294 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5296 MonoMethod *method = rfield->method;
5297 return mono_security_core_clr_method_level (method, TRUE);
5301 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)
5303 static MonoMethod *create_culture = NULL;
5307 const char *pkey_ptr;
5309 MonoBoolean assembly_ref = 0;
5311 mono_error_init (error);
5313 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5314 aname->major = name->major;
5315 aname->minor = name->minor;
5316 aname->build = name->build;
5317 aname->flags = name->flags;
5318 aname->revision = name->revision;
5319 aname->hashalg = name->hash_alg;
5320 aname->versioncompat = 1; /* SameMachine (default) */
5321 aname->processor_architecture = name->arch;
5323 if (by_default_version) {
5324 MonoObject *version;
5326 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5327 return_if_nok (error);
5329 MONO_OBJECT_SETREF (aname, version, version);
5333 if (absolute != NULL && *absolute != '\0') {
5334 const gchar *prepend = "file://";
5337 codebase = g_strdup (absolute);
5342 for (i = strlen (codebase) - 1; i >= 0; i--)
5343 if (codebase [i] == '\\')
5346 if (*codebase == '/' && *(codebase + 1) == '/') {
5349 prepend = "file:///";
5353 result = g_strconcat (prepend, codebase, NULL);
5359 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5363 if (!create_culture) {
5364 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5365 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5366 g_assert (create_culture);
5367 mono_method_desc_free (desc);
5370 if (name->culture) {
5371 args [0] = mono_string_new (domain, name->culture);
5372 args [1] = &assembly_ref;
5374 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5375 return_if_nok (error);
5377 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5380 if (name->public_key) {
5381 pkey_ptr = (char*)name->public_key;
5382 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5384 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5385 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5386 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5387 } else if (default_publickey) {
5388 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5389 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5392 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5393 if (name->public_key_token [0]) {
5397 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5398 p = mono_array_addr (aname->keyToken, char, 0);
5400 for (i = 0, j = 0; i < 8; i++) {
5401 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5402 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5405 } else if (default_token) {
5406 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5410 ICALL_EXPORT MonoString *
5411 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5413 MonoDomain *domain = mono_object_domain (assembly);
5414 MonoAssembly *mass = assembly->assembly;
5418 name = mono_stringify_assembly_name (&mass->aname);
5419 res = mono_string_new (domain, name);
5426 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5430 MonoAssembly *mass = assembly->assembly;
5432 if (g_path_is_absolute (mass->image->name)) {
5433 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5434 mono_error_set_pending_exception (&error);
5437 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5439 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5440 mono_error_set_pending_exception (&error);
5446 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5450 MonoImageOpenStatus status = MONO_IMAGE_OK;
5453 MonoAssemblyName name;
5456 filename = mono_string_to_utf8 (fname);
5458 dirname = g_path_get_dirname (filename);
5459 replace_shadow_path (mono_domain_get (), dirname, &filename);
5462 image = mono_image_open (filename, &status);
5468 if (status == MONO_IMAGE_IMAGE_INVALID)
5469 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5471 exc = mono_get_exception_file_not_found2 (NULL, fname);
5472 mono_set_pending_exception (exc);
5476 res = mono_assembly_fill_assembly_name (image, &name);
5478 mono_image_close (image);
5480 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5484 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5485 mono_error_set_pending_exception (&error);
5487 mono_image_close (image);
5491 ICALL_EXPORT MonoBoolean
5492 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5493 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5495 MonoBoolean result = FALSE;
5496 MonoDeclSecurityEntry entry;
5498 /* SecurityAction.RequestMinimum */
5499 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5500 *minimum = entry.blob;
5501 *minLength = entry.size;
5504 /* SecurityAction.RequestOptional */
5505 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5506 *optional = entry.blob;
5507 *optLength = entry.size;
5510 /* SecurityAction.RequestRefuse */
5511 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5512 *refused = entry.blob;
5513 *refLength = entry.size;
5521 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5523 guint32 attrs, visibility;
5525 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5526 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5527 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5530 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5536 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5538 MonoReflectionType *rt;
5541 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5544 mono_error_init (error);
5546 /* we start the count from 1 because we skip the special type <Module> */
5549 for (i = 1; i < tdef->rows; ++i) {
5550 if (mono_module_type_is_visible (tdef, image, i + 1))
5554 count = tdef->rows - 1;
5556 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5557 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5559 for (i = 1; i < tdef->rows; ++i) {
5560 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5561 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5562 mono_loader_assert_no_error (); /* Plug any leaks */
5565 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5566 return_val_if_nok (error, NULL);
5568 mono_array_setref (res, count, rt);
5570 MonoException *ex = mono_error_convert_to_exception (error);
5571 mono_array_setref (*exceptions, count, ex);
5580 ICALL_EXPORT MonoArray*
5581 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5584 MonoArray *res = NULL;
5585 MonoArray *exceptions = NULL;
5586 MonoImage *image = NULL;
5587 MonoTableInfo *table = NULL;
5590 int i, len, ex_count;
5592 domain = mono_object_domain (assembly);
5594 g_assert (!assembly_is_dynamic (assembly->assembly));
5595 image = assembly->assembly->image;
5596 table = &image->tables [MONO_TABLE_FILE];
5597 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5598 mono_error_raise_exception (&error);
5600 /* Append data from all modules in the assembly */
5601 for (i = 0; i < table->rows; ++i) {
5602 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5603 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5608 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5609 mono_error_raise_exception (&error);
5611 /* Append the new types to the end of the array */
5612 if (mono_array_length (res2) > 0) {
5614 MonoArray *res3, *ex3;
5616 len1 = mono_array_length (res);
5617 len2 = mono_array_length (res2);
5619 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5620 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5621 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5624 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5625 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5626 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5633 /* the ReflectionTypeLoadException must have all the types (Types property),
5634 * NULL replacing types which throws an exception. The LoaderException must
5635 * contain all exceptions for NULL items.
5638 len = mono_array_length (res);
5641 for (i = 0; i < len; i++) {
5642 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5646 klass = mono_type_get_class (t->type);
5647 if ((klass != NULL) && mono_class_has_failure (klass)) {
5648 /* keep the class in the list */
5649 list = g_list_append (list, klass);
5650 /* and replace Type with NULL */
5651 mono_array_setref (res, i, NULL);
5658 if (list || ex_count) {
5660 MonoException *exc = NULL;
5661 MonoArray *exl = NULL;
5662 int j, length = g_list_length (list) + ex_count;
5664 mono_loader_clear_error ();
5666 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5667 /* Types for which mono_class_get_checked () succeeded */
5668 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5669 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5670 mono_array_setref (exl, i, exc);
5672 /* Types for which it don't */
5673 for (j = 0; j < mono_array_length (exceptions); ++j) {
5674 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5676 g_assert (i < length);
5677 mono_array_setref (exl, i, exc);
5684 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5685 if (!is_ok (&error)) {
5686 mono_error_set_pending_exception (&error);
5689 mono_loader_clear_error ();
5690 mono_set_pending_exception (exc);
5697 ICALL_EXPORT gboolean
5698 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5701 MonoAssemblyName aname;
5702 MonoDomain *domain = mono_object_domain (name);
5704 gboolean is_version_defined;
5705 gboolean is_token_defined;
5707 aname.public_key = NULL;
5708 val = mono_string_to_utf8 (assname);
5709 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5710 g_free ((guint8*) aname.public_key);
5715 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5716 mono_error_set_pending_exception (&error);
5718 mono_assembly_name_free (&aname);
5719 g_free ((guint8*) aname.public_key);
5725 ICALL_EXPORT MonoReflectionType*
5726 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5729 MonoReflectionType *ret;
5730 MonoDomain *domain = mono_object_domain (module);
5733 g_assert (module->image);
5735 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5736 /* These images do not have a global type */
5739 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5740 if (!mono_error_ok (&error)) {
5741 mono_error_set_pending_exception (&error);
5745 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5746 if (!mono_error_ok (&error)) {
5747 mono_error_set_pending_exception (&error);
5755 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5757 /*if (module->image)
5758 mono_image_close (module->image);*/
5761 ICALL_EXPORT MonoString*
5762 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5764 MonoDomain *domain = mono_object_domain (module);
5766 g_assert (module->image);
5767 return mono_string_new (domain, module->image->guid);
5770 ICALL_EXPORT gpointer
5771 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5774 if (module->image && module->image->is_module_handle)
5775 return module->image->raw_data;
5778 return (gpointer) (-1);
5782 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5784 if (image_is_dynamic (image)) {
5785 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5786 *pe_kind = dyn->pe_kind;
5787 *machine = dyn->machine;
5790 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5791 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5796 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5798 return (image->md_version_major << 16) | (image->md_version_minor);
5801 ICALL_EXPORT MonoArray*
5802 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5805 MonoArray *exceptions;
5809 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5813 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5814 mono_error_raise_exception (&error);
5816 for (i = 0; i < mono_array_length (exceptions); ++i) {
5817 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5819 mono_set_pending_exception (ex);
5828 mono_memberref_is_method (MonoImage *image, guint32 token)
5830 if (!image_is_dynamic (image)) {
5831 guint32 cols [MONO_MEMBERREF_SIZE];
5833 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5834 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5835 mono_metadata_decode_blob_size (sig, &sig);
5836 return (*sig != 0x6);
5839 MonoClass *handle_class;
5841 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5842 mono_error_cleanup (&error); /* just probing, ignore error */
5846 return mono_defaults.methodhandle_class == handle_class;
5851 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5854 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5855 mono_array_addr (type_args, MonoType*, 0));
5857 context->class_inst = NULL;
5859 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5860 mono_array_addr (method_args, MonoType*, 0));
5862 context->method_inst = NULL;
5865 ICALL_EXPORT MonoType*
5866 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5869 int table = mono_metadata_token_table (token);
5870 int index = mono_metadata_token_index (token);
5871 MonoGenericContext context;
5874 *resolve_error = ResolveTokenError_Other;
5876 /* Validate token */
5877 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5878 (table != MONO_TABLE_TYPESPEC)) {
5879 *resolve_error = ResolveTokenError_BadTable;
5883 if (image_is_dynamic (image)) {
5884 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5885 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5886 mono_error_cleanup (&error);
5887 return klass ? &klass->byval_arg : NULL;
5890 init_generic_context_from_args (&context, type_args, method_args);
5891 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5892 mono_error_cleanup (&error);
5893 return klass ? &klass->byval_arg : NULL;
5896 if ((index <= 0) || (index > image->tables [table].rows)) {
5897 *resolve_error = ResolveTokenError_OutOfRange;
5901 init_generic_context_from_args (&context, type_args, method_args);
5902 klass = mono_class_get_checked (image, token, &error);
5904 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5905 if (!mono_error_ok (&error)) {
5906 mono_error_set_pending_exception (&error);
5911 return &klass->byval_arg;
5916 ICALL_EXPORT MonoMethod*
5917 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5920 int table = mono_metadata_token_table (token);
5921 int index = mono_metadata_token_index (token);
5922 MonoGenericContext context;
5925 *resolve_error = ResolveTokenError_Other;
5927 /* Validate token */
5928 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5929 (table != MONO_TABLE_MEMBERREF)) {
5930 *resolve_error = ResolveTokenError_BadTable;
5934 if (image_is_dynamic (image)) {
5935 if (table == MONO_TABLE_METHOD) {
5936 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5937 mono_error_cleanup (&error);
5941 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5942 *resolve_error = ResolveTokenError_BadTable;
5946 init_generic_context_from_args (&context, type_args, method_args);
5947 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5948 mono_error_cleanup (&error);
5952 if ((index <= 0) || (index > image->tables [table].rows)) {
5953 *resolve_error = ResolveTokenError_OutOfRange;
5956 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5957 *resolve_error = ResolveTokenError_BadTable;
5961 init_generic_context_from_args (&context, type_args, method_args);
5962 method = mono_get_method_checked (image, token, NULL, &context, &error);
5963 mono_error_set_pending_exception (&error);
5968 ICALL_EXPORT MonoString*
5969 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5972 int index = mono_metadata_token_index (token);
5974 *resolve_error = ResolveTokenError_Other;
5976 /* Validate token */
5977 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5978 *resolve_error = ResolveTokenError_BadTable;
5982 if (image_is_dynamic (image)) {
5983 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5984 mono_error_cleanup (&error);
5988 if ((index <= 0) || (index >= image->heap_us.size)) {
5989 *resolve_error = ResolveTokenError_OutOfRange;
5993 /* FIXME: What to do if the index points into the middle of a string ? */
5995 return mono_ldstr (mono_domain_get (), image, index);
5998 ICALL_EXPORT MonoClassField*
5999 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6003 int table = mono_metadata_token_table (token);
6004 int index = mono_metadata_token_index (token);
6005 MonoGenericContext context;
6006 MonoClassField *field;
6008 *resolve_error = ResolveTokenError_Other;
6010 /* Validate token */
6011 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6012 *resolve_error = ResolveTokenError_BadTable;
6016 if (image_is_dynamic (image)) {
6017 if (table == MONO_TABLE_FIELD) {
6018 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6019 mono_error_cleanup (&error);
6023 if (mono_memberref_is_method (image, token)) {
6024 *resolve_error = ResolveTokenError_BadTable;
6028 init_generic_context_from_args (&context, type_args, method_args);
6029 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6030 mono_error_cleanup (&error);
6034 if ((index <= 0) || (index > image->tables [table].rows)) {
6035 *resolve_error = ResolveTokenError_OutOfRange;
6038 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6039 *resolve_error = ResolveTokenError_BadTable;
6043 init_generic_context_from_args (&context, type_args, method_args);
6044 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6045 mono_error_set_pending_exception (&error);
6051 ICALL_EXPORT MonoObject*
6052 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6056 int table = mono_metadata_token_table (token);
6058 *error = ResolveTokenError_Other;
6061 case MONO_TABLE_TYPEDEF:
6062 case MONO_TABLE_TYPEREF:
6063 case MONO_TABLE_TYPESPEC: {
6064 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6066 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6067 mono_error_raise_exception (&merror);
6074 case MONO_TABLE_METHOD:
6075 case MONO_TABLE_METHODSPEC: {
6076 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6078 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6079 mono_error_raise_exception (&merror);
6085 case MONO_TABLE_FIELD: {
6086 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6088 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6089 mono_error_raise_exception (&merror);
6095 case MONO_TABLE_MEMBERREF:
6096 if (mono_memberref_is_method (image, token)) {
6097 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6099 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6100 mono_error_raise_exception (&merror);
6107 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6109 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6110 mono_error_raise_exception (&merror);
6119 *error = ResolveTokenError_BadTable;
6125 ICALL_EXPORT MonoArray*
6126 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
6128 int table = mono_metadata_token_table (token);
6129 int idx = mono_metadata_token_index (token);
6130 MonoTableInfo *tables = image->tables;
6135 *error = ResolveTokenError_OutOfRange;
6137 /* FIXME: Support other tables ? */
6138 if (table != MONO_TABLE_STANDALONESIG)
6141 if (image_is_dynamic (image))
6144 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6147 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6149 ptr = mono_metadata_blob_heap (image, sig);
6150 len = mono_metadata_decode_blob_size (ptr, &ptr);
6152 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
6153 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6157 ICALL_EXPORT MonoReflectionType*
6158 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6161 MonoReflectionType *ret;
6163 int isbyref = 0, rank;
6164 char *str = mono_string_to_utf8 (smodifiers);
6167 klass = mono_class_from_mono_type (tb->type.type);
6169 /* logic taken from mono_reflection_parse_type(): keep in sync */
6173 if (isbyref) { /* only one level allowed by the spec */
6182 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6183 mono_error_raise_exception (&error);
6187 klass = mono_ptr_class_get (&klass->byval_arg);
6188 mono_class_init (klass);
6199 else if (*p != '*') { /* '*' means unknown lower bound */
6210 klass = mono_array_class_get (klass, rank);
6211 mono_class_init (klass);
6220 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6221 mono_error_raise_exception (&error);
6226 ICALL_EXPORT MonoBoolean
6227 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6233 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6239 check_for_invalid_type (MonoClass *klass, MonoError *error)
6244 mono_error_init (error);
6246 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6249 name = mono_type_get_full_name (klass);
6250 str = mono_string_new (mono_domain_get (), name);
6252 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6255 ICALL_EXPORT MonoReflectionType *
6256 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6259 MonoReflectionType *ret;
6260 MonoClass *klass, *aklass;
6262 klass = mono_class_from_mono_type (type->type);
6263 check_for_invalid_type (klass, &error);
6264 mono_error_raise_exception (&error);
6266 if (rank == 0) //single dimentional array
6267 aklass = mono_array_class_get (klass, 1);
6269 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6271 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6272 mono_error_raise_exception (&error);
6277 ICALL_EXPORT MonoReflectionType *
6278 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6281 MonoReflectionType *ret;
6284 klass = mono_class_from_mono_type (type->type);
6285 mono_class_init_checked (klass, &error);
6286 mono_error_raise_exception (&error);
6287 check_for_invalid_type (klass, &error);
6288 mono_error_raise_exception (&error);
6290 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6291 mono_error_raise_exception (&error);
6296 ICALL_EXPORT MonoReflectionType *
6297 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6300 MonoReflectionType *ret;
6301 MonoClass *klass, *pklass;
6303 klass = mono_class_from_mono_type (type->type);
6304 mono_class_init_checked (klass, &error);
6305 mono_error_raise_exception (&error);
6306 check_for_invalid_type (klass, &error);
6307 mono_error_raise_exception (&error);
6309 pklass = mono_ptr_class_get (type->type);
6311 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6312 mono_error_raise_exception (&error);
6317 ICALL_EXPORT MonoObject *
6318 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6319 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6322 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6323 MonoObject *delegate;
6325 MonoMethod *method = info->method;
6327 mono_class_init_checked (delegate_class, &error);
6328 mono_error_raise_exception (&error);
6330 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6331 /* FIXME improve this exception message */
6332 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6334 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6335 mono_error_set_pending_exception (&error);
6339 if (mono_security_core_clr_enabled ()) {
6340 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6341 if (throwOnBindFailure)
6342 mono_error_set_pending_exception (&error);
6344 mono_error_cleanup (&error);
6349 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6350 mono_error_raise_exception (&error);
6352 if (method_is_dynamic (method)) {
6353 /* Creating a trampoline would leak memory */
6354 func = mono_compile_method (method);
6356 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6357 method = mono_object_get_virtual_method (target, method);
6358 func = mono_create_ftnptr (mono_domain_get (),
6359 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6362 mono_delegate_ctor_with_method (delegate, target, func, method);
6367 ICALL_EXPORT MonoMulticastDelegate *
6368 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6371 MonoMulticastDelegate *ret;
6373 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6375 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6376 mono_error_raise_exception (&error);
6377 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6382 ICALL_EXPORT MonoReflectionMethod*
6383 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6385 MonoReflectionMethod *ret = NULL;
6387 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6388 mono_error_raise_exception (&error);
6394 static inline gint32
6395 mono_array_get_byte_length (MonoArray *array)
6401 klass = array->obj.vtable->klass;
6403 if (array->bounds == NULL)
6404 length = array->max_length;
6407 for (i = 0; i < klass->rank; ++ i)
6408 length *= array->bounds [i].length;
6411 switch (klass->element_class->byval_arg.type) {
6414 case MONO_TYPE_BOOLEAN:
6418 case MONO_TYPE_CHAR:
6426 return length * sizeof (gpointer);
6437 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6439 return mono_array_get_byte_length (array);
6443 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6445 return mono_array_get (array, gint8, idx);
6449 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6451 mono_array_set (array, gint8, idx, value);
6454 ICALL_EXPORT MonoBoolean
6455 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6457 guint8 *src_buf, *dest_buf;
6460 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6464 g_assert (count >= 0);
6466 /* This is called directly from the class libraries without going through the managed wrapper */
6467 MONO_CHECK_ARG_NULL (src, FALSE);
6468 MONO_CHECK_ARG_NULL (dest, FALSE);
6470 /* watch out for integer overflow */
6471 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6474 src_buf = (guint8 *)src->vector + src_offset;
6475 dest_buf = (guint8 *)dest->vector + dest_offset;
6478 memcpy (dest_buf, src_buf, count);
6480 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6485 #ifndef DISABLE_REMOTING
6486 ICALL_EXPORT MonoObject *
6487 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6490 MonoDomain *domain = mono_object_domain (this_obj);
6492 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6493 MonoTransparentProxy *tp;
6497 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6498 mono_error_raise_exception (&error);
6499 tp = (MonoTransparentProxy*) res;
6501 MONO_OBJECT_SETREF (tp, rp, rp);
6502 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6503 klass = mono_class_from_mono_type (type);
6505 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6506 mono_class_setup_vtable (klass);
6507 if (mono_class_has_failure (klass)) {
6508 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6512 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6513 if (!is_ok (&error)) {
6514 mono_error_set_pending_exception (&error);
6517 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6518 if (!is_ok (&error)) {
6519 mono_error_set_pending_exception (&error);
6523 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6527 ICALL_EXPORT MonoReflectionType *
6528 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6531 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6532 mono_error_raise_exception (&error);
6538 /* System.Environment */
6541 ves_icall_System_Environment_get_UserName (void)
6543 /* using glib is more portable */
6544 return mono_string_new (mono_domain_get (), g_get_user_name ());
6548 ICALL_EXPORT MonoString *
6549 ves_icall_System_Environment_get_MachineName (void)
6551 #if defined (HOST_WIN32)
6556 len = MAX_COMPUTERNAME_LENGTH + 1;
6557 buf = g_new (gunichar2, len);
6560 if (GetComputerName (buf, (PDWORD) &len)) {
6562 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6563 mono_error_raise_exception (&error);
6568 #elif !defined(DISABLE_SOCKETS)
6572 #if defined _SC_HOST_NAME_MAX
6573 n = sysconf (_SC_HOST_NAME_MAX);
6577 buf = g_malloc (n+1);
6579 if (gethostname (buf, n) == 0){
6581 result = mono_string_new (mono_domain_get (), buf);
6588 return mono_string_new (mono_domain_get (), "mono");
6593 ves_icall_System_Environment_get_Platform (void)
6595 #if defined (TARGET_WIN32)
6598 #elif defined(__MACH__)
6601 // Notice that the value is hidden from user code, and only exposed
6602 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6603 // define and making assumptions based on Unix/128/4 values before there
6604 // was a MacOS define. Lots of code would assume that not-Unix meant
6605 // Windows, but in this case, it would be OSX.
6614 ICALL_EXPORT MonoString *
6615 ves_icall_System_Environment_get_NewLine (void)
6617 #if defined (HOST_WIN32)
6618 return mono_string_new (mono_domain_get (), "\r\n");
6620 return mono_string_new (mono_domain_get (), "\n");
6624 ICALL_EXPORT MonoBoolean
6625 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6627 #if SIZEOF_VOID_P == 8
6631 gboolean isWow64Process = FALSE;
6632 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6633 return (MonoBoolean)isWow64Process;
6635 #elif defined(HAVE_SYS_UTSNAME_H)
6636 struct utsname name;
6638 if (uname (&name) >= 0) {
6639 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6646 ICALL_EXPORT MonoString *
6647 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6655 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6656 value = g_getenv (utf8_name);
6663 return mono_string_new (mono_domain_get (), value);
6667 * There is no standard way to get at environ.
6670 #ifndef __MINGW32_VERSION
6671 #if defined(__APPLE__)
6672 #if defined (TARGET_OSX)
6673 /* Apple defines this in crt_externs.h but doesn't provide that header for
6674 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6675 * in fact exist on all implementations (so far)
6677 gchar ***_NSGetEnviron(void);
6678 #define environ (*_NSGetEnviron())
6680 static char *mono_environ[1] = { NULL };
6681 #define environ mono_environ
6682 #endif /* defined (TARGET_OSX) */
6690 ICALL_EXPORT MonoArray *
6691 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6702 env_strings = GetEnvironmentStrings();
6705 env_string = env_strings;
6706 while (*env_string != '\0') {
6707 /* weird case that MS seems to skip */
6708 if (*env_string != '=')
6710 while (*env_string != '\0')
6716 domain = mono_domain_get ();
6717 names = mono_array_new (domain, mono_defaults.string_class, n);
6721 env_string = env_strings;
6722 while (*env_string != '\0') {
6723 /* weird case that MS seems to skip */
6724 if (*env_string != '=') {
6725 equal_str = wcschr(env_string, '=');
6726 g_assert(equal_str);
6728 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6729 mono_error_raise_exception (&error);
6730 mono_array_setref (names, n, str);
6733 while (*env_string != '\0')
6738 FreeEnvironmentStrings (env_strings);
6751 for (e = environ; *e != 0; ++ e)
6754 domain = mono_domain_get ();
6755 names = mono_array_new (domain, mono_defaults.string_class, n);
6758 for (e = environ; *e != 0; ++ e) {
6759 parts = g_strsplit (*e, "=", 2);
6761 str = mono_string_new (domain, *parts);
6762 mono_array_setref (names, n, str);
6775 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6777 #if !GLIB_CHECK_VERSION(2,4,0)
6778 #define g_setenv(a,b,c) setenv(a,b,c)
6779 #define g_unsetenv(a) unsetenv(a)
6783 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6786 gunichar2 *utf16_name, *utf16_value;
6788 gchar *utf8_name, *utf8_value;
6793 utf16_name = mono_string_to_utf16 (name);
6794 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6795 SetEnvironmentVariable (utf16_name, NULL);
6796 g_free (utf16_name);
6800 utf16_value = mono_string_to_utf16 (value);
6802 SetEnvironmentVariable (utf16_name, utf16_value);
6804 g_free (utf16_name);
6805 g_free (utf16_value);
6807 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6809 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6810 g_unsetenv (utf8_name);
6815 utf8_value = mono_string_to_utf8_checked (value, &error);
6816 if (!mono_error_ok (&error)) {
6818 mono_error_set_pending_exception (&error);
6821 g_setenv (utf8_name, utf8_value, TRUE);
6824 g_free (utf8_value);
6829 ves_icall_System_Environment_Exit (int result)
6831 mono_environment_exitcode_set (result);
6833 /* FIXME: There are some cleanup hangs that should be worked out, but
6834 * if the program is going to exit, everything will be cleaned up when
6835 * NaCl exits anyway.
6837 #ifndef __native_client__
6838 if (!mono_runtime_try_shutdown ())
6839 mono_thread_exit ();
6841 /* Suspend all managed threads since the runtime is going away */
6842 mono_thread_suspend_all_other_threads ();
6844 mono_runtime_quit ();
6847 /* we may need to do some cleanup here... */
6851 ICALL_EXPORT MonoString*
6852 ves_icall_System_Environment_GetGacPath (void)
6854 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6857 ICALL_EXPORT MonoString*
6858 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6860 #if defined (HOST_WIN32)
6861 #ifndef CSIDL_FLAG_CREATE
6862 #define CSIDL_FLAG_CREATE 0x8000
6865 WCHAR path [MAX_PATH];
6866 /* Create directory if no existing */
6867 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6872 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6873 mono_error_raise_exception (&error);
6877 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6879 return mono_string_new (mono_domain_get (), "");
6882 ICALL_EXPORT MonoArray *
6883 ves_icall_System_Environment_GetLogicalDrives (void)
6886 gunichar2 buf [256], *ptr, *dname;
6888 guint initial_size = 127, size = 128;
6891 MonoString *drivestr;
6892 MonoDomain *domain = mono_domain_get ();
6898 while (size > initial_size) {
6899 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6900 if (size > initial_size) {
6903 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6904 initial_size = size;
6918 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6923 while (*u16) { u16++; len ++; }
6924 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6925 mono_error_raise_exception (&error);
6926 mono_array_setref (result, ndrives++, drivestr);
6936 ICALL_EXPORT MonoString *
6937 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6939 gunichar2 volume_name [MAX_PATH + 1];
6941 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6943 return mono_string_from_utf16 (volume_name);
6946 ICALL_EXPORT MonoString *
6947 ves_icall_System_Environment_InternalGetHome (void)
6949 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6952 static const char *encodings [] = {
6954 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6955 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6956 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6958 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6959 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6960 "x_unicode_2_0_utf_7",
6962 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6963 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6965 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6968 "unicodefffe", "utf_16be",
6975 * Returns the internal codepage, if the value of "int_code_page" is
6976 * 1 at entry, and we can not compute a suitable code page number,
6977 * returns the code page as a string
6979 ICALL_EXPORT MonoString*
6980 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6985 char *codepage = NULL;
6987 int want_name = *int_code_page;
6990 *int_code_page = -1;
6992 g_get_charset (&cset);
6993 c = codepage = strdup (cset);
6994 for (c = codepage; *c; c++){
6995 if (isascii (*c) && isalpha (*c))
7000 /* g_print ("charset: %s\n", cset); */
7002 /* handle some common aliases */
7005 for (i = 0; p != 0; ){
7008 p = encodings [++i];
7011 if (strcmp (p, codepage) == 0){
7012 *int_code_page = code;
7015 p = encodings [++i];
7018 if (strstr (codepage, "utf_8") != NULL)
7019 *int_code_page |= 0x10000000;
7022 if (want_name && *int_code_page == -1)
7023 return mono_string_new (mono_domain_get (), cset);
7028 ICALL_EXPORT MonoBoolean
7029 ves_icall_System_Environment_get_HasShutdownStarted (void)
7031 if (mono_runtime_is_shutting_down ())
7034 if (mono_domain_is_unloading (mono_domain_get ()))
7041 ves_icall_System_Environment_BroadcastSettingChange (void)
7044 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7049 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7055 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
7056 MonoReflectionMethod *method,
7057 MonoArray *out_args)
7059 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
7062 #ifndef DISABLE_REMOTING
7063 ICALL_EXPORT MonoBoolean
7064 ves_icall_IsTransparentProxy (MonoObject *proxy)
7069 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7075 ICALL_EXPORT MonoReflectionMethod *
7076 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7077 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7079 MonoReflectionMethod *ret = NULL;
7084 MonoMethod **vtable;
7085 MonoMethod *res = NULL;
7087 MONO_CHECK_ARG_NULL (rtype, NULL);
7088 MONO_CHECK_ARG_NULL (rmethod, NULL);
7090 method = rmethod->method;
7091 klass = mono_class_from_mono_type (rtype->type);
7092 mono_class_init_checked (klass, &error);
7093 mono_error_raise_exception (&error);
7095 if (MONO_CLASS_IS_INTERFACE (klass))
7098 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7101 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7102 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7108 mono_class_setup_vtable (klass);
7109 vtable = klass->vtable;
7111 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7112 gboolean variance_used = FALSE;
7113 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7114 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7116 res = vtable [offs + method->slot];
7118 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7121 if (method->slot != -1)
7122 res = vtable [method->slot];
7128 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7129 mono_error_raise_exception (&error);
7134 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7140 klass = mono_class_from_mono_type (type->type);
7141 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7142 if (!is_ok (&error)) {
7143 mono_error_set_pending_exception (&error);
7147 mono_vtable_set_is_remote (vtable, enable);
7150 #else /* DISABLE_REMOTING */
7153 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7155 g_assert_not_reached ();
7160 ICALL_EXPORT MonoObject *
7161 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7168 domain = mono_object_domain (type);
7169 klass = mono_class_from_mono_type (type->type);
7170 mono_class_init_checked (klass, &error);
7171 mono_error_raise_exception (&error);
7173 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7174 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7178 if (klass->rank >= 1) {
7179 g_assert (klass->rank == 1);
7180 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7182 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7183 if (!is_ok (&error)) {
7184 mono_error_set_pending_exception (&error);
7187 /* Bypass remoting object creation check */
7188 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7189 mono_error_set_pending_exception (&error);
7195 ICALL_EXPORT MonoString *
7196 ves_icall_System_IO_get_temp_path (void)
7198 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7201 #ifndef PLATFORM_NO_DRIVEINFO
7202 ICALL_EXPORT MonoBoolean
7203 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7204 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7208 ULARGE_INTEGER wapi_free_bytes_avail;
7209 ULARGE_INTEGER wapi_total_number_of_bytes;
7210 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7212 *error = ERROR_SUCCESS;
7213 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7214 &wapi_total_number_of_free_bytes);
7217 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7218 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7219 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7221 *free_bytes_avail = 0;
7222 *total_number_of_bytes = 0;
7223 *total_number_of_free_bytes = 0;
7224 *error = GetLastError ();
7230 ICALL_EXPORT guint32
7231 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7233 return GetDriveType (mono_string_chars (root_path_name));
7237 ICALL_EXPORT gpointer
7238 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7240 return mono_compile_method (method);
7243 ICALL_EXPORT MonoString *
7244 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7249 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7251 #if defined (HOST_WIN32)
7252 /* Avoid mixing '/' and '\\' */
7255 for (i = strlen (path) - 1; i >= 0; i--)
7256 if (path [i] == '/')
7260 mcpath = mono_string_new (mono_domain_get (), path);
7267 get_bundled_app_config (void)
7269 const gchar *app_config;
7272 gchar *config_file_name, *config_file_path;
7273 gsize len, config_file_path_length, config_ext_length;
7276 domain = mono_domain_get ();
7277 file = domain->setup->configuration_file;
7278 if (!file || file->length == 0)
7281 // Retrieve config file and remove the extension
7282 config_file_name = mono_string_to_utf8 (file);
7283 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7284 if (!config_file_path)
7285 config_file_path = config_file_name;
7287 config_file_path_length = strlen (config_file_path);
7288 config_ext_length = strlen (".config");
7289 if (config_file_path_length <= config_ext_length)
7292 len = config_file_path_length - config_ext_length;
7293 module = (gchar *)g_malloc0 (len + 1);
7294 memcpy (module, config_file_path, len);
7295 // Get the config file from the module name
7296 app_config = mono_config_string_for_assembly_file (module);
7299 if (config_file_name != config_file_path)
7300 g_free (config_file_name);
7301 g_free (config_file_path);
7306 return mono_string_new (mono_domain_get (), app_config);
7310 get_bundled_machine_config (void)
7312 const gchar *machine_config;
7314 machine_config = mono_get_machine_config ();
7316 if (!machine_config)
7319 return mono_string_new (mono_domain_get (), machine_config);
7322 ICALL_EXPORT MonoString *
7323 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7328 path = g_path_get_dirname (mono_get_config_dir ());
7330 #if defined (HOST_WIN32)
7331 /* Avoid mixing '/' and '\\' */
7334 for (i = strlen (path) - 1; i >= 0; i--)
7335 if (path [i] == '/')
7339 ipath = mono_string_new (mono_domain_get (), path);
7345 ICALL_EXPORT gboolean
7346 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7348 MonoPEResourceDataEntry *entry;
7351 if (!assembly || !result || !size)
7356 image = assembly->assembly->image;
7357 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7361 *result = mono_image_rva_map (image, entry->rde_data_offset);
7366 *size = entry->rde_size;
7371 ICALL_EXPORT MonoBoolean
7372 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7374 return mono_is_debugger_attached ();
7377 ICALL_EXPORT MonoBoolean
7378 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7380 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7381 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7387 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7389 if (mono_get_runtime_callbacks ()->debug_log)
7390 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7394 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7396 #if defined (HOST_WIN32)
7397 OutputDebugString (mono_string_chars (message));
7399 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7403 /* Only used for value types */
7404 ICALL_EXPORT MonoObject *
7405 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7412 domain = mono_object_domain (type);
7413 klass = mono_class_from_mono_type (type->type);
7414 mono_class_init_checked (klass, &error);
7415 mono_error_raise_exception (&error);
7417 if (mono_class_is_nullable (klass))
7418 /* No arguments -> null */
7421 result = mono_object_new_checked (domain, klass, &error);
7422 mono_error_raise_exception (&error);
7426 ICALL_EXPORT MonoReflectionMethod *
7427 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7429 MonoReflectionMethod *ret = NULL;
7432 MonoClass *klass, *parent;
7433 MonoGenericContext *generic_inst = NULL;
7434 MonoMethod *method = m->method;
7435 MonoMethod *result = NULL;
7438 if (method->klass == NULL)
7441 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7442 MONO_CLASS_IS_INTERFACE (method->klass) ||
7443 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7446 slot = mono_method_get_vtable_slot (method);
7450 klass = method->klass;
7451 if (klass->generic_class) {
7452 generic_inst = mono_class_get_context (klass);
7453 klass = klass->generic_class->container_class;
7457 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7458 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7459 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7460 or klass is the generic container class and generic_inst is the instantiation.
7462 when we go to the parent, if the parent is an open constructed type, we need to
7463 replace the type parameters by the definitions from the generic_inst, and then take it
7464 apart again into the klass and the generic_inst.
7466 For cases like this:
7467 class C<T> : B<T, int> {
7468 public override void Foo () { ... }
7470 class B<U,V> : A<HashMap<U,V>> {
7471 public override void Foo () { ... }
7474 public virtual void Foo () { ... }
7477 if at each iteration the parent isn't open, we can skip inflating it. if at some
7478 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7481 MonoGenericContext *parent_inst = NULL;
7482 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7484 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7485 if (!mono_error_ok (&error)) {
7486 mono_error_set_pending_exception (&error);
7490 if (parent->generic_class) {
7491 parent_inst = mono_class_get_context (parent);
7492 parent = parent->generic_class->container_class;
7495 mono_class_setup_vtable (parent);
7496 if (parent->vtable_size <= slot)
7499 generic_inst = parent_inst;
7502 klass = klass->parent;
7505 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7506 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7507 if (!mono_error_ok (&error)) {
7508 mono_error_set_pending_exception (&error);
7512 generic_inst = NULL;
7514 if (klass->generic_class) {
7515 generic_inst = mono_class_get_context (klass);
7516 klass = klass->generic_class->container_class;
7522 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7523 if (!mono_error_ok (&error)) {
7524 mono_error_set_pending_exception (&error);
7529 if (klass == method->klass)
7532 /*This is possible if definition == FALSE.
7533 * Do it here to be really sure we don't read invalid memory.
7535 if (slot >= klass->vtable_size)
7538 mono_class_setup_vtable (klass);
7540 result = klass->vtable [slot];
7541 if (result == NULL) {
7542 /* It is an abstract method */
7543 gpointer iter = NULL;
7544 while ((result = mono_class_get_methods (klass, &iter)))
7545 if (result->slot == slot)
7552 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7553 mono_error_raise_exception (&error);
7557 ICALL_EXPORT MonoString*
7558 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7560 MonoMethod *method = m->method;
7562 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7567 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7569 iter->sig = *(MonoMethodSignature**)argsp;
7571 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7572 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7575 /* FIXME: it's not documented what start is exactly... */
7579 iter->args = argsp + sizeof (gpointer);
7581 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7583 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7586 ICALL_EXPORT MonoTypedRef
7587 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7589 guint32 i, arg_size;
7593 i = iter->sig->sentinelpos + iter->next_arg;
7595 g_assert (i < iter->sig->param_count);
7597 res.type = iter->sig->params [i];
7598 res.klass = mono_class_from_mono_type (res.type);
7599 arg_size = mono_type_stack_size (res.type, &align);
7600 #if defined(__arm__) || defined(__mips__)
7601 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7603 res.value = iter->args;
7604 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7605 /* Values are stored as 8 byte register sized objects, but 'value'
7606 * is dereferenced as a pointer in other routines.
7608 res.value = (char*)res.value + 4;
7610 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7611 if (arg_size <= sizeof (gpointer)) {
7613 int padding = arg_size - mono_type_size (res.type, &dummy);
7614 res.value = (guint8*)res.value + padding;
7617 iter->args = (char*)iter->args + arg_size;
7620 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7625 ICALL_EXPORT MonoTypedRef
7626 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7628 guint32 i, arg_size;
7632 i = iter->sig->sentinelpos + iter->next_arg;
7634 g_assert (i < iter->sig->param_count);
7636 while (i < iter->sig->param_count) {
7637 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7639 res.type = iter->sig->params [i];
7640 res.klass = mono_class_from_mono_type (res.type);
7641 /* FIXME: endianess issue... */
7642 arg_size = mono_type_stack_size (res.type, &align);
7643 #if defined(__arm__) || defined(__mips__)
7644 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7646 res.value = iter->args;
7647 iter->args = (char*)iter->args + arg_size;
7649 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7652 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7660 ICALL_EXPORT MonoType*
7661 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7665 i = iter->sig->sentinelpos + iter->next_arg;
7667 g_assert (i < iter->sig->param_count);
7669 return iter->sig->params [i];
7672 ICALL_EXPORT MonoObject*
7673 mono_TypedReference_ToObject (MonoTypedRef* tref)
7676 MonoObject *result = NULL;
7677 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7678 MonoObject** objp = (MonoObject **)tref->value;
7682 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7683 mono_error_set_pending_exception (&error);
7687 ICALL_EXPORT MonoTypedRef
7688 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7691 MonoReflectionField *f;
7693 MonoType *ftype = NULL;
7697 memset (&res, 0, sizeof (res));
7700 g_assert (mono_array_length (fields) > 0);
7702 klass = target->vtable->klass;
7704 for (i = 0; i < mono_array_length (fields); ++i) {
7705 f = mono_array_get (fields, MonoReflectionField*, i);
7707 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7710 if (f->field->parent != klass) {
7711 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7715 p = (guint8*)target + f->field->offset;
7717 p += f->field->offset - sizeof (MonoObject);
7718 klass = mono_class_from_mono_type (f->field->type);
7719 ftype = f->field->type;
7723 res.klass = mono_class_from_mono_type (ftype);
7730 prelink_method (MonoMethod *method, MonoError *error)
7732 const char *exc_class, *exc_arg;
7734 mono_error_init (error);
7735 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7737 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7739 mono_error_set_exception_instance (error,
7740 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7743 /* create the wrapper, too? */
7747 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7751 prelink_method (method->method, &error);
7752 mono_error_raise_exception (&error);
7756 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7759 MonoClass *klass = mono_class_from_mono_type (type->type);
7761 gpointer iter = NULL;
7763 mono_class_init_checked (klass, &error);
7764 mono_error_raise_exception (&error);
7766 while ((m = mono_class_get_methods (klass, &iter))) {
7767 prelink_method (m, &error);
7768 mono_error_raise_exception (&error);
7772 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7774 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7775 gint32 const **exponents,
7776 gunichar2 const **digitLowerTable,
7777 gunichar2 const **digitUpperTable,
7778 gint64 const **tenPowersList,
7779 gint32 const **decHexDigits)
7781 *mantissas = Formatter_MantissaBitsTable;
7782 *exponents = Formatter_TensExponentTable;
7783 *digitLowerTable = Formatter_DigitLowerTable;
7784 *digitUpperTable = Formatter_DigitUpperTable;
7785 *tenPowersList = Formatter_TenPowersList;
7786 *decHexDigits = Formatter_DecHexDigits;
7790 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7791 * and avoid useless allocations.
7794 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7796 MonoReflectionType *rt;
7800 mono_error_init (error);
7801 for (i = 0; i < type->num_mods; ++i) {
7802 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7807 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7809 for (i = 0; i < type->num_mods; ++i) {
7810 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7811 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7812 return_val_if_nok (error, NULL);
7814 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7815 return_val_if_nok (error, NULL);
7817 mono_array_setref (res, count, rt);
7824 ICALL_EXPORT MonoArray*
7825 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7828 MonoType *type = param->ClassImpl->type;
7829 MonoClass *member_class = mono_object_class (param->MemberImpl);
7830 MonoMethod *method = NULL;
7833 MonoMethodSignature *sig;
7836 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7837 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7838 method = rmethod->method;
7839 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7840 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7841 if (!(method = prop->property->get))
7842 method = prop->property->set;
7845 char *type_name = mono_type_get_full_name (member_class);
7846 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7847 MonoException *ex = mono_get_exception_not_supported (msg);
7850 mono_set_pending_exception (ex);
7854 image = method->klass->image;
7855 pos = param->PositionImpl;
7856 sig = mono_method_signature (method);
7860 type = sig->params [pos];
7862 res = type_array_from_modifiers (image, type, optional, &error);
7863 mono_error_raise_exception (&error);
7868 get_property_type (MonoProperty *prop)
7870 MonoMethodSignature *sig;
7872 sig = mono_method_signature (prop->get);
7874 } else if (prop->set) {
7875 sig = mono_method_signature (prop->set);
7876 return sig->params [sig->param_count - 1];
7881 ICALL_EXPORT MonoArray*
7882 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7885 MonoType *type = get_property_type (property->property);
7886 MonoImage *image = property->klass->image;
7891 res = type_array_from_modifiers (image, type, optional, &error);
7892 mono_error_raise_exception (&error);
7897 *Construct a MonoType suited to be used to decode a constant blob object.
7899 * @type is the target type which will be constructed
7900 * @blob_type is the blob type, for example, that comes from the constant table
7901 * @real_type is the expected constructed type.
7904 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7906 type->type = blob_type;
7907 type->data.klass = NULL;
7908 if (blob_type == MONO_TYPE_CLASS)
7909 type->data.klass = mono_defaults.object_class;
7910 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7911 /* For enums, we need to use the base type */
7912 type->type = MONO_TYPE_VALUETYPE;
7913 type->data.klass = mono_class_from_mono_type (real_type);
7915 type->data.klass = mono_class_from_mono_type (real_type);
7918 ICALL_EXPORT MonoObject*
7919 property_info_get_default_value (MonoReflectionProperty *property)
7923 MonoProperty *prop = property->property;
7924 MonoType *type = get_property_type (prop);
7925 MonoDomain *domain = mono_object_domain (property);
7926 MonoTypeEnum def_type;
7927 const char *def_value;
7930 mono_class_init (prop->parent);
7932 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7933 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7937 def_value = mono_class_get_property_default_value (prop, &def_type);
7939 mono_type_from_blob_type (&blob_type, def_type, type);
7940 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7942 mono_error_set_pending_exception (&error);
7946 ICALL_EXPORT MonoBoolean
7947 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7950 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7951 MonoCustomAttrInfo *cinfo;
7954 mono_class_init_checked (attr_class, &error);
7955 mono_error_raise_exception (&error);
7957 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7958 if (!is_ok (&error)) {
7959 mono_error_set_pending_exception (&error);
7964 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7966 mono_custom_attrs_free (cinfo);
7970 ICALL_EXPORT MonoArray*
7971 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7973 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7978 mono_class_init_checked (attr_class, &error);
7979 mono_error_raise_exception (&error);
7982 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7983 if (!mono_error_ok (&error)) {
7984 mono_error_set_pending_exception (&error);
7988 if (mono_loader_get_last_error ()) {
7989 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7996 ICALL_EXPORT MonoArray*
7997 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8001 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8002 mono_error_set_pending_exception (&error);
8007 ICALL_EXPORT MonoString*
8008 ves_icall_Mono_Runtime_GetDisplayName (void)
8011 MonoString *display_name;
8013 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8014 display_name = mono_string_new (mono_domain_get (), info);
8016 return display_name;
8019 ICALL_EXPORT MonoString*
8020 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8023 MonoString *message;
8027 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8028 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8031 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8033 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8034 mono_error_raise_exception (&error);
8040 ICALL_EXPORT gpointer
8041 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8043 return GetCurrentProcess ();
8046 ICALL_EXPORT MonoBoolean
8047 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8049 return GetExitCodeProcess (handle, (guint32*) exitcode);
8052 ICALL_EXPORT MonoBoolean
8053 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8055 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8056 return CloseHandle (handle);
8058 return CloseProcess (handle);
8062 ICALL_EXPORT MonoBoolean
8063 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8065 return TerminateProcess (handle, exitcode);
8069 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8071 return WaitForInputIdle (handle, milliseconds);
8074 ICALL_EXPORT MonoBoolean
8075 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8077 return GetProcessWorkingSetSize (handle, min, max);
8080 ICALL_EXPORT MonoBoolean
8081 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8083 return SetProcessWorkingSetSize (handle, min, max);
8086 ICALL_EXPORT MonoBoolean
8087 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8089 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8093 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8095 return mono_process_current_pid ();
8099 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8101 return GetPriorityClass (handle);
8104 ICALL_EXPORT MonoBoolean
8105 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8107 return SetPriorityClass (handle, priorityClass);
8110 #ifndef DISABLE_ICALL_TABLES
8112 #define ICALL_TYPE(id,name,first)
8113 #define ICALL(id,name,func) Icall_ ## id,
8116 #include "metadata/icall-def.h"
8122 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8123 #define ICALL(id,name,func)
8125 #include "metadata/icall-def.h"
8131 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8132 #define ICALL(id,name,func)
8134 guint16 first_icall;
8137 static const IcallTypeDesc
8138 icall_type_descs [] = {
8139 #include "metadata/icall-def.h"
8143 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8146 #define ICALL_TYPE(id,name,first)
8149 #ifdef HAVE_ARRAY_ELEM_INIT
8150 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8151 #define MSGSTRFIELD1(line) str##line
8153 static const struct msgstrtn_t {
8154 #define ICALL(id,name,func)
8156 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8157 #include "metadata/icall-def.h"
8159 } icall_type_names_str = {
8160 #define ICALL_TYPE(id,name,first) (name),
8161 #include "metadata/icall-def.h"
8164 static const guint16 icall_type_names_idx [] = {
8165 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8166 #include "metadata/icall-def.h"
8169 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8171 static const struct msgstr_t {
8173 #define ICALL_TYPE(id,name,first)
8174 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8175 #include "metadata/icall-def.h"
8177 } icall_names_str = {
8178 #define ICALL(id,name,func) (name),
8179 #include "metadata/icall-def.h"
8182 static const guint16 icall_names_idx [] = {
8183 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8184 #include "metadata/icall-def.h"
8187 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8193 #define ICALL_TYPE(id,name,first) name,
8194 #define ICALL(id,name,func)
8195 static const char* const
8196 icall_type_names [] = {
8197 #include "metadata/icall-def.h"
8201 #define icall_type_name_get(id) (icall_type_names [(id)])
8205 #define ICALL_TYPE(id,name,first)
8206 #define ICALL(id,name,func) name,
8207 static const char* const
8209 #include "metadata/icall-def.h"
8212 #define icall_name_get(id) icall_names [(id)]
8214 #endif /* !HAVE_ARRAY_ELEM_INIT */
8218 #define ICALL_TYPE(id,name,first)
8219 #define ICALL(id,name,func) func,
8220 static const gconstpointer
8221 icall_functions [] = {
8222 #include "metadata/icall-def.h"
8226 #ifdef ENABLE_ICALL_SYMBOL_MAP
8229 #define ICALL_TYPE(id,name,first)
8230 #define ICALL(id,name,func) #func,
8231 static const gconstpointer
8232 icall_symbols [] = {
8233 #include "metadata/icall-def.h"
8238 #endif /* DISABLE_ICALL_TABLES */
8240 static mono_mutex_t icall_mutex;
8241 static GHashTable *icall_hash = NULL;
8242 static GHashTable *jit_icall_hash_name = NULL;
8243 static GHashTable *jit_icall_hash_addr = NULL;
8246 mono_icall_init (void)
8248 #ifndef DISABLE_ICALL_TABLES
8251 /* check that tables are sorted: disable in release */
8254 const char *prev_class = NULL;
8255 const char *prev_method;
8257 for (i = 0; i < Icall_type_num; ++i) {
8258 const IcallTypeDesc *desc;
8261 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8262 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8263 prev_class = icall_type_name_get (i);
8264 desc = &icall_type_descs [i];
8265 num_icalls = icall_desc_num_icalls (desc);
8266 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8267 for (j = 0; j < num_icalls; ++j) {
8268 const char *methodn = icall_name_get (desc->first_icall + j);
8269 if (prev_method && strcmp (prev_method, methodn) >= 0)
8270 g_print ("method %s should come before method %s\n", methodn, prev_method);
8271 prev_method = methodn;
8277 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8278 mono_os_mutex_init (&icall_mutex);
8282 mono_icall_lock (void)
8284 mono_locks_os_acquire (&icall_mutex, IcallLock);
8288 mono_icall_unlock (void)
8290 mono_locks_os_release (&icall_mutex, IcallLock);
8294 mono_icall_cleanup (void)
8296 g_hash_table_destroy (icall_hash);
8297 g_hash_table_destroy (jit_icall_hash_name);
8298 g_hash_table_destroy (jit_icall_hash_addr);
8299 mono_os_mutex_destroy (&icall_mutex);
8303 * mono_add_internal_call:
8304 * @name: method specification to surface to the managed world
8305 * @method: pointer to a C method to invoke when the method is called
8307 * This method surfaces the C function pointed by @method as a method
8308 * that has been surfaced in managed code with the method specified in
8309 * @name as an internal call.
8311 * Internal calls are surfaced to all app domains loaded and they are
8312 * accessibly by a type with the specified name.
8314 * You must provide a fully qualified type name, that is namespaces
8315 * and type name, followed by a colon and the method name, with an
8316 * optional signature to bind.
8318 * For example, the following are all valid declarations:
8320 * "MyApp.Services.ScriptService:Accelerate"
8321 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8323 * You use method parameters in cases where there might be more than
8324 * one surface method to managed code. That way you can register different
8325 * internal calls for different method overloads.
8327 * The internal calls are invoked with no marshalling. This means that .NET
8328 * types like System.String are exposed as `MonoString *` parameters. This is
8329 * different than the way that strings are surfaced in P/Invoke.
8331 * For more information on how the parameters are marshalled, see the
8332 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8335 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8336 * reference for more information on the format of method descriptions.
8339 mono_add_internal_call (const char *name, gconstpointer method)
8343 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8345 mono_icall_unlock ();
8348 #ifndef DISABLE_ICALL_TABLES
8350 #ifdef HAVE_ARRAY_ELEM_INIT
8352 compare_method_imap (const void *key, const void *elem)
8354 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8355 return strcmp (key, method_name);
8359 find_method_icall (const IcallTypeDesc *imap, const char *name)
8361 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);
8364 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8368 compare_class_imap (const void *key, const void *elem)
8370 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8371 return strcmp (key, class_name);
8374 static const IcallTypeDesc*
8375 find_class_icalls (const char *name)
8377 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);
8380 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8383 #else /* HAVE_ARRAY_ELEM_INIT */
8386 compare_method_imap (const void *key, const void *elem)
8388 const char** method_name = (const char**)elem;
8389 return strcmp (key, *method_name);
8393 find_method_icall (const IcallTypeDesc *imap, const char *name)
8395 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8398 return (gpointer)icall_functions [(nameslot - icall_names)];
8402 compare_class_imap (const void *key, const void *elem)
8404 const char** class_name = (const char**)elem;
8405 return strcmp (key, *class_name);
8408 static const IcallTypeDesc*
8409 find_class_icalls (const char *name)
8411 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8414 return &icall_type_descs [nameslot - icall_type_names];
8417 #endif /* HAVE_ARRAY_ELEM_INIT */
8419 #endif /* DISABLE_ICALL_TABLES */
8422 * we should probably export this as an helper (handle nested types).
8423 * Returns the number of chars written in buf.
8426 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8428 int nspacelen, cnamelen;
8429 nspacelen = strlen (klass->name_space);
8430 cnamelen = strlen (klass->name);
8431 if (nspacelen + cnamelen + 2 > bufsize)
8434 memcpy (buf, klass->name_space, nspacelen);
8435 buf [nspacelen ++] = '.';
8437 memcpy (buf + nspacelen, klass->name, cnamelen);
8438 buf [nspacelen + cnamelen] = 0;
8439 return nspacelen + cnamelen;
8442 #ifdef DISABLE_ICALL_TABLES
8444 no_icall_table (void)
8446 g_assert_not_reached ();
8451 mono_lookup_internal_call (MonoMethod *method)
8456 int typelen = 0, mlen, siglen;
8458 #ifndef DISABLE_ICALL_TABLES
8459 const IcallTypeDesc *imap = NULL;
8462 g_assert (method != NULL);
8464 if (method->is_inflated)
8465 method = ((MonoMethodInflated *) method)->declaring;
8467 if (method->klass->nested_in) {
8468 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8472 mname [pos++] = '/';
8475 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8481 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8486 #ifndef DISABLE_ICALL_TABLES
8487 imap = find_class_icalls (mname);
8490 mname [typelen] = ':';
8491 mname [typelen + 1] = ':';
8493 mlen = strlen (method->name);
8494 memcpy (mname + typelen + 2, method->name, mlen);
8495 sigstart = mname + typelen + 2 + mlen;
8498 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8499 siglen = strlen (tmpsig);
8500 if (typelen + mlen + siglen + 6 > sizeof (mname))
8503 memcpy (sigstart + 1, tmpsig, siglen);
8504 sigstart [siglen + 1] = ')';
8505 sigstart [siglen + 2] = 0;
8510 res = g_hash_table_lookup (icall_hash, mname);
8512 mono_icall_unlock ();;
8515 /* try without signature */
8517 res = g_hash_table_lookup (icall_hash, mname);
8519 mono_icall_unlock ();
8523 #ifdef DISABLE_ICALL_TABLES
8524 mono_icall_unlock ();
8525 /* Fail only when the result is actually used */
8526 /* mono_marshal_get_native_wrapper () depends on this */
8527 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8528 return ves_icall_System_String_ctor_RedirectToCreateString;
8530 return no_icall_table;
8532 /* it wasn't found in the static call tables */
8534 mono_icall_unlock ();
8537 res = find_method_icall (imap, sigstart - mlen);
8539 mono_icall_unlock ();
8542 /* try _with_ signature */
8544 res = find_method_icall (imap, sigstart - mlen);
8546 mono_icall_unlock ();
8550 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8551 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8552 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8553 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8554 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");
8555 g_print ("If you see other errors or faults after this message they are probably related\n");
8556 g_print ("and you need to fix your mono install first.\n");
8558 mono_icall_unlock ();
8564 #ifdef ENABLE_ICALL_SYMBOL_MAP
8566 func_cmp (gconstpointer key, gconstpointer p)
8568 return (gsize)key - (gsize)*(gsize*)p;
8573 * mono_lookup_icall_symbol:
8575 * Given the icall METHOD, returns its C symbol.
8578 mono_lookup_icall_symbol (MonoMethod *m)
8580 #ifdef DISABLE_ICALL_TABLES
8581 g_assert_not_reached ();
8584 #ifdef ENABLE_ICALL_SYMBOL_MAP
8588 static gconstpointer *functions_sorted;
8589 static const char**symbols_sorted;
8590 static gboolean inited;
8595 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8596 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8597 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8598 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8599 /* Bubble sort the two arrays */
8603 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8604 if (functions_sorted [i] > functions_sorted [i + 1]) {
8607 tmp = functions_sorted [i];
8608 functions_sorted [i] = functions_sorted [i + 1];
8609 functions_sorted [i + 1] = tmp;
8610 tmp = symbols_sorted [i];
8611 symbols_sorted [i] = symbols_sorted [i + 1];
8612 symbols_sorted [i + 1] = tmp;
8619 func = mono_lookup_internal_call (m);
8622 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8626 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8628 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8629 g_assert_not_reached ();
8636 type_from_typename (char *type_name)
8638 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8640 if (!strcmp (type_name, "int"))
8641 klass = mono_defaults.int_class;
8642 else if (!strcmp (type_name, "ptr"))
8643 klass = mono_defaults.int_class;
8644 else if (!strcmp (type_name, "void"))
8645 klass = mono_defaults.void_class;
8646 else if (!strcmp (type_name, "int32"))
8647 klass = mono_defaults.int32_class;
8648 else if (!strcmp (type_name, "uint32"))
8649 klass = mono_defaults.uint32_class;
8650 else if (!strcmp (type_name, "int8"))
8651 klass = mono_defaults.sbyte_class;
8652 else if (!strcmp (type_name, "uint8"))
8653 klass = mono_defaults.byte_class;
8654 else if (!strcmp (type_name, "int16"))
8655 klass = mono_defaults.int16_class;
8656 else if (!strcmp (type_name, "uint16"))
8657 klass = mono_defaults.uint16_class;
8658 else if (!strcmp (type_name, "long"))
8659 klass = mono_defaults.int64_class;
8660 else if (!strcmp (type_name, "ulong"))
8661 klass = mono_defaults.uint64_class;
8662 else if (!strcmp (type_name, "float"))
8663 klass = mono_defaults.single_class;
8664 else if (!strcmp (type_name, "double"))
8665 klass = mono_defaults.double_class;
8666 else if (!strcmp (type_name, "object"))
8667 klass = mono_defaults.object_class;
8668 else if (!strcmp (type_name, "obj"))
8669 klass = mono_defaults.object_class;
8670 else if (!strcmp (type_name, "string"))
8671 klass = mono_defaults.string_class;
8672 else if (!strcmp (type_name, "bool"))
8673 klass = mono_defaults.boolean_class;
8674 else if (!strcmp (type_name, "boolean"))
8675 klass = mono_defaults.boolean_class;
8677 g_error ("%s", type_name);
8678 g_assert_not_reached ();
8680 return &klass->byval_arg;
8684 * LOCKING: Take the corlib image lock.
8686 MonoMethodSignature*
8687 mono_create_icall_signature (const char *sigstr)
8692 MonoMethodSignature *res, *res2;
8693 MonoImage *corlib = mono_defaults.corlib;
8695 mono_image_lock (corlib);
8696 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8697 mono_image_unlock (corlib);
8702 parts = g_strsplit (sigstr, " ", 256);
8711 res = mono_metadata_signature_alloc (corlib, len - 1);
8716 * Under windows, the default pinvoke calling convention is STDCALL but
8719 res->call_convention = MONO_CALL_C;
8722 res->ret = type_from_typename (parts [0]);
8723 for (i = 1; i < len; ++i) {
8724 res->params [i - 1] = type_from_typename (parts [i]);
8729 mono_image_lock (corlib);
8730 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8732 res = res2; /*Value is allocated in the image pool*/
8734 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8735 mono_image_unlock (corlib);
8741 mono_find_jit_icall_by_name (const char *name)
8743 MonoJitICallInfo *info;
8744 g_assert (jit_icall_hash_name);
8747 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8748 mono_icall_unlock ();
8753 mono_find_jit_icall_by_addr (gconstpointer addr)
8755 MonoJitICallInfo *info;
8756 g_assert (jit_icall_hash_addr);
8759 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8760 mono_icall_unlock ();
8766 * mono_get_jit_icall_info:
8768 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8769 * caller should access it while holding the icall lock.
8772 mono_get_jit_icall_info (void)
8774 return jit_icall_hash_name;
8778 * mono_lookup_jit_icall_symbol:
8780 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8783 mono_lookup_jit_icall_symbol (const char *name)
8785 MonoJitICallInfo *info;
8786 const char *res = NULL;
8789 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8791 res = info->c_symbol;
8792 mono_icall_unlock ();
8797 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8800 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8801 mono_icall_unlock ();
8805 * 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
8806 * icalls without wrappers in some cases.
8809 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8811 MonoJitICallInfo *info;
8818 if (!jit_icall_hash_name) {
8819 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8820 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8823 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8824 g_warning ("jit icall already defined \"%s\"\n", name);
8825 g_assert_not_reached ();
8828 info = g_new0 (MonoJitICallInfo, 1);
8833 info->c_symbol = c_symbol;
8834 info->no_raise = no_raise;
8837 info->wrapper = func;
8839 info->wrapper = NULL;
8842 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8843 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8845 mono_icall_unlock ();
8850 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8852 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);