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_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1284 MonoMethod **dest = (MonoMethod **)data;
1286 /* skip unmanaged frames */
1291 if (!strcmp (m->klass->name_space, "System.Reflection"))
1300 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1302 MonoMethod **dest = (MonoMethod **)data;
1304 /* skip unmanaged frames */
1308 if (m->wrapper_type != MONO_WRAPPER_NONE)
1311 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1325 static MonoReflectionType *
1326 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1328 MonoMethod *m, *dest;
1330 MonoType *type = NULL;
1331 MonoAssembly *assembly = NULL;
1332 gboolean type_resolve = FALSE;
1334 mono_error_init (error);
1337 * We must compute the calling assembly as type loading must happen under a metadata context.
1338 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1339 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1341 m = mono_method_get_last_managed ();
1344 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1349 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1350 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1351 * to crash. This only seems to happen in some strange remoting
1352 * scenarios and I was unable to figure out what's happening there.
1353 * Dec 10, 2005 - Martin.
1357 assembly = dest->klass->image->assembly;
1358 type_resolve = TRUE;
1360 g_warning (G_STRLOC);
1363 if (info->assembly.name)
1364 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1368 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1369 type = mono_reflection_get_type_checked (assembly->image, info, ignoreCase, &type_resolve, error);
1370 return_val_if_nok (error, NULL);
1373 if (!info->assembly.name && !type) {
1375 type = mono_reflection_get_type_checked (NULL, info, ignoreCase, &type_resolve, error);
1376 return_val_if_nok (error, NULL);
1378 if (assembly && !type && type_resolve) {
1379 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1380 type = mono_reflection_get_type_checked (assembly->image, info, ignoreCase, &type_resolve, error);
1381 return_val_if_nok (error, NULL);
1387 return mono_type_get_object_checked (mono_domain_get (), type, error);
1390 ICALL_EXPORT MonoReflectionType*
1391 ves_icall_System_Type_internal_from_name (MonoString *name,
1392 MonoBoolean throwOnError,
1393 MonoBoolean ignoreCase)
1396 char *str = mono_string_to_utf8 (name);
1397 MonoTypeNameParse info;
1398 MonoReflectionType *type;
1401 parsedOk = mono_reflection_parse_type (str, &info);
1403 /* mono_reflection_parse_type() mangles the string */
1405 mono_reflection_free_type_info (&info);
1408 mono_set_pending_exception (mono_get_exception_argument("typeName", "failed parse"));
1413 type = type_from_parsed_name (&info, ignoreCase, &error);
1415 mono_reflection_free_type_info (&info);
1418 if (!mono_error_ok (&error)) {
1420 mono_error_set_pending_exception (&error);
1422 mono_error_cleanup (&error);
1427 MonoException *e = NULL;
1430 e = mono_get_exception_type_load (name, NULL);
1433 mono_set_pending_exception (e);
1442 ICALL_EXPORT MonoReflectionType*
1443 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1446 MonoReflectionType *ret;
1447 MonoDomain *domain = mono_domain_get ();
1449 ret = mono_type_get_object_checked (domain, handle, &error);
1450 mono_error_raise_exception (&error);
1455 /* System.TypeCode */
1474 TYPECODE_STRING = 18
1477 ICALL_EXPORT guint32
1478 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1480 int t = type->type->type;
1482 if (type->type->byref)
1483 return TYPECODE_OBJECT;
1487 case MONO_TYPE_VOID:
1488 return TYPECODE_OBJECT;
1489 case MONO_TYPE_BOOLEAN:
1490 return TYPECODE_BOOLEAN;
1492 return TYPECODE_BYTE;
1494 return TYPECODE_SBYTE;
1496 return TYPECODE_UINT16;
1498 return TYPECODE_INT16;
1499 case MONO_TYPE_CHAR:
1500 return TYPECODE_CHAR;
1504 return TYPECODE_OBJECT;
1506 return TYPECODE_UINT32;
1508 return TYPECODE_INT32;
1510 return TYPECODE_UINT64;
1512 return TYPECODE_INT64;
1514 return TYPECODE_SINGLE;
1516 return TYPECODE_DOUBLE;
1517 case MONO_TYPE_VALUETYPE: {
1518 MonoClass *klass = type->type->data.klass;
1520 if (klass->enumtype) {
1521 t = mono_class_enum_basetype (klass)->type;
1523 } else if (mono_is_corlib_image (klass->image)) {
1524 if (strcmp (klass->name_space, "System") == 0) {
1525 if (strcmp (klass->name, "Decimal") == 0)
1526 return TYPECODE_DECIMAL;
1527 else if (strcmp (klass->name, "DateTime") == 0)
1528 return TYPECODE_DATETIME;
1531 return TYPECODE_OBJECT;
1533 case MONO_TYPE_STRING:
1534 return TYPECODE_STRING;
1535 case MONO_TYPE_SZARRAY:
1536 case MONO_TYPE_ARRAY:
1537 case MONO_TYPE_OBJECT:
1539 case MONO_TYPE_MVAR:
1540 case MONO_TYPE_TYPEDBYREF:
1541 return TYPECODE_OBJECT;
1542 case MONO_TYPE_CLASS:
1544 MonoClass *klass = type->type->data.klass;
1545 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1546 if (strcmp (klass->name, "DBNull") == 0)
1547 return TYPECODE_DBNULL;
1550 return TYPECODE_OBJECT;
1551 case MONO_TYPE_GENERICINST:
1552 return TYPECODE_OBJECT;
1554 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1560 mono_type_is_primitive (MonoType *type)
1562 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1563 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1567 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1569 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1570 return mono_class_enum_basetype (type->data.klass);
1571 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1572 return mono_class_enum_basetype (type->data.generic_class->container_class);
1576 ICALL_EXPORT guint32
1577 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1582 g_assert (type != NULL);
1584 klass = mono_class_from_mono_type (type->type);
1585 klassc = mono_class_from_mono_type (c->type);
1587 if (type->type->byref ^ c->type->byref)
1590 if (type->type->byref) {
1591 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1592 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1594 klass = mono_class_from_mono_type (t);
1595 klassc = mono_class_from_mono_type (ot);
1597 if (mono_type_is_primitive (t)) {
1598 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1599 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1600 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1601 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1602 return t->type == ot->type;
1604 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1607 if (klass->valuetype)
1608 return klass == klassc;
1609 return klass->valuetype == klassc->valuetype;
1612 return mono_class_is_assignable_from (klass, klassc);
1615 ICALL_EXPORT guint32
1616 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1619 MonoClass *klass = mono_class_from_mono_type (type->type);
1620 mono_class_init_checked (klass, &error);
1621 if (!is_ok (&error)) {
1622 mono_error_set_pending_exception (&error);
1625 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1626 mono_error_set_pending_exception (&error);
1630 ICALL_EXPORT guint32
1631 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1633 MonoClass *klass = mono_class_from_mono_type (type->type);
1634 return klass->flags;
1637 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1638 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1641 MonoClass *klass = field->field->parent;
1642 MonoMarshalType *info;
1646 if (klass->generic_container ||
1647 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1650 ftype = mono_field_get_type (field->field);
1651 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1654 info = mono_marshal_load_type_info (klass);
1656 for (i = 0; i < info->num_fields; ++i) {
1657 if (info->fields [i].field == field->field) {
1658 if (!info->fields [i].mspec)
1661 MonoReflectionMarshalAsAttribute* obj;
1662 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1663 if (!mono_error_ok (&error))
1664 mono_error_set_pending_exception (&error);
1673 ICALL_EXPORT MonoReflectionField*
1674 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1677 gboolean found = FALSE;
1684 klass = handle->parent;
1686 klass = mono_class_from_mono_type (type);
1688 /* Check that the field belongs to the class */
1689 for (k = klass; k; k = k->parent) {
1690 if (k == handle->parent) {
1697 /* The managed code will throw the exception */
1701 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1702 mono_error_raise_exception (&error);
1706 ICALL_EXPORT MonoArray*
1707 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1710 MonoType *type = mono_field_get_type_checked (field->field, &error);
1713 if (!mono_error_ok (&error)) {
1714 mono_error_set_pending_exception (&error);
1718 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1719 mono_error_raise_exception (&error);
1724 vell_icall_get_method_attributes (MonoMethod *method)
1726 return method->flags;
1730 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1733 MonoReflectionType *rt;
1734 MonoDomain *domain = mono_domain_get ();
1735 MonoMethodSignature* sig;
1737 sig = mono_method_signature_checked (method, &error);
1738 if (!mono_error_ok (&error)) {
1739 mono_error_set_pending_exception (&error);
1743 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1744 if (!mono_error_ok (&error)) {
1745 mono_error_set_pending_exception (&error);
1749 MONO_STRUCT_SETREF (info, parent, rt);
1751 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1752 if (!mono_error_ok (&error)) {
1753 mono_error_set_pending_exception (&error);
1757 MONO_STRUCT_SETREF (info, ret, rt);
1759 info->attrs = method->flags;
1760 info->implattrs = method->iflags;
1761 if (sig->call_convention == MONO_CALL_DEFAULT)
1762 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1764 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1769 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1772 ICALL_EXPORT MonoArray*
1773 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1776 MonoDomain *domain = mono_domain_get ();
1778 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1779 mono_error_set_pending_exception (&error);
1783 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1784 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1787 MonoDomain *domain = mono_domain_get ();
1788 MonoReflectionMarshalAsAttribute* res = NULL;
1789 MonoMarshalSpec **mspecs;
1792 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1793 mono_method_get_marshal_info (method, mspecs);
1796 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1797 if (!mono_error_ok (&error)) {
1798 mono_error_set_pending_exception (&error);
1803 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1805 mono_metadata_free_marshal_spec (mspecs [i]);
1812 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1814 MonoClass *parent = field->field->parent;
1815 if (!parent->size_inited)
1816 mono_class_init (parent);
1817 mono_class_setup_fields_locking (parent);
1819 return field->field->offset - sizeof (MonoObject);
1822 ICALL_EXPORT MonoReflectionType*
1823 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1826 MonoReflectionType *ret;
1829 parent = declaring? field->field->parent: field->klass;
1831 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1832 mono_error_raise_exception (&error);
1838 ICALL_EXPORT MonoObject *
1839 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1842 MonoClass *fklass = field->klass;
1843 MonoClassField *cf = field->field;
1844 MonoDomain *domain = mono_object_domain (field);
1846 if (fklass->image->assembly->ref_only) {
1847 mono_set_pending_exception (mono_get_exception_invalid_operation (
1848 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1852 if (mono_security_core_clr_enabled () &&
1853 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1854 mono_error_set_pending_exception (&error);
1858 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1859 mono_error_set_pending_exception (&error);
1864 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1867 MonoClassField *cf = field->field;
1871 if (field->klass->image->assembly->ref_only) {
1872 mono_set_pending_exception (mono_get_exception_invalid_operation (
1873 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1877 if (mono_security_core_clr_enabled () &&
1878 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1879 mono_error_set_pending_exception (&error);
1883 type = mono_field_get_type_checked (cf, &error);
1884 if (!mono_error_ok (&error)) {
1885 mono_error_set_pending_exception (&error);
1889 v = (gchar *) value;
1891 switch (type->type) {
1894 case MONO_TYPE_BOOLEAN:
1897 case MONO_TYPE_CHAR:
1906 case MONO_TYPE_VALUETYPE:
1909 v += sizeof (MonoObject);
1911 case MONO_TYPE_STRING:
1912 case MONO_TYPE_OBJECT:
1913 case MONO_TYPE_CLASS:
1914 case MONO_TYPE_ARRAY:
1915 case MONO_TYPE_SZARRAY:
1918 case MONO_TYPE_GENERICINST: {
1919 MonoGenericClass *gclass = type->data.generic_class;
1920 g_assert (!gclass->context.class_inst->is_open);
1922 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1923 MonoClass *nklass = mono_class_from_mono_type (type);
1924 MonoObject *nullable;
1927 * Convert the boxed vtype into a Nullable structure.
1928 * This is complicated by the fact that Nullables have
1929 * a variable structure.
1931 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1932 if (!mono_error_ok (&error)) {
1933 mono_error_set_pending_exception (&error);
1937 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1939 v = (gchar *)mono_object_unbox (nullable);
1942 if (gclass->container_class->valuetype && (v != NULL))
1943 v += sizeof (MonoObject);
1947 g_error ("type 0x%x not handled in "
1948 "ves_icall_FieldInfo_SetValueInternal", type->type);
1953 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1954 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
1955 if (!is_ok (&error)) {
1956 mono_error_set_pending_exception (&error);
1959 if (!vtable->initialized) {
1960 if (!mono_runtime_class_init_full (vtable, &error)) {
1961 mono_error_set_pending_exception (&error);
1965 mono_field_static_set_value (vtable, cf, v);
1967 mono_field_set_value (obj, cf, v);
1972 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1981 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1982 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1986 if (MONO_TYPE_IS_REFERENCE (f->type))
1987 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1989 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1992 ICALL_EXPORT MonoObject *
1993 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1995 MonoObject *o = NULL;
1996 MonoClassField *field = rfield->field;
1998 MonoDomain *domain = mono_object_domain (rfield);
2000 MonoTypeEnum def_type;
2001 const char *def_value;
2005 mono_class_init (field->parent);
2007 t = mono_field_get_type_checked (field, &error);
2008 if (!mono_error_ok (&error)) {
2009 mono_error_set_pending_exception (&error);
2013 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2014 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2018 if (image_is_dynamic (field->parent->image)) {
2019 MonoClass *klass = field->parent;
2020 int fidx = field - klass->fields;
2022 g_assert (fidx >= 0 && fidx < klass->field.count);
2023 g_assert (klass->ext);
2024 g_assert (klass->ext->field_def_values);
2025 def_type = klass->ext->field_def_values [fidx].def_type;
2026 def_value = klass->ext->field_def_values [fidx].data;
2027 if (def_type == MONO_TYPE_END) {
2028 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2032 def_value = mono_class_get_field_default_value (field, &def_type);
2033 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2035 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2040 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2044 case MONO_TYPE_BOOLEAN:
2047 case MONO_TYPE_CHAR:
2055 case MONO_TYPE_R8: {
2058 /* boxed value type */
2059 t = g_new0 (MonoType, 1);
2061 klass = mono_class_from_mono_type (t);
2063 o = mono_object_new_checked (domain, klass, &error);
2064 if (!mono_error_ok (&error)) {
2065 mono_error_set_pending_exception (&error);
2068 v = ((gchar *) o) + sizeof (MonoObject);
2069 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2072 case MONO_TYPE_STRING:
2073 case MONO_TYPE_CLASS:
2074 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2077 g_assert_not_reached ();
2083 ICALL_EXPORT MonoReflectionType*
2084 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2087 MonoReflectionType *ret;
2090 type = mono_field_get_type_checked (ref_field->field, &error);
2091 if (!mono_error_ok (&error)) {
2092 mono_error_set_pending_exception (&error);
2096 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2097 if (!mono_error_ok (&error)) {
2098 mono_error_set_pending_exception (&error);
2105 /* From MonoProperty.cs */
2107 PInfo_Attributes = 1,
2108 PInfo_GetMethod = 1 << 1,
2109 PInfo_SetMethod = 1 << 2,
2110 PInfo_ReflectedType = 1 << 3,
2111 PInfo_DeclaringType = 1 << 4,
2116 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2119 MonoReflectionType *rt;
2120 MonoReflectionMethod *rm;
2121 MonoDomain *domain = mono_object_domain (property);
2122 const MonoProperty *pproperty = property->property;
2124 if ((req_info & PInfo_ReflectedType) != 0) {
2125 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2126 mono_error_raise_exception (&error);
2128 MONO_STRUCT_SETREF (info, parent, rt);
2130 if ((req_info & PInfo_DeclaringType) != 0) {
2131 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2132 mono_error_raise_exception (&error);
2134 MONO_STRUCT_SETREF (info, declaring_type, rt);
2137 if ((req_info & PInfo_Name) != 0)
2138 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2140 if ((req_info & PInfo_Attributes) != 0)
2141 info->attrs = pproperty->attrs;
2143 if ((req_info & PInfo_GetMethod) != 0) {
2144 if (pproperty->get &&
2145 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2146 pproperty->get->klass == property->klass)) {
2147 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2148 mono_error_raise_exception (&error);
2153 MONO_STRUCT_SETREF (info, get, rm);
2155 if ((req_info & PInfo_SetMethod) != 0) {
2156 if (pproperty->set &&
2157 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2158 pproperty->set->klass == property->klass)) {
2159 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2160 mono_error_raise_exception (&error);
2165 MONO_STRUCT_SETREF (info, set, rm);
2168 * There may be other methods defined for properties, though, it seems they are not exposed
2169 * in the reflection API
2174 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2177 MonoReflectionType *rt;
2178 MonoReflectionMethod *rm;
2179 MonoDomain *domain = mono_object_domain (event);
2181 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2182 mono_error_raise_exception (&error);
2184 MONO_STRUCT_SETREF (info, reflected_type, rt);
2186 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2187 mono_error_raise_exception (&error);
2189 MONO_STRUCT_SETREF (info, declaring_type, rt);
2191 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2192 info->attrs = event->event->attrs;
2194 if (event->event->add) {
2195 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2196 mono_error_raise_exception (&error);
2201 MONO_STRUCT_SETREF (info, add_method, rm);
2203 if (event->event->remove) {
2204 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2205 mono_error_raise_exception (&error);
2210 MONO_STRUCT_SETREF (info, remove_method, rm);
2212 if (event->event->raise) {
2213 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2214 mono_error_raise_exception (&error);
2219 MONO_STRUCT_SETREF (info, raise_method, rm);
2221 #ifndef MONO_SMALL_CONFIG
2222 if (event->event->other) {
2224 while (event->event->other [n])
2226 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2228 for (i = 0; i < n; i++) {
2229 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2230 mono_error_raise_exception (&error);
2231 mono_array_setref (info->other_methods, i, rm);
2238 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2243 mono_class_setup_interfaces (klass, error);
2244 if (!mono_error_ok (error))
2247 for (i = 0; i < klass->interface_count; i++) {
2248 ic = klass->interfaces [i];
2249 g_hash_table_insert (ifaces, ic, ic);
2251 collect_interfaces (ic, ifaces, error);
2252 if (!mono_error_ok (error))
2258 MonoArray *iface_array;
2259 MonoGenericContext *context;
2263 } FillIfaceArrayData;
2266 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2268 MonoReflectionType *rt;
2269 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2270 MonoClass *ic = (MonoClass *)key;
2271 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2273 if (!mono_error_ok (data->error))
2276 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2277 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2278 if (!mono_error_ok (data->error))
2282 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2283 if (!mono_error_ok (data->error))
2286 mono_array_setref (data->iface_array, data->next_idx++, rt);
2289 mono_metadata_free_type (inflated);
2293 get_interfaces_hash (gconstpointer v1)
2295 MonoClass *k = (MonoClass*)v1;
2297 return k->type_token;
2300 ICALL_EXPORT MonoArray*
2301 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2304 MonoClass *klass = mono_class_from_mono_type (type->type);
2306 FillIfaceArrayData data = { 0 };
2309 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2311 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2312 data.context = mono_class_get_context (klass);
2313 klass = klass->generic_class->container_class;
2316 for (parent = klass; parent; parent = parent->parent) {
2317 mono_class_setup_interfaces (parent, &error);
2318 if (!mono_error_ok (&error))
2320 collect_interfaces (parent, iface_hash, &error);
2321 if (!mono_error_ok (&error))
2325 data.error = &error;
2326 data.domain = mono_object_domain (type);
2328 len = g_hash_table_size (iface_hash);
2330 g_hash_table_destroy (iface_hash);
2331 if (!data.domain->empty_types)
2332 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2333 return data.domain->empty_types;
2336 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2337 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2338 if (!mono_error_ok (&error))
2341 g_hash_table_destroy (iface_hash);
2342 return data.iface_array;
2345 g_hash_table_destroy (iface_hash);
2346 mono_error_set_pending_exception (&error);
2351 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2353 gboolean variance_used;
2354 MonoClass *klass = mono_class_from_mono_type (type->type);
2355 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2356 MonoReflectionMethod *member;
2359 int i = 0, len, ioffset;
2363 mono_class_init_checked (klass, &error);
2364 mono_error_raise_exception (&error);
2365 mono_class_init_checked (iclass, &error);
2366 mono_error_raise_exception (&error);
2368 mono_class_setup_vtable (klass);
2370 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2374 len = mono_class_num_methods (iclass);
2375 domain = mono_object_domain (type);
2376 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2377 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2379 while ((method = mono_class_get_methods (iclass, &iter))) {
2380 member = mono_method_get_object_checked (domain, method, iclass, &error);
2381 mono_error_raise_exception (&error);
2382 mono_array_setref (*methods, i, member);
2383 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2384 mono_error_raise_exception (&error);
2385 mono_array_setref (*targets, i, member);
2392 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2395 MonoClass *klass = mono_class_from_mono_type (type->type);
2397 mono_class_init_checked (klass, &error);
2398 mono_error_raise_exception (&error);
2400 if (image_is_dynamic (klass->image)) {
2401 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2402 *packing = tb->packing_size;
2403 *size = tb->class_size;
2405 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2409 ICALL_EXPORT MonoReflectionType*
2410 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2413 MonoReflectionType *ret;
2416 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2417 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2418 mono_error_raise_exception (&error);
2423 klass = mono_class_from_mono_type (type->type);
2424 mono_class_init_checked (klass, &error);
2425 mono_error_raise_exception (&error);
2427 // GetElementType should only return a type for:
2428 // Array Pointer PassedByRef
2429 if (type->type->byref)
2430 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2431 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2432 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2433 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2434 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2438 mono_error_raise_exception (&error);
2443 ICALL_EXPORT MonoReflectionType*
2444 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2447 MonoReflectionType *ret;
2449 if (type->type->byref)
2452 MonoClass *klass = mono_class_from_mono_type (type->type);
2456 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2457 mono_error_raise_exception (&error);
2462 ICALL_EXPORT MonoBoolean
2463 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2465 return type->type->type == MONO_TYPE_PTR;
2468 ICALL_EXPORT MonoBoolean
2469 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2471 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)));
2474 ICALL_EXPORT MonoBoolean
2475 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2477 return type->type->byref;
2480 ICALL_EXPORT MonoBoolean
2481 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2484 MonoClass *klass = mono_class_from_mono_type (type->type);
2485 mono_class_init_checked (klass, &error);
2486 mono_error_raise_exception (&error);
2488 return mono_class_is_com_object (klass);
2491 ICALL_EXPORT guint32
2492 ves_icall_reflection_get_token (MonoObject* obj)
2495 guint32 result = mono_reflection_get_token_checked (obj, &error);
2496 mono_error_set_pending_exception (&error);
2500 ICALL_EXPORT MonoReflectionModule*
2501 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2504 MonoReflectionModule *result = NULL;
2505 MonoClass *klass = mono_class_from_mono_type (type->type);
2506 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2507 if (!mono_error_ok (&error))
2508 mono_error_set_pending_exception (&error);
2512 ICALL_EXPORT MonoReflectionAssembly*
2513 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2516 MonoDomain *domain = mono_domain_get ();
2517 MonoClass *klass = mono_class_from_mono_type (type->type);
2518 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2520 mono_error_set_pending_exception (&error);
2524 ICALL_EXPORT MonoReflectionType*
2525 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2528 MonoReflectionType *ret;
2529 MonoDomain *domain = mono_domain_get ();
2532 if (type->type->byref)
2534 if (type->type->type == MONO_TYPE_VAR) {
2535 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2536 klass = param ? param->owner.klass : NULL;
2537 } else if (type->type->type == MONO_TYPE_MVAR) {
2538 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2539 klass = param ? param->owner.method->klass : NULL;
2541 klass = mono_class_from_mono_type (type->type)->nested_in;
2547 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2548 mono_error_raise_exception (&error);
2553 ICALL_EXPORT MonoString*
2554 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2556 MonoDomain *domain = mono_domain_get ();
2557 MonoClass *klass = mono_class_from_mono_type (type->type);
2559 if (type->type->byref) {
2560 char *n = g_strdup_printf ("%s&", klass->name);
2561 MonoString *res = mono_string_new (domain, n);
2567 return mono_string_new (domain, klass->name);
2571 ICALL_EXPORT MonoString*
2572 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2574 MonoDomain *domain = mono_domain_get ();
2575 MonoClass *klass = mono_class_from_mono_type (type->type);
2577 while (klass->nested_in)
2578 klass = klass->nested_in;
2580 if (klass->name_space [0] == '\0')
2583 return mono_string_new (domain, klass->name_space);
2587 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2591 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2592 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2596 klass = mono_class_from_mono_type (type->type);
2602 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2605 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2609 ICALL_EXPORT MonoArray*
2610 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2613 MonoReflectionType *rt;
2615 MonoClass *klass, *pklass;
2616 MonoDomain *domain = mono_object_domain (type);
2619 klass = mono_class_from_mono_type (type->type);
2621 if (klass->generic_container) {
2622 MonoGenericContainer *container = klass->generic_container;
2623 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2624 for (i = 0; i < container->type_argc; ++i) {
2625 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2627 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2628 mono_error_raise_exception (&error);
2630 mono_array_setref (res, i, rt);
2632 } else if (klass->generic_class) {
2633 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2634 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2635 for (i = 0; i < inst->type_argc; ++i) {
2636 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2637 mono_error_raise_exception (&error);
2639 mono_array_setref (res, i, rt);
2647 ICALL_EXPORT gboolean
2648 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2652 if (!IS_MONOTYPE (type))
2655 if (type->type->byref)
2658 klass = mono_class_from_mono_type (type->type);
2659 return klass->generic_container != NULL;
2662 ICALL_EXPORT MonoReflectionType*
2663 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2666 MonoReflectionType *ret;
2669 if (type->type->byref)
2672 klass = mono_class_from_mono_type (type->type);
2674 if (klass->generic_container) {
2675 return type; /* check this one */
2677 if (klass->generic_class) {
2678 MonoClass *generic_class = klass->generic_class->container_class;
2681 tb = mono_class_get_ref_info (generic_class);
2683 if (generic_class->wastypebuilder && tb)
2684 return (MonoReflectionType *)tb;
2686 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2687 mono_error_raise_exception (&error);
2695 ICALL_EXPORT MonoReflectionType*
2696 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2699 MonoReflectionType *ret;
2701 MonoType *geninst, **types;
2704 g_assert (IS_MONOTYPE (type));
2705 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2706 mono_error_raise_exception (&error);
2708 count = mono_array_length (type_array);
2709 types = g_new0 (MonoType *, count);
2711 for (i = 0; i < count; i++) {
2712 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2713 types [i] = t->type;
2716 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2719 mono_error_set_pending_exception (&error);
2723 klass = mono_class_from_mono_type (geninst);
2725 /*we might inflate to the GTD*/
2726 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2727 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2731 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2732 mono_error_raise_exception (&error);
2737 ICALL_EXPORT gboolean
2738 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2742 if (!IS_MONOTYPE (type))
2745 if (type->type->byref)
2748 klass = mono_class_from_mono_type (type->type);
2749 return klass->generic_class != NULL || klass->generic_container != NULL;
2753 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2755 if (!IS_MONOTYPE (type))
2758 if (is_generic_parameter (type->type))
2759 return mono_type_get_generic_param_num (type->type);
2763 ICALL_EXPORT GenericParameterAttributes
2764 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2766 g_assert (IS_MONOTYPE (type));
2767 g_assert (is_generic_parameter (type->type));
2768 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2771 ICALL_EXPORT MonoArray *
2772 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2775 MonoReflectionType *rt;
2776 MonoGenericParamInfo *param_info;
2782 g_assert (IS_MONOTYPE (type));
2784 domain = mono_object_domain (type);
2785 param_info = mono_generic_param_info (type->type->data.generic_param);
2786 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2789 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2790 for (i = 0; i < count; i++) {
2791 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2792 mono_error_raise_exception (&error);
2794 mono_array_setref (res, i, rt);
2801 ICALL_EXPORT MonoBoolean
2802 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2804 return is_generic_parameter (type->type);
2807 ICALL_EXPORT MonoBoolean
2808 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2810 return is_generic_parameter (tb->type.type);
2814 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2815 MonoReflectionType *t)
2817 enumtype->type = t->type;
2820 ICALL_EXPORT MonoReflectionMethod*
2821 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2822 MonoReflectionMethod* generic)
2829 MonoReflectionMethod *ret = NULL;
2831 domain = ((MonoObject *)type)->vtable->domain;
2833 klass = mono_class_from_mono_type (type->type);
2834 mono_class_init_checked (klass, &error);
2835 mono_error_raise_exception (&error);
2838 while ((method = mono_class_get_methods (klass, &iter))) {
2839 if (method->token == generic->method->token) {
2840 ret = mono_method_get_object_checked (domain, method, klass, &error);
2841 mono_error_raise_exception (&error);
2848 ICALL_EXPORT MonoReflectionMethod *
2849 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2852 MonoType *type = ref_type->type;
2854 MonoReflectionMethod *ret = NULL;
2856 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2857 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2860 if (type->type == MONO_TYPE_VAR)
2863 method = mono_type_get_generic_param_owner (type)->owner.method;
2866 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2867 if (!mono_error_ok (&error))
2868 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2872 ICALL_EXPORT MonoBoolean
2873 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2875 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2879 ICALL_EXPORT MonoBoolean
2880 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2882 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2887 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2889 MonoDomain *domain = mono_domain_get ();
2890 MonoImage *image = method->method->klass->image;
2891 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2892 MonoTableInfo *tables = image->tables;
2893 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2894 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2895 guint32 im_cols [MONO_IMPLMAP_SIZE];
2896 guint32 scope_token;
2897 const char *import = NULL;
2898 const char *scope = NULL;
2900 if (image_is_dynamic (image)) {
2901 MonoReflectionMethodAux *method_aux =
2902 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2904 import = method_aux->dllentry;
2905 scope = method_aux->dll;
2908 if (!import || !scope) {
2909 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2914 if (piinfo->implmap_idx) {
2915 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2917 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2918 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2919 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2920 scope = mono_metadata_string_heap (image, scope_token);
2924 *flags = piinfo->piflags;
2925 *entry_point = mono_string_new (domain, import);
2926 *dll_name = mono_string_new (domain, scope);
2929 ICALL_EXPORT MonoReflectionMethod *
2930 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2932 MonoMethodInflated *imethod;
2934 MonoReflectionMethod *ret = NULL;
2937 if (method->method->is_generic)
2940 if (!method->method->is_inflated)
2943 imethod = (MonoMethodInflated *) method->method;
2945 result = imethod->declaring;
2946 /* Not a generic method. */
2947 if (!result->is_generic)
2950 if (image_is_dynamic (method->method->klass->image)) {
2951 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2952 MonoReflectionMethod *res;
2955 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2956 * the dynamic case as well ?
2958 mono_image_lock ((MonoImage*)image);
2959 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2960 mono_image_unlock ((MonoImage*)image);
2966 if (imethod->context.class_inst) {
2967 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2968 /*Generic methods gets the context of the GTD.*/
2969 if (mono_class_get_context (klass)) {
2970 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2971 if (!mono_error_ok (&error))
2976 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2978 if (!mono_error_ok (&error))
2979 mono_error_set_pending_exception (&error);
2983 ICALL_EXPORT gboolean
2984 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2986 return mono_method_signature (method->method)->generic_param_count != 0;
2989 ICALL_EXPORT gboolean
2990 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2992 return method->method->is_generic;
2995 ICALL_EXPORT MonoArray*
2996 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2999 MonoReflectionType *rt;
3004 domain = mono_object_domain (method);
3006 if (method->method->is_inflated) {
3007 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3010 count = inst->type_argc;
3011 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3013 for (i = 0; i < count; i++) {
3014 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3015 mono_error_raise_exception (&error);
3017 mono_array_setref (res, i, rt);
3024 count = mono_method_signature (method->method)->generic_param_count;
3025 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3027 for (i = 0; i < count; i++) {
3028 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3029 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3030 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3032 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3033 mono_error_raise_exception (&error);
3035 mono_array_setref (res, i, rt);
3041 ICALL_EXPORT MonoObject *
3042 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3046 * Invoke from reflection is supposed to always be a virtual call (the API
3047 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3048 * greater flexibility.
3050 MonoMethod *m = method->method;
3051 MonoMethodSignature *sig = mono_method_signature (m);
3054 void *obj = this_arg;
3058 if (mono_security_core_clr_enabled () &&
3059 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3060 mono_error_set_pending_exception (&error);
3064 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3065 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3066 mono_error_cleanup (&error); /* FIXME does this make sense? */
3067 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3072 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3073 if (!is_ok (&error)) {
3074 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3077 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3078 char *target_name = mono_type_get_full_name (m->klass);
3079 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3080 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3082 g_free (target_name);
3086 m = mono_object_get_virtual_method (this_arg, m);
3087 /* must pass the pointer to the value for valuetype methods */
3088 if (m->klass->valuetype)
3089 obj = mono_object_unbox (this_arg);
3090 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3091 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3096 if (sig->ret->byref) {
3097 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"));
3101 pcount = params? mono_array_length (params): 0;
3102 if (pcount != sig->param_count) {
3103 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3107 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3108 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."));
3112 image = m->klass->image;
3113 if (image->assembly->ref_only) {
3114 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."));
3118 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3119 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3123 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3127 intptr_t *lower_bounds;
3128 pcount = mono_array_length (params);
3129 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3130 /* Note: the synthetized array .ctors have int32 as argument type */
3131 for (i = 0; i < pcount; ++i)
3132 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3134 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3135 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3136 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3137 if (!mono_error_ok (&error)) {
3138 mono_error_set_pending_exception (&error);
3142 for (i = 0; i < mono_array_length (arr); ++i) {
3143 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3144 if (!mono_error_ok (&error)) {
3145 mono_error_set_pending_exception (&error);
3148 mono_array_setref_fast (arr, i, subarray);
3150 return (MonoObject*)arr;
3153 if (m->klass->rank == pcount) {
3154 /* Only lengths provided. */
3155 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3156 if (!mono_error_ok (&error)) {
3157 mono_error_set_pending_exception (&error);
3161 return (MonoObject*)arr;
3163 g_assert (pcount == (m->klass->rank * 2));
3164 /* The arguments are lower-bound-length pairs */
3165 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3167 for (i = 0; i < pcount / 2; ++i) {
3168 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3169 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3172 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3173 if (!mono_error_ok (&error)) {
3174 mono_error_set_pending_exception (&error);
3178 return (MonoObject*)arr;
3181 return mono_runtime_invoke_array (m, obj, params, NULL);
3184 #ifndef DISABLE_REMOTING
3185 ICALL_EXPORT MonoObject *
3186 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3189 MonoDomain *domain = mono_object_domain (method);
3190 MonoMethod *m = method->method;
3191 MonoMethodSignature *sig = mono_method_signature (m);
3192 MonoArray *out_args;
3194 int i, j, outarg_count = 0;
3196 if (m->klass == mono_defaults.object_class) {
3197 if (!strcmp (m->name, "FieldGetter")) {
3198 MonoClass *k = this_arg->vtable->klass;
3202 /* If this is a proxy, then it must be a CBO */
3203 if (k == mono_defaults.transparent_proxy_class) {
3204 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3205 this_arg = tp->rp->unwrapped_server;
3206 g_assert (this_arg);
3207 k = this_arg->vtable->klass;
3210 name = mono_array_get (params, MonoString *, 1);
3211 str = mono_string_to_utf8 (name);
3214 MonoClassField* field = mono_class_get_field_from_name (k, str);
3216 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3217 if (field_klass->valuetype) {
3218 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3219 mono_error_set_pending_exception (&error);
3220 /* fallthru to cleanup */
3222 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3224 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3225 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3226 mono_array_setref (out_args, 0, result);
3234 g_assert_not_reached ();
3236 } else if (!strcmp (m->name, "FieldSetter")) {
3237 MonoClass *k = this_arg->vtable->klass;
3243 /* If this is a proxy, then it must be a CBO */
3244 if (k == mono_defaults.transparent_proxy_class) {
3245 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3246 this_arg = tp->rp->unwrapped_server;
3247 g_assert (this_arg);
3248 k = this_arg->vtable->klass;
3251 name = mono_array_get (params, MonoString *, 1);
3252 str = mono_string_to_utf8 (name);
3255 MonoClassField* field = mono_class_get_field_from_name (k, str);
3257 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3258 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3260 if (field_klass->valuetype) {
3261 size = mono_type_size (field->type, &align);
3262 g_assert (size == mono_class_value_size (field_klass, NULL));
3263 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3265 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3268 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3269 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3279 g_assert_not_reached ();
3284 for (i = 0; i < mono_array_length (params); i++) {
3285 if (sig->params [i]->byref)
3289 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3291 /* handle constructors only for objects already allocated */
3292 if (!strcmp (method->method->name, ".ctor"))
3293 g_assert (this_arg);
3295 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3296 g_assert (!method->method->klass->valuetype);
3297 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3299 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3300 if (sig->params [i]->byref) {
3302 arg = mono_array_get (params, gpointer, i);
3303 mono_array_setref (out_args, j, arg);
3308 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3315 read_enum_value (const char *mem, int type)
3318 case MONO_TYPE_BOOLEAN:
3320 return *(guint8*)mem;
3322 return *(gint8*)mem;
3323 case MONO_TYPE_CHAR:
3325 return read16 (mem);
3327 return (gint16) read16 (mem);
3329 return read32 (mem);
3331 return (gint32) read32 (mem);
3334 return read64 (mem);
3336 g_assert_not_reached ();
3342 write_enum_value (char *mem, int type, guint64 value)
3346 case MONO_TYPE_I1: {
3347 guint8 *p = (guint8*)mem;
3352 case MONO_TYPE_I2: {
3353 guint16 *p = (guint16 *)mem;
3358 case MONO_TYPE_I4: {
3359 guint32 *p = (guint32 *)mem;
3364 case MONO_TYPE_I8: {
3365 guint64 *p = (guint64 *)mem;
3370 g_assert_not_reached ();
3375 ICALL_EXPORT MonoObject *
3376 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3384 domain = mono_object_domain (enumType);
3385 enumc = mono_class_from_mono_type (enumType->type);
3387 mono_class_init_checked (enumc, &error);
3388 mono_error_raise_exception (&error);
3390 etype = mono_class_enum_basetype (enumc);
3392 res = mono_object_new_checked (domain, enumc, &error);
3393 mono_error_raise_exception (&error);
3394 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3399 ICALL_EXPORT MonoBoolean
3400 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3402 int size = mono_class_value_size (a->vtable->klass, NULL);
3403 guint64 a_val = 0, b_val = 0;
3405 memcpy (&a_val, mono_object_unbox (a), size);
3406 memcpy (&b_val, mono_object_unbox (b), size);
3408 return (a_val & b_val) == b_val;
3411 ICALL_EXPORT MonoObject *
3412 ves_icall_System_Enum_get_value (MonoObject *eobj)
3424 g_assert (eobj->vtable->klass->enumtype);
3426 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3427 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3428 mono_error_raise_exception (&error);
3429 dst = (char *)res + sizeof (MonoObject);
3430 src = (char *)eobj + sizeof (MonoObject);
3431 size = mono_class_value_size (enumc, NULL);
3433 memcpy (dst, src, size);
3438 ICALL_EXPORT MonoReflectionType *
3439 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3442 MonoReflectionType *ret;
3446 klass = mono_class_from_mono_type (type->type);
3447 mono_class_init_checked (klass, &error);
3448 mono_error_raise_exception (&error);
3450 etype = mono_class_enum_basetype (klass);
3452 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3456 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3457 mono_error_raise_exception (&error);
3463 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3465 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3466 gpointer odata = (char *)other + sizeof (MonoObject);
3467 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3468 g_assert (basetype);
3473 if (eobj->vtable->klass != other->vtable->klass)
3476 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3477 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3478 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3481 return me > other ? 1 : -1; \
3484 switch (basetype->type) {
3486 COMPARE_ENUM_VALUES (guint8);
3488 COMPARE_ENUM_VALUES (gint8);
3489 case MONO_TYPE_CHAR:
3491 COMPARE_ENUM_VALUES (guint16);
3493 COMPARE_ENUM_VALUES (gint16);
3495 COMPARE_ENUM_VALUES (guint32);
3497 COMPARE_ENUM_VALUES (gint32);
3499 COMPARE_ENUM_VALUES (guint64);
3501 COMPARE_ENUM_VALUES (gint64);
3505 #undef COMPARE_ENUM_VALUES
3506 /* indicates that the enum was of an unsupported unerlying type */
3511 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3513 gpointer data = (char *)eobj + sizeof (MonoObject);
3514 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3515 g_assert (basetype);
3517 switch (basetype->type) {
3518 case MONO_TYPE_I1: {
3519 gint8 value = *((gint8*)data);
3520 return ((int)value ^ (int)value << 8);
3523 return *((guint8*)data);
3524 case MONO_TYPE_CHAR:
3526 return *((guint16*)data);
3528 case MONO_TYPE_I2: {
3529 gint16 value = *((gint16*)data);
3530 return ((int)(guint16)value | (((int)value) << 16));
3533 return *((guint32*)data);
3535 return *((gint32*)data);
3537 case MONO_TYPE_I8: {
3538 gint64 value = *((gint64*)data);
3539 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3542 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3547 ICALL_EXPORT MonoBoolean
3548 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3551 MonoDomain *domain = mono_object_domain (type);
3552 MonoClass *enumc = mono_class_from_mono_type (type->type);
3553 guint j = 0, nvalues;
3555 MonoClassField *field;
3557 guint64 field_value, previous_value = 0;
3558 gboolean sorted = TRUE;
3560 mono_class_init_checked (enumc, &error);
3561 mono_error_raise_exception (&error);
3563 if (!enumc->enumtype) {
3564 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3568 base_type = mono_class_enum_basetype (enumc)->type;
3570 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3571 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3572 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3575 while ((field = mono_class_get_fields (enumc, &iter))) {
3577 MonoTypeEnum def_type;
3579 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3581 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3583 if (mono_field_is_deleted (field))
3585 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3587 p = mono_class_get_field_default_value (field, &def_type);
3588 /* len = */ mono_metadata_decode_blob_size (p, &p);
3590 field_value = read_enum_value (p, base_type);
3591 mono_array_set (*values, guint64, j, field_value);
3593 if (previous_value > field_value)
3596 previous_value = field_value;
3604 BFLAGS_IgnoreCase = 1,
3605 BFLAGS_DeclaredOnly = 2,
3606 BFLAGS_Instance = 4,
3608 BFLAGS_Public = 0x10,
3609 BFLAGS_NonPublic = 0x20,
3610 BFLAGS_FlattenHierarchy = 0x40,
3611 BFLAGS_InvokeMethod = 0x100,
3612 BFLAGS_CreateInstance = 0x200,
3613 BFLAGS_GetField = 0x400,
3614 BFLAGS_SetField = 0x800,
3615 BFLAGS_GetProperty = 0x1000,
3616 BFLAGS_SetProperty = 0x2000,
3617 BFLAGS_ExactBinding = 0x10000,
3618 BFLAGS_SuppressChangeType = 0x20000,
3619 BFLAGS_OptionalParamBinding = 0x40000
3622 ICALL_EXPORT MonoArray*
3623 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3627 MonoClass *startklass, *klass, *refklass;
3632 char *utf8_name = NULL;
3633 int (*compare_func) (const char *s1, const char *s2) = NULL;
3634 MonoClassField *field;
3635 MonoPtrArray tmp_array;
3637 domain = ((MonoObject *)type)->vtable->domain;
3638 if (type->type->byref)
3639 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3641 klass = startklass = mono_class_from_mono_type (type->type);
3642 refklass = mono_class_from_mono_type (reftype->type);
3644 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3647 if (mono_class_has_failure (klass)) {
3648 mono_ptr_array_destroy (tmp_array);
3649 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3654 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3655 guint32 flags = mono_field_get_flags (field);
3657 if (mono_field_is_deleted_with_flags (field, flags))
3659 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3660 if (bflags & BFLAGS_Public)
3662 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3663 if (bflags & BFLAGS_NonPublic) {
3670 if (flags & FIELD_ATTRIBUTE_STATIC) {
3671 if (bflags & BFLAGS_Static)
3672 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3675 if (bflags & BFLAGS_Instance)
3683 if (utf8_name == NULL) {
3684 utf8_name = mono_string_to_utf8 (name);
3685 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3688 if (compare_func (mono_field_get_name (field), utf8_name))
3692 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3693 if (!mono_error_ok (&error))
3695 mono_ptr_array_append (tmp_array, member);
3697 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3700 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3702 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3703 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3705 mono_ptr_array_destroy (tmp_array);
3707 if (utf8_name != NULL)
3712 mono_ptr_array_destroy (tmp_array);
3713 mono_error_raise_exception (&error);
3714 g_assert_not_reached ();
3718 method_nonpublic (MonoMethod* method, gboolean start_klass)
3720 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3721 case METHOD_ATTRIBUTE_ASSEM:
3722 return (start_klass || mono_defaults.generic_ilist_class);
3723 case METHOD_ATTRIBUTE_PRIVATE:
3725 case METHOD_ATTRIBUTE_PUBLIC:
3733 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3736 MonoClass *startklass;
3740 /*FIXME, use MonoBitSet*/
3741 guint32 method_slots_default [8];
3742 guint32 *method_slots = NULL;
3743 int (*compare_func) (const char *s1, const char *s2) = NULL;
3745 array = g_ptr_array_new ();
3750 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3752 /* An optimization for calls made from Delegate:CreateDelegate () */
3753 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3754 method = mono_get_delegate_invoke (klass);
3757 g_ptr_array_add (array, method);
3761 mono_class_setup_methods (klass);
3762 mono_class_setup_vtable (klass);
3763 if (mono_class_has_failure (klass))
3766 if (is_generic_parameter (&klass->byval_arg))
3767 nslots = mono_class_get_vtable_size (klass->parent);
3769 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3770 if (nslots >= sizeof (method_slots_default) * 8) {
3771 method_slots = g_new0 (guint32, nslots / 32 + 1);
3773 method_slots = method_slots_default;
3774 memset (method_slots, 0, sizeof (method_slots_default));
3777 mono_class_setup_methods (klass);
3778 mono_class_setup_vtable (klass);
3779 if (mono_class_has_failure (klass))
3783 while ((method = mono_class_get_methods (klass, &iter))) {
3785 if (method->slot != -1) {
3786 g_assert (method->slot < nslots);
3787 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3789 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3790 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3793 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3795 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3796 if (bflags & BFLAGS_Public)
3798 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3804 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3805 if (bflags & BFLAGS_Static)
3806 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3809 if (bflags & BFLAGS_Instance)
3817 if (compare_func (name, method->name))
3822 g_ptr_array_add (array, method);
3824 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3826 if (method_slots != method_slots_default)
3827 g_free (method_slots);
3832 if (method_slots != method_slots_default)
3833 g_free (method_slots);
3834 g_ptr_array_free (array, TRUE);
3836 if (mono_class_has_failure (klass)) {
3837 *ex = mono_class_get_exception_for_failure (klass);
3839 *ex = mono_get_exception_execution_engine ("Unknown error");
3844 ICALL_EXPORT MonoArray*
3845 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3847 static MonoClass *MethodInfo_array;
3851 MonoVTable *array_vtable;
3852 MonoException *ex = NULL;
3853 const char *mname = NULL;
3854 GPtrArray *method_array;
3855 MonoClass *klass, *refklass;
3858 mono_error_init (&error);
3860 if (!MethodInfo_array) {
3861 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3862 mono_memory_barrier ();
3863 MethodInfo_array = klass;
3866 klass = mono_class_from_mono_type (type->type);
3867 refklass = mono_class_from_mono_type (reftype->type);
3868 domain = ((MonoObject *)type)->vtable->domain;
3869 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3870 if (!is_ok (&error)) {
3871 mono_error_set_pending_exception (&error);
3874 if (type->type->byref) {
3875 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3876 mono_error_set_pending_exception (&error);
3882 mname = mono_string_to_utf8 (name);
3884 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3885 g_free ((char*)mname);
3887 mono_set_pending_exception (ex);
3891 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3892 if (!mono_error_ok (&error)) {
3893 mono_error_set_pending_exception (&error);
3897 for (i = 0; i < method_array->len; ++i) {
3898 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3899 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3900 if (!mono_error_ok (&error))
3902 mono_array_setref (res, i, rm);
3906 g_ptr_array_free (method_array, TRUE);
3907 if (!mono_error_ok (&error))
3908 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3912 ICALL_EXPORT MonoArray*
3913 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3916 MonoClass *startklass, *klass, *refklass;
3921 gpointer iter = NULL;
3922 MonoPtrArray tmp_array;
3925 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3927 domain = ((MonoObject *)type)->vtable->domain;
3928 if (type->type->byref)
3929 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3930 klass = startklass = mono_class_from_mono_type (type->type);
3931 refklass = mono_class_from_mono_type (reftype->type);
3933 mono_class_setup_methods (klass);
3934 if (mono_class_has_failure (klass)) {
3935 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3940 while ((method = mono_class_get_methods (klass, &iter))) {
3942 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3944 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3945 if (bflags & BFLAGS_Public)
3948 if (bflags & BFLAGS_NonPublic)
3954 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3955 if (bflags & BFLAGS_Static)
3956 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3959 if (bflags & BFLAGS_Instance)
3965 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3966 if (!mono_error_ok (&error)) {
3967 mono_error_set_pending_exception (&error);
3971 mono_ptr_array_append (tmp_array, member);
3974 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
3976 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3977 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3979 mono_ptr_array_destroy (tmp_array);
3985 property_hash (gconstpointer data)
3987 MonoProperty *prop = (MonoProperty*)data;
3989 return g_str_hash (prop->name);
3993 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3995 if (method1->is_inflated)
3996 method1 = ((MonoMethodInflated*) method1)->declaring;
3997 if (method2->is_inflated)
3998 method2 = ((MonoMethodInflated*) method2)->declaring;
4000 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4004 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4006 // Properties are hide-by-name-and-signature
4007 if (!g_str_equal (prop1->name, prop2->name))
4010 /* If we see a property in a generic method, we want to
4011 compare the generic signatures, not the inflated signatures
4012 because we might conflate two properties that were
4016 public T this[T t] { getter { return t; } } // method 1
4017 public U this[U u] { getter { return u; } } // method 2
4020 If we see int Foo<int,int>::Item[int] we need to know if
4021 the indexer came from method 1 or from method 2, and we
4022 shouldn't conflate them. (Bugzilla 36283)
4024 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
4027 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4034 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4039 return method_nonpublic (accessor, start_klass);
4042 ICALL_EXPORT MonoArray*
4043 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4047 MonoClass *startklass, *klass;
4053 gchar *propname = NULL;
4054 int (*compare_func) (const char *s1, const char *s2) = NULL;
4056 GHashTable *properties = NULL;
4057 MonoPtrArray tmp_array;
4059 mono_error_init (&error);
4061 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4063 domain = ((MonoObject *)type)->vtable->domain;
4064 if (type->type->byref)
4065 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
4066 klass = startklass = mono_class_from_mono_type (type->type);
4069 propname = mono_string_to_utf8 (name);
4070 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4073 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4075 mono_class_setup_methods (klass);
4076 mono_class_setup_vtable (klass);
4077 if (mono_class_has_failure (klass))
4081 while ((prop = mono_class_get_properties (klass, &iter))) {
4087 flags = method->flags;
4090 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4091 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4092 if (bflags & BFLAGS_Public)
4094 } else if (bflags & BFLAGS_NonPublic) {
4095 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4096 property_accessor_nonpublic(prop->set, startklass == klass)) {
4103 if (flags & METHOD_ATTRIBUTE_STATIC) {
4104 if (bflags & BFLAGS_Static)
4105 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4108 if (bflags & BFLAGS_Instance)
4117 if (compare_func (propname, prop->name))
4121 if (g_hash_table_lookup (properties, prop))
4124 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4127 mono_ptr_array_append (tmp_array, pr);
4129 g_hash_table_insert (properties, prop, prop);
4131 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4134 g_hash_table_destroy (properties);
4137 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4138 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4139 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4141 mono_ptr_array_destroy (tmp_array);
4148 if (mono_class_has_failure (klass)) {
4149 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4154 g_hash_table_destroy (properties);
4157 mono_ptr_array_destroy (tmp_array);
4159 mono_error_set_pending_exception (&error);
4165 event_hash (gconstpointer data)
4167 MonoEvent *event = (MonoEvent*)data;
4169 return g_str_hash (event->name);
4173 event_equal (MonoEvent *event1, MonoEvent *event2)
4175 // Events are hide-by-name
4176 return g_str_equal (event1->name, event2->name);
4179 ICALL_EXPORT MonoArray*
4180 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4184 MonoClass *startklass, *klass;
4190 char *utf8_name = NULL;
4191 int (*compare_func) (const char *s1, const char *s2) = NULL;
4192 GHashTable *events = NULL;
4193 MonoPtrArray tmp_array;
4195 mono_error_init (&error);
4197 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4199 domain = mono_object_domain (type);
4200 if (type->type->byref)
4201 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4202 klass = startklass = mono_class_from_mono_type (type->type);
4204 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4206 mono_class_setup_methods (klass);
4207 mono_class_setup_vtable (klass);
4208 if (mono_class_has_failure (klass))
4212 while ((event = mono_class_get_events (klass, &iter))) {
4214 method = event->add;
4216 method = event->remove;
4218 method = event->raise;
4220 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4221 if (bflags & BFLAGS_Public)
4223 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4224 if (bflags & BFLAGS_NonPublic)
4229 if (bflags & BFLAGS_NonPublic)
4235 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4236 if (bflags & BFLAGS_Static)
4237 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4240 if (bflags & BFLAGS_Instance)
4245 if (bflags & BFLAGS_Instance)
4251 if (utf8_name == NULL) {
4252 utf8_name = mono_string_to_utf8 (name);
4253 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4256 if (compare_func (event->name, utf8_name))
4260 if (g_hash_table_lookup (events, event))
4263 MonoReflectionEvent *ev_obj;
4264 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4267 mono_ptr_array_append (tmp_array, ev_obj);
4269 g_hash_table_insert (events, event, event);
4271 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4274 g_hash_table_destroy (events);
4276 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4278 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4279 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4281 mono_ptr_array_destroy (tmp_array);
4283 if (utf8_name != NULL)
4289 if (mono_class_has_failure (klass)) {
4290 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4296 g_hash_table_destroy (events);
4297 if (utf8_name != NULL)
4300 mono_ptr_array_destroy (tmp_array);
4302 mono_error_set_pending_exception (&error);
4306 ICALL_EXPORT MonoArray*
4307 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4310 MonoReflectionType *rt;
4318 MonoPtrArray tmp_array;
4320 domain = ((MonoObject *)type)->vtable->domain;
4321 if (type->type->byref)
4322 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4323 klass = mono_class_from_mono_type (type->type);
4326 * If a nested type is generic, return its generic type definition.
4327 * Note that this means that the return value is essentially the set
4328 * of nested types of the generic type definition of @klass.
4330 * A note in MSDN claims that a generic type definition can have
4331 * nested types that aren't generic. In any case, the container of that
4332 * nested type would be the generic type definition.
4334 if (klass->generic_class)
4335 klass = klass->generic_class->container_class;
4337 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4339 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4341 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4342 if (bflags & BFLAGS_Public)
4345 if (bflags & BFLAGS_NonPublic)
4353 str = mono_string_to_utf8 (name);
4354 mono_identifier_unescape_type_name_chars (str);
4357 if (strcmp (nested->name, str))
4361 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4362 mono_error_raise_exception (&error);
4364 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4367 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4369 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4370 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4372 mono_ptr_array_destroy (tmp_array);
4379 ICALL_EXPORT MonoReflectionType*
4380 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4383 MonoReflectionType *ret;
4385 MonoType *type = NULL;
4386 MonoTypeNameParse info;
4387 gboolean type_resolve;
4389 /* On MS.NET, this does not fire a TypeResolve event */
4390 type_resolve = TRUE;
4391 str = mono_string_to_utf8 (name);
4392 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4393 if (!mono_reflection_parse_type (str, &info)) {
4395 mono_reflection_free_type_info (&info);
4397 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4400 /*g_print ("failed parse\n");*/
4404 if (info.assembly.name) {
4406 mono_reflection_free_type_info (&info);
4408 /* 1.0 and 2.0 throw different exceptions */
4409 if (mono_defaults.generic_ilist_class)
4410 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4412 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4418 if (module != NULL) {
4419 if (module->image) {
4420 type = mono_reflection_get_type_checked (module->image, &info, ignoreCase, &type_resolve, &error);
4421 if (!is_ok (&error)) {
4423 mono_reflection_free_type_info (&info);
4424 mono_error_set_pending_exception (&error);
4431 if (assembly_is_dynamic (assembly->assembly)) {
4432 /* Enumerate all modules */
4433 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4437 if (abuilder->modules) {
4438 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4439 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4440 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4441 if (!is_ok (&error)) {
4443 mono_reflection_free_type_info (&info);
4444 mono_error_set_pending_exception (&error);
4452 if (!type && abuilder->loaded_modules) {
4453 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4454 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4455 type = mono_reflection_get_type_checked (mod->image, &info, ignoreCase, &type_resolve, &error);
4456 if (!is_ok (&error)) {
4458 mono_reflection_free_type_info (&info);
4459 mono_error_set_pending_exception (&error);
4468 type = mono_reflection_get_type_checked (assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4469 if (!is_ok (&error)) {
4471 mono_reflection_free_type_info (&info);
4472 mono_error_set_pending_exception (&error);
4477 mono_reflection_free_type_info (&info);
4479 MonoException *e = NULL;
4482 e = mono_get_exception_type_load (name, NULL);
4485 mono_set_pending_exception (e);
4489 if (type->type == MONO_TYPE_CLASS) {
4490 MonoClass *klass = mono_type_get_class (type);
4492 /* need to report exceptions ? */
4493 if (throwOnError && mono_class_has_failure (klass)) {
4494 /* report SecurityException (or others) that occured when loading the assembly */
4495 MonoException *exc = mono_class_get_exception_for_failure (klass);
4496 mono_set_pending_exception (exc);
4501 /* g_print ("got it\n"); */
4502 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4503 mono_error_set_pending_exception (&error);
4509 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4512 gchar *shadow_ini_file;
4515 /* Check for shadow-copied assembly */
4516 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4517 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4519 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4520 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4526 g_free (shadow_ini_file);
4527 if (content != NULL) {
4530 *filename = content;
4537 ICALL_EXPORT MonoString *
4538 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4540 MonoDomain *domain = mono_object_domain (assembly);
4541 MonoAssembly *mass = assembly->assembly;
4542 MonoString *res = NULL;
4547 if (g_path_is_absolute (mass->image->name)) {
4548 absolute = g_strdup (mass->image->name);
4549 dirname = g_path_get_dirname (absolute);
4551 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4552 dirname = g_strdup (mass->basedir);
4555 replace_shadow_path (domain, dirname, &absolute);
4560 for (i = strlen (absolute) - 1; i >= 0; i--)
4561 if (absolute [i] == '\\')
4566 uri = g_filename_to_uri (absolute, NULL, NULL);
4568 const char *prepend = "file://";
4570 if (*absolute == '/' && *(absolute + 1) == '/') {
4573 prepend = "file:///";
4576 uri = g_strconcat (prepend, absolute, NULL);
4580 res = mono_string_new (domain, uri);
4587 ICALL_EXPORT MonoBoolean
4588 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4590 MonoAssembly *mass = assembly->assembly;
4592 return mass->in_gac;
4595 ICALL_EXPORT MonoReflectionAssembly*
4596 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4601 MonoImageOpenStatus status;
4602 MonoReflectionAssembly* result = NULL;
4604 name = mono_string_to_utf8 (mname);
4605 res = mono_assembly_load_with_partial_name (name, &status);
4611 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4613 mono_error_set_pending_exception (&error);
4617 ICALL_EXPORT MonoString *
4618 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4620 MonoDomain *domain = mono_object_domain (assembly);
4623 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4628 ICALL_EXPORT MonoBoolean
4629 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4631 return assembly->assembly->ref_only;
4634 ICALL_EXPORT MonoString *
4635 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4637 MonoDomain *domain = mono_object_domain (assembly);
4639 return mono_string_new (domain, assembly->assembly->image->version);
4642 ICALL_EXPORT MonoReflectionMethod*
4643 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4646 MonoReflectionMethod *res = NULL;
4649 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4653 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4654 if (!mono_error_ok (&error))
4657 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4660 if (!mono_error_ok (&error))
4661 mono_error_set_pending_exception (&error);
4665 ICALL_EXPORT MonoReflectionModule*
4666 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4669 MonoReflectionModule *result = NULL;
4670 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4671 if (!mono_error_ok (&error))
4672 mono_error_set_pending_exception (&error);
4676 ICALL_EXPORT MonoArray*
4677 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4679 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4680 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4684 for (i = 0; i < table->rows; ++i) {
4685 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4686 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4692 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4694 static MonoMethod *create_version = NULL;
4698 mono_error_init (error);
4701 if (!create_version) {
4702 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4703 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4704 g_assert (create_version);
4705 mono_method_desc_free (desc);
4711 args [3] = &revision;
4712 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4713 return_val_if_nok (error, NULL);
4715 mono_runtime_invoke_checked (create_version, result, args, error);
4716 return_val_if_nok (error, NULL);
4721 ICALL_EXPORT MonoArray*
4722 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4726 MonoDomain *domain = mono_object_domain (assembly);
4728 static MonoMethod *create_culture = NULL;
4729 MonoImage *image = assembly->assembly->image;
4733 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4736 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4738 if (count > 0 && !create_culture) {
4739 MonoMethodDesc *desc = mono_method_desc_new (
4740 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4741 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4742 g_assert (create_culture);
4743 mono_method_desc_free (desc);
4746 for (i = 0; i < count; i++) {
4747 MonoObject *version;
4748 MonoReflectionAssemblyName *aname;
4749 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4751 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4753 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4754 domain, mono_class_get_assembly_name_class (), &error);
4755 mono_error_raise_exception (&error);
4757 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4759 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4760 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4761 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4762 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4763 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4764 aname->versioncompat = 1; /* SameMachine (default) */
4765 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4767 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4768 mono_error_raise_exception (&error);
4770 MONO_OBJECT_SETREF (aname, version, version);
4772 if (create_culture) {
4774 MonoBoolean assembly_ref = 1;
4775 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4776 args [1] = &assembly_ref;
4778 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4779 mono_error_raise_exception (&error);
4781 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4784 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4785 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4786 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4788 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4789 /* public key token isn't copied - the class library will
4790 automatically generate it from the public key if required */
4791 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4792 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4794 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4795 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4798 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4801 /* note: this function doesn't return the codebase on purpose (i.e. it can
4802 be used under partial trust as path information isn't present). */
4804 mono_array_setref (result, i, aname);
4809 /* move this in some file in mono/util/ */
4811 g_concat_dir_and_file (const char *dir, const char *file)
4813 g_return_val_if_fail (dir != NULL, NULL);
4814 g_return_val_if_fail (file != NULL, NULL);
4817 * If the directory name doesn't have a / on the end, we need
4818 * to add one so we get a proper path to the file
4820 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4821 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4823 return g_strconcat (dir, file, NULL);
4827 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4830 char *n = mono_string_to_utf8 (name);
4831 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4833 guint32 cols [MONO_MANIFEST_SIZE];
4834 guint32 impl, file_idx;
4838 for (i = 0; i < table->rows; ++i) {
4839 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4840 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4841 if (strcmp (val, n) == 0)
4845 if (i == table->rows)
4848 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4851 * this code should only be called after obtaining the
4852 * ResourceInfo and handling the other cases.
4854 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4855 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4857 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4862 module = assembly->assembly->image;
4865 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4866 mono_error_raise_exception (&error);
4867 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4869 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4872 ICALL_EXPORT gboolean
4873 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4876 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4878 guint32 cols [MONO_MANIFEST_SIZE];
4879 guint32 file_cols [MONO_FILE_SIZE];
4883 n = mono_string_to_utf8 (name);
4884 for (i = 0; i < table->rows; ++i) {
4885 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4886 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4887 if (strcmp (val, n) == 0)
4891 if (i == table->rows)
4894 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4895 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4898 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4899 case MONO_IMPLEMENTATION_FILE:
4900 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4901 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4902 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4903 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4904 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4905 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4908 info->location = RESOURCE_LOCATION_EMBEDDED;
4911 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4912 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4913 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4914 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4915 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4916 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4918 mono_set_pending_exception (ex);
4921 MonoReflectionAssembly *assm_obj;
4922 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4924 mono_error_set_pending_exception (&error);
4927 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4929 /* Obtain info recursively */
4930 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4931 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4934 case MONO_IMPLEMENTATION_EXP_TYPE:
4935 g_assert_not_reached ();
4943 ICALL_EXPORT MonoObject*
4944 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4946 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4947 MonoArray *result = NULL;
4952 /* check hash if needed */
4954 n = mono_string_to_utf8 (name);
4955 for (i = 0; i < table->rows; ++i) {
4956 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4957 if (strcmp (val, n) == 0) {
4960 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4961 fn = mono_string_new (mono_object_domain (assembly), n);
4963 return (MonoObject*)fn;
4971 for (i = 0; i < table->rows; ++i) {
4972 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4976 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4979 for (i = 0; i < table->rows; ++i) {
4980 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4981 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4982 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4983 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4988 return (MonoObject*)result;
4991 ICALL_EXPORT MonoArray*
4992 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4995 MonoDomain *domain = mono_domain_get();
4998 int i, j, file_count = 0;
4999 MonoImage **modules;
5000 guint32 module_count, real_module_count;
5001 MonoTableInfo *table;
5002 guint32 cols [MONO_FILE_SIZE];
5003 MonoImage *image = assembly->assembly->image;
5005 g_assert (image != NULL);
5006 g_assert (!assembly_is_dynamic (assembly->assembly));
5008 table = &image->tables [MONO_TABLE_FILE];
5009 file_count = table->rows;
5011 modules = image->modules;
5012 module_count = image->module_count;
5014 real_module_count = 0;
5015 for (i = 0; i < module_count; ++i)
5017 real_module_count ++;
5019 klass = mono_class_get_module_class ();
5020 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
5022 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5023 mono_error_raise_exception (&error);
5024 mono_array_setref (res, 0, image_obj);
5026 for (i = 0; i < module_count; ++i)
5028 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5029 mono_error_raise_exception (&error);
5030 mono_array_setref (res, j, rm);
5034 for (i = 0; i < file_count; ++i, ++j) {
5035 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5036 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5037 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5038 mono_error_raise_exception (&error);
5039 mono_array_setref (res, j, rm);
5042 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5044 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5045 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5048 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5049 mono_error_raise_exception (&error);
5050 mono_array_setref (res, j, rm);
5057 ICALL_EXPORT MonoReflectionMethod*
5058 ves_icall_GetCurrentMethod (void)
5060 MonoReflectionMethod *res = NULL;
5063 MonoMethod *m = mono_method_get_last_managed ();
5066 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5070 while (m->is_inflated)
5071 m = ((MonoMethodInflated*)m)->declaring;
5073 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5074 mono_error_raise_exception (&error);
5080 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5083 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5086 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5087 //method is inflated, we should inflate it on the other class
5088 MonoGenericContext ctx;
5089 ctx.method_inst = inflated->context.method_inst;
5090 ctx.class_inst = inflated->context.class_inst;
5091 if (klass->generic_class)
5092 ctx.class_inst = klass->generic_class->context.class_inst;
5093 else if (klass->generic_container)
5094 ctx.class_inst = klass->generic_container->context.class_inst;
5095 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5096 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5100 mono_class_setup_methods (method->klass);
5101 if (mono_class_has_failure (method->klass))
5103 for (i = 0; i < method->klass->method.count; ++i) {
5104 if (method->klass->methods [i] == method) {
5109 mono_class_setup_methods (klass);
5110 if (mono_class_has_failure (klass))
5112 g_assert (offset >= 0 && offset < klass->method.count);
5113 return klass->methods [offset];
5116 ICALL_EXPORT MonoReflectionMethod*
5117 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5119 MonoReflectionMethod *res = NULL;
5123 klass = mono_class_from_mono_type (type);
5124 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5126 if (method->klass != klass) {
5127 method = mono_method_get_equivalent_method (method, klass);
5132 klass = method->klass;
5133 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5134 mono_error_raise_exception (&error);
5138 ICALL_EXPORT MonoReflectionMethodBody*
5139 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5142 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5143 mono_error_set_pending_exception (&error);
5147 ICALL_EXPORT MonoReflectionAssembly*
5148 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5151 MonoReflectionAssembly *result;
5152 MonoMethod *dest = NULL;
5154 mono_stack_walk_no_il (get_executing, &dest);
5156 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5158 mono_error_set_pending_exception (&error);
5163 ICALL_EXPORT MonoReflectionAssembly*
5164 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5167 MonoReflectionAssembly *result;
5168 MonoDomain* domain = mono_domain_get ();
5170 if (!domain->entry_assembly)
5173 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5175 mono_error_set_pending_exception (&error);
5179 ICALL_EXPORT MonoReflectionAssembly*
5180 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5185 MonoReflectionAssembly *result;
5188 mono_stack_walk_no_il (get_executing, &dest);
5190 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5194 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5197 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5199 mono_error_set_pending_exception (&error);
5203 ICALL_EXPORT MonoString *
5204 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5205 gboolean assembly_qualified)
5207 MonoDomain *domain = mono_object_domain (object);
5208 MonoTypeNameFormat format;
5213 format = assembly_qualified ?
5214 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5215 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5217 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5219 name = mono_type_get_name_full (object->type, format);
5223 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5228 res = mono_string_new (domain, name);
5235 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5238 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5240 mono_class_init_checked (klass, &error);
5241 mono_error_raise_exception (&error);
5242 return mono_security_core_clr_class_level (klass);
5246 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5248 MonoClassField *field = rfield->field;
5249 return mono_security_core_clr_field_level (field, TRUE);
5253 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5255 MonoMethod *method = rfield->method;
5256 return mono_security_core_clr_method_level (method, TRUE);
5260 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)
5262 static MonoMethod *create_culture = NULL;
5266 const char *pkey_ptr;
5268 MonoBoolean assembly_ref = 0;
5270 mono_error_init (error);
5272 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5273 aname->major = name->major;
5274 aname->minor = name->minor;
5275 aname->build = name->build;
5276 aname->flags = name->flags;
5277 aname->revision = name->revision;
5278 aname->hashalg = name->hash_alg;
5279 aname->versioncompat = 1; /* SameMachine (default) */
5280 aname->processor_architecture = name->arch;
5282 if (by_default_version) {
5283 MonoObject *version;
5285 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5286 return_if_nok (error);
5288 MONO_OBJECT_SETREF (aname, version, version);
5292 if (absolute != NULL && *absolute != '\0') {
5293 const gchar *prepend = "file://";
5296 codebase = g_strdup (absolute);
5301 for (i = strlen (codebase) - 1; i >= 0; i--)
5302 if (codebase [i] == '\\')
5305 if (*codebase == '/' && *(codebase + 1) == '/') {
5308 prepend = "file:///";
5312 result = g_strconcat (prepend, codebase, NULL);
5318 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5322 if (!create_culture) {
5323 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5324 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5325 g_assert (create_culture);
5326 mono_method_desc_free (desc);
5329 if (name->culture) {
5330 args [0] = mono_string_new (domain, name->culture);
5331 args [1] = &assembly_ref;
5333 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5334 return_if_nok (error);
5336 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5339 if (name->public_key) {
5340 pkey_ptr = (char*)name->public_key;
5341 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5343 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5344 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5345 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5346 } else if (default_publickey) {
5347 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5348 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5351 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5352 if (name->public_key_token [0]) {
5356 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5357 p = mono_array_addr (aname->keyToken, char, 0);
5359 for (i = 0, j = 0; i < 8; i++) {
5360 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5361 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5364 } else if (default_token) {
5365 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5369 ICALL_EXPORT MonoString *
5370 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5372 MonoDomain *domain = mono_object_domain (assembly);
5373 MonoAssembly *mass = assembly->assembly;
5377 name = mono_stringify_assembly_name (&mass->aname);
5378 res = mono_string_new (domain, name);
5385 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5389 MonoAssembly *mass = assembly->assembly;
5391 if (g_path_is_absolute (mass->image->name)) {
5392 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5393 mono_error_set_pending_exception (&error);
5396 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5398 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5399 mono_error_set_pending_exception (&error);
5405 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5409 MonoImageOpenStatus status = MONO_IMAGE_OK;
5412 MonoAssemblyName name;
5415 filename = mono_string_to_utf8 (fname);
5417 dirname = g_path_get_dirname (filename);
5418 replace_shadow_path (mono_domain_get (), dirname, &filename);
5421 image = mono_image_open (filename, &status);
5427 if (status == MONO_IMAGE_IMAGE_INVALID)
5428 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5430 exc = mono_get_exception_file_not_found2 (NULL, fname);
5431 mono_set_pending_exception (exc);
5435 res = mono_assembly_fill_assembly_name (image, &name);
5437 mono_image_close (image);
5439 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5443 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5444 mono_error_set_pending_exception (&error);
5446 mono_image_close (image);
5450 ICALL_EXPORT MonoBoolean
5451 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5452 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5454 MonoBoolean result = FALSE;
5455 MonoDeclSecurityEntry entry;
5457 /* SecurityAction.RequestMinimum */
5458 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5459 *minimum = entry.blob;
5460 *minLength = entry.size;
5463 /* SecurityAction.RequestOptional */
5464 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5465 *optional = entry.blob;
5466 *optLength = entry.size;
5469 /* SecurityAction.RequestRefuse */
5470 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5471 *refused = entry.blob;
5472 *refLength = entry.size;
5480 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5482 guint32 attrs, visibility;
5484 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5485 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5486 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5489 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5495 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5497 MonoReflectionType *rt;
5500 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5503 mono_error_init (error);
5505 /* we start the count from 1 because we skip the special type <Module> */
5508 for (i = 1; i < tdef->rows; ++i) {
5509 if (mono_module_type_is_visible (tdef, image, i + 1))
5513 count = tdef->rows - 1;
5515 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5516 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5518 for (i = 1; i < tdef->rows; ++i) {
5519 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5520 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5523 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5524 return_val_if_nok (error, NULL);
5526 mono_array_setref (res, count, rt);
5528 MonoException *ex = mono_error_convert_to_exception (error);
5529 mono_array_setref (*exceptions, count, ex);
5538 ICALL_EXPORT MonoArray*
5539 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5542 MonoArray *res = NULL;
5543 MonoArray *exceptions = NULL;
5544 MonoImage *image = NULL;
5545 MonoTableInfo *table = NULL;
5548 int i, len, ex_count;
5550 domain = mono_object_domain (assembly);
5552 g_assert (!assembly_is_dynamic (assembly->assembly));
5553 image = assembly->assembly->image;
5554 table = &image->tables [MONO_TABLE_FILE];
5555 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5556 mono_error_raise_exception (&error);
5558 /* Append data from all modules in the assembly */
5559 for (i = 0; i < table->rows; ++i) {
5560 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5561 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5566 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5567 mono_error_raise_exception (&error);
5569 /* Append the new types to the end of the array */
5570 if (mono_array_length (res2) > 0) {
5572 MonoArray *res3, *ex3;
5574 len1 = mono_array_length (res);
5575 len2 = mono_array_length (res2);
5577 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5578 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5579 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5582 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5583 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5584 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5591 /* the ReflectionTypeLoadException must have all the types (Types property),
5592 * NULL replacing types which throws an exception. The LoaderException must
5593 * contain all exceptions for NULL items.
5596 len = mono_array_length (res);
5599 for (i = 0; i < len; i++) {
5600 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5604 klass = mono_type_get_class (t->type);
5605 if ((klass != NULL) && mono_class_has_failure (klass)) {
5606 /* keep the class in the list */
5607 list = g_list_append (list, klass);
5608 /* and replace Type with NULL */
5609 mono_array_setref (res, i, NULL);
5616 if (list || ex_count) {
5618 MonoException *exc = NULL;
5619 MonoArray *exl = NULL;
5620 int j, length = g_list_length (list) + ex_count;
5622 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5623 /* Types for which mono_class_get_checked () succeeded */
5624 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5625 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5626 mono_array_setref (exl, i, exc);
5628 /* Types for which it don't */
5629 for (j = 0; j < mono_array_length (exceptions); ++j) {
5630 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5632 g_assert (i < length);
5633 mono_array_setref (exl, i, exc);
5640 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5641 if (!is_ok (&error)) {
5642 mono_error_set_pending_exception (&error);
5645 mono_set_pending_exception (exc);
5652 ICALL_EXPORT gboolean
5653 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5656 MonoAssemblyName aname;
5657 MonoDomain *domain = mono_object_domain (name);
5659 gboolean is_version_defined;
5660 gboolean is_token_defined;
5662 aname.public_key = NULL;
5663 val = mono_string_to_utf8 (assname);
5664 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5665 g_free ((guint8*) aname.public_key);
5670 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5671 mono_error_set_pending_exception (&error);
5673 mono_assembly_name_free (&aname);
5674 g_free ((guint8*) aname.public_key);
5680 ICALL_EXPORT MonoReflectionType*
5681 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5684 MonoReflectionType *ret;
5685 MonoDomain *domain = mono_object_domain (module);
5688 g_assert (module->image);
5690 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5691 /* These images do not have a global type */
5694 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5695 if (!mono_error_ok (&error)) {
5696 mono_error_set_pending_exception (&error);
5700 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5701 if (!mono_error_ok (&error)) {
5702 mono_error_set_pending_exception (&error);
5710 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5712 /*if (module->image)
5713 mono_image_close (module->image);*/
5716 ICALL_EXPORT MonoString*
5717 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5719 MonoDomain *domain = mono_object_domain (module);
5721 g_assert (module->image);
5722 return mono_string_new (domain, module->image->guid);
5725 ICALL_EXPORT gpointer
5726 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5729 if (module->image && module->image->is_module_handle)
5730 return module->image->raw_data;
5733 return (gpointer) (-1);
5737 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5739 if (image_is_dynamic (image)) {
5740 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5741 *pe_kind = dyn->pe_kind;
5742 *machine = dyn->machine;
5745 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5746 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5751 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5753 return (image->md_version_major << 16) | (image->md_version_minor);
5756 ICALL_EXPORT MonoArray*
5757 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5760 MonoArray *exceptions;
5764 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5768 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5769 mono_error_raise_exception (&error);
5771 for (i = 0; i < mono_array_length (exceptions); ++i) {
5772 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5774 mono_set_pending_exception (ex);
5783 mono_memberref_is_method (MonoImage *image, guint32 token)
5785 if (!image_is_dynamic (image)) {
5786 guint32 cols [MONO_MEMBERREF_SIZE];
5788 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5789 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5790 mono_metadata_decode_blob_size (sig, &sig);
5791 return (*sig != 0x6);
5794 MonoClass *handle_class;
5796 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5797 mono_error_cleanup (&error); /* just probing, ignore error */
5801 return mono_defaults.methodhandle_class == handle_class;
5806 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5809 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5810 mono_array_addr (type_args, MonoType*, 0));
5812 context->class_inst = NULL;
5814 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5815 mono_array_addr (method_args, MonoType*, 0));
5817 context->method_inst = NULL;
5820 ICALL_EXPORT MonoType*
5821 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5824 int table = mono_metadata_token_table (token);
5825 int index = mono_metadata_token_index (token);
5826 MonoGenericContext context;
5829 *resolve_error = ResolveTokenError_Other;
5831 /* Validate token */
5832 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5833 (table != MONO_TABLE_TYPESPEC)) {
5834 *resolve_error = ResolveTokenError_BadTable;
5838 if (image_is_dynamic (image)) {
5839 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5840 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5841 mono_error_cleanup (&error);
5842 return klass ? &klass->byval_arg : NULL;
5845 init_generic_context_from_args (&context, type_args, method_args);
5846 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5847 mono_error_cleanup (&error);
5848 return klass ? &klass->byval_arg : NULL;
5851 if ((index <= 0) || (index > image->tables [table].rows)) {
5852 *resolve_error = ResolveTokenError_OutOfRange;
5856 init_generic_context_from_args (&context, type_args, method_args);
5857 klass = mono_class_get_checked (image, token, &error);
5859 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5860 if (!mono_error_ok (&error)) {
5861 mono_error_set_pending_exception (&error);
5866 return &klass->byval_arg;
5871 ICALL_EXPORT MonoMethod*
5872 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5875 int table = mono_metadata_token_table (token);
5876 int index = mono_metadata_token_index (token);
5877 MonoGenericContext context;
5880 *resolve_error = ResolveTokenError_Other;
5882 /* Validate token */
5883 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5884 (table != MONO_TABLE_MEMBERREF)) {
5885 *resolve_error = ResolveTokenError_BadTable;
5889 if (image_is_dynamic (image)) {
5890 if (table == MONO_TABLE_METHOD) {
5891 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5892 mono_error_cleanup (&error);
5896 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5897 *resolve_error = ResolveTokenError_BadTable;
5901 init_generic_context_from_args (&context, type_args, method_args);
5902 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5903 mono_error_cleanup (&error);
5907 if ((index <= 0) || (index > image->tables [table].rows)) {
5908 *resolve_error = ResolveTokenError_OutOfRange;
5911 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5912 *resolve_error = ResolveTokenError_BadTable;
5916 init_generic_context_from_args (&context, type_args, method_args);
5917 method = mono_get_method_checked (image, token, NULL, &context, &error);
5918 mono_error_set_pending_exception (&error);
5923 ICALL_EXPORT MonoString*
5924 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5927 int index = mono_metadata_token_index (token);
5929 *resolve_error = ResolveTokenError_Other;
5931 /* Validate token */
5932 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5933 *resolve_error = ResolveTokenError_BadTable;
5937 if (image_is_dynamic (image)) {
5938 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5939 mono_error_cleanup (&error);
5943 if ((index <= 0) || (index >= image->heap_us.size)) {
5944 *resolve_error = ResolveTokenError_OutOfRange;
5948 /* FIXME: What to do if the index points into the middle of a string ? */
5950 return mono_ldstr (mono_domain_get (), image, index);
5953 ICALL_EXPORT MonoClassField*
5954 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5958 int table = mono_metadata_token_table (token);
5959 int index = mono_metadata_token_index (token);
5960 MonoGenericContext context;
5961 MonoClassField *field;
5963 *resolve_error = ResolveTokenError_Other;
5965 /* Validate token */
5966 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5967 *resolve_error = ResolveTokenError_BadTable;
5971 if (image_is_dynamic (image)) {
5972 if (table == MONO_TABLE_FIELD) {
5973 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5974 mono_error_cleanup (&error);
5978 if (mono_memberref_is_method (image, token)) {
5979 *resolve_error = ResolveTokenError_BadTable;
5983 init_generic_context_from_args (&context, type_args, method_args);
5984 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5985 mono_error_cleanup (&error);
5989 if ((index <= 0) || (index > image->tables [table].rows)) {
5990 *resolve_error = ResolveTokenError_OutOfRange;
5993 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5994 *resolve_error = ResolveTokenError_BadTable;
5998 init_generic_context_from_args (&context, type_args, method_args);
5999 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6000 mono_error_set_pending_exception (&error);
6006 ICALL_EXPORT MonoObject*
6007 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6011 int table = mono_metadata_token_table (token);
6013 *error = ResolveTokenError_Other;
6016 case MONO_TABLE_TYPEDEF:
6017 case MONO_TABLE_TYPEREF:
6018 case MONO_TABLE_TYPESPEC: {
6019 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6021 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6022 mono_error_raise_exception (&merror);
6029 case MONO_TABLE_METHOD:
6030 case MONO_TABLE_METHODSPEC: {
6031 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6033 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6034 mono_error_raise_exception (&merror);
6040 case MONO_TABLE_FIELD: {
6041 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6043 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6044 mono_error_raise_exception (&merror);
6050 case MONO_TABLE_MEMBERREF:
6051 if (mono_memberref_is_method (image, token)) {
6052 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6054 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6055 mono_error_raise_exception (&merror);
6062 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6064 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6065 mono_error_raise_exception (&merror);
6074 *error = ResolveTokenError_BadTable;
6080 ICALL_EXPORT MonoArray*
6081 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
6083 int table = mono_metadata_token_table (token);
6084 int idx = mono_metadata_token_index (token);
6085 MonoTableInfo *tables = image->tables;
6090 *error = ResolveTokenError_OutOfRange;
6092 /* FIXME: Support other tables ? */
6093 if (table != MONO_TABLE_STANDALONESIG)
6096 if (image_is_dynamic (image))
6099 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6102 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6104 ptr = mono_metadata_blob_heap (image, sig);
6105 len = mono_metadata_decode_blob_size (ptr, &ptr);
6107 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
6108 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6112 ICALL_EXPORT MonoReflectionType*
6113 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6116 MonoReflectionType *ret;
6118 int isbyref = 0, rank;
6119 char *str = mono_string_to_utf8 (smodifiers);
6122 klass = mono_class_from_mono_type (tb->type.type);
6124 /* logic taken from mono_reflection_parse_type(): keep in sync */
6128 if (isbyref) { /* only one level allowed by the spec */
6137 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6138 mono_error_raise_exception (&error);
6142 klass = mono_ptr_class_get (&klass->byval_arg);
6143 mono_class_init (klass);
6154 else if (*p != '*') { /* '*' means unknown lower bound */
6165 klass = mono_array_class_get (klass, rank);
6166 mono_class_init (klass);
6175 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6176 mono_error_raise_exception (&error);
6181 ICALL_EXPORT MonoBoolean
6182 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6188 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6194 check_for_invalid_type (MonoClass *klass, MonoError *error)
6199 mono_error_init (error);
6201 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6204 name = mono_type_get_full_name (klass);
6205 str = mono_string_new (mono_domain_get (), name);
6207 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6210 ICALL_EXPORT MonoReflectionType *
6211 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6214 MonoReflectionType *ret;
6215 MonoClass *klass, *aklass;
6217 klass = mono_class_from_mono_type (type->type);
6218 check_for_invalid_type (klass, &error);
6219 mono_error_raise_exception (&error);
6221 if (rank == 0) //single dimentional array
6222 aklass = mono_array_class_get (klass, 1);
6224 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6226 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6227 mono_error_raise_exception (&error);
6232 ICALL_EXPORT MonoReflectionType *
6233 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6236 MonoReflectionType *ret;
6239 klass = mono_class_from_mono_type (type->type);
6240 mono_class_init_checked (klass, &error);
6241 mono_error_raise_exception (&error);
6242 check_for_invalid_type (klass, &error);
6243 mono_error_raise_exception (&error);
6245 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6246 mono_error_raise_exception (&error);
6251 ICALL_EXPORT MonoReflectionType *
6252 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6255 MonoReflectionType *ret;
6256 MonoClass *klass, *pklass;
6258 klass = mono_class_from_mono_type (type->type);
6259 mono_class_init_checked (klass, &error);
6260 mono_error_raise_exception (&error);
6261 check_for_invalid_type (klass, &error);
6262 mono_error_raise_exception (&error);
6264 pklass = mono_ptr_class_get (type->type);
6266 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6267 mono_error_raise_exception (&error);
6272 ICALL_EXPORT MonoObject *
6273 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6274 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6277 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6278 MonoObject *delegate;
6280 MonoMethod *method = info->method;
6282 mono_class_init_checked (delegate_class, &error);
6283 mono_error_raise_exception (&error);
6285 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6286 /* FIXME improve this exception message */
6287 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6289 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6290 mono_error_set_pending_exception (&error);
6294 if (mono_security_core_clr_enabled ()) {
6295 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6296 if (throwOnBindFailure)
6297 mono_error_set_pending_exception (&error);
6299 mono_error_cleanup (&error);
6304 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6305 mono_error_raise_exception (&error);
6307 if (method_is_dynamic (method)) {
6308 /* Creating a trampoline would leak memory */
6309 func = mono_compile_method (method);
6311 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6312 method = mono_object_get_virtual_method (target, method);
6313 func = mono_create_ftnptr (mono_domain_get (),
6314 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6317 mono_delegate_ctor_with_method (delegate, target, func, method);
6322 ICALL_EXPORT MonoMulticastDelegate *
6323 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6326 MonoMulticastDelegate *ret;
6328 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6330 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6331 mono_error_raise_exception (&error);
6332 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6337 ICALL_EXPORT MonoReflectionMethod*
6338 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6340 MonoReflectionMethod *ret = NULL;
6342 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6343 mono_error_raise_exception (&error);
6349 static inline gint32
6350 mono_array_get_byte_length (MonoArray *array)
6356 klass = array->obj.vtable->klass;
6358 if (array->bounds == NULL)
6359 length = array->max_length;
6362 for (i = 0; i < klass->rank; ++ i)
6363 length *= array->bounds [i].length;
6366 switch (klass->element_class->byval_arg.type) {
6369 case MONO_TYPE_BOOLEAN:
6373 case MONO_TYPE_CHAR:
6381 return length * sizeof (gpointer);
6392 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6394 return mono_array_get_byte_length (array);
6398 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6400 return mono_array_get (array, gint8, idx);
6404 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6406 mono_array_set (array, gint8, idx, value);
6409 ICALL_EXPORT MonoBoolean
6410 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6412 guint8 *src_buf, *dest_buf;
6415 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6419 g_assert (count >= 0);
6421 /* This is called directly from the class libraries without going through the managed wrapper */
6422 MONO_CHECK_ARG_NULL (src, FALSE);
6423 MONO_CHECK_ARG_NULL (dest, FALSE);
6425 /* watch out for integer overflow */
6426 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6429 src_buf = (guint8 *)src->vector + src_offset;
6430 dest_buf = (guint8 *)dest->vector + dest_offset;
6433 memcpy (dest_buf, src_buf, count);
6435 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6440 #ifndef DISABLE_REMOTING
6441 ICALL_EXPORT MonoObject *
6442 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6445 MonoDomain *domain = mono_object_domain (this_obj);
6447 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6448 MonoTransparentProxy *tp;
6452 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6453 mono_error_raise_exception (&error);
6454 tp = (MonoTransparentProxy*) res;
6456 MONO_OBJECT_SETREF (tp, rp, rp);
6457 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6458 klass = mono_class_from_mono_type (type);
6460 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6461 mono_class_setup_vtable (klass);
6462 if (mono_class_has_failure (klass)) {
6463 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6467 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6468 if (!is_ok (&error)) {
6469 mono_error_set_pending_exception (&error);
6472 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6473 if (!is_ok (&error)) {
6474 mono_error_set_pending_exception (&error);
6478 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6482 ICALL_EXPORT MonoReflectionType *
6483 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6486 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6487 mono_error_raise_exception (&error);
6493 /* System.Environment */
6496 ves_icall_System_Environment_get_UserName (void)
6498 /* using glib is more portable */
6499 return mono_string_new (mono_domain_get (), g_get_user_name ());
6503 ICALL_EXPORT MonoString *
6504 ves_icall_System_Environment_get_MachineName (void)
6506 #if defined (HOST_WIN32)
6511 len = MAX_COMPUTERNAME_LENGTH + 1;
6512 buf = g_new (gunichar2, len);
6515 if (GetComputerName (buf, (PDWORD) &len)) {
6517 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6518 mono_error_raise_exception (&error);
6523 #elif !defined(DISABLE_SOCKETS)
6527 #if defined _SC_HOST_NAME_MAX
6528 n = sysconf (_SC_HOST_NAME_MAX);
6532 buf = g_malloc (n+1);
6534 if (gethostname (buf, n) == 0){
6536 result = mono_string_new (mono_domain_get (), buf);
6543 return mono_string_new (mono_domain_get (), "mono");
6548 ves_icall_System_Environment_get_Platform (void)
6550 #if defined (TARGET_WIN32)
6553 #elif defined(__MACH__)
6556 // Notice that the value is hidden from user code, and only exposed
6557 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6558 // define and making assumptions based on Unix/128/4 values before there
6559 // was a MacOS define. Lots of code would assume that not-Unix meant
6560 // Windows, but in this case, it would be OSX.
6569 ICALL_EXPORT MonoString *
6570 ves_icall_System_Environment_get_NewLine (void)
6572 #if defined (HOST_WIN32)
6573 return mono_string_new (mono_domain_get (), "\r\n");
6575 return mono_string_new (mono_domain_get (), "\n");
6579 ICALL_EXPORT MonoBoolean
6580 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6582 #if SIZEOF_VOID_P == 8
6586 gboolean isWow64Process = FALSE;
6587 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6588 return (MonoBoolean)isWow64Process;
6590 #elif defined(HAVE_SYS_UTSNAME_H)
6591 struct utsname name;
6593 if (uname (&name) >= 0) {
6594 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6601 ICALL_EXPORT MonoString *
6602 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6610 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6611 value = g_getenv (utf8_name);
6618 return mono_string_new (mono_domain_get (), value);
6622 * There is no standard way to get at environ.
6625 #ifndef __MINGW32_VERSION
6626 #if defined(__APPLE__)
6627 #if defined (TARGET_OSX)
6628 /* Apple defines this in crt_externs.h but doesn't provide that header for
6629 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6630 * in fact exist on all implementations (so far)
6632 gchar ***_NSGetEnviron(void);
6633 #define environ (*_NSGetEnviron())
6635 static char *mono_environ[1] = { NULL };
6636 #define environ mono_environ
6637 #endif /* defined (TARGET_OSX) */
6645 ICALL_EXPORT MonoArray *
6646 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6657 env_strings = GetEnvironmentStrings();
6660 env_string = env_strings;
6661 while (*env_string != '\0') {
6662 /* weird case that MS seems to skip */
6663 if (*env_string != '=')
6665 while (*env_string != '\0')
6671 domain = mono_domain_get ();
6672 names = mono_array_new (domain, mono_defaults.string_class, n);
6676 env_string = env_strings;
6677 while (*env_string != '\0') {
6678 /* weird case that MS seems to skip */
6679 if (*env_string != '=') {
6680 equal_str = wcschr(env_string, '=');
6681 g_assert(equal_str);
6683 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6684 mono_error_raise_exception (&error);
6685 mono_array_setref (names, n, str);
6688 while (*env_string != '\0')
6693 FreeEnvironmentStrings (env_strings);
6706 for (e = environ; *e != 0; ++ e)
6709 domain = mono_domain_get ();
6710 names = mono_array_new (domain, mono_defaults.string_class, n);
6713 for (e = environ; *e != 0; ++ e) {
6714 parts = g_strsplit (*e, "=", 2);
6716 str = mono_string_new (domain, *parts);
6717 mono_array_setref (names, n, str);
6730 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6732 #if !GLIB_CHECK_VERSION(2,4,0)
6733 #define g_setenv(a,b,c) setenv(a,b,c)
6734 #define g_unsetenv(a) unsetenv(a)
6738 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6741 gunichar2 *utf16_name, *utf16_value;
6743 gchar *utf8_name, *utf8_value;
6748 utf16_name = mono_string_to_utf16 (name);
6749 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6750 SetEnvironmentVariable (utf16_name, NULL);
6751 g_free (utf16_name);
6755 utf16_value = mono_string_to_utf16 (value);
6757 SetEnvironmentVariable (utf16_name, utf16_value);
6759 g_free (utf16_name);
6760 g_free (utf16_value);
6762 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6764 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6765 g_unsetenv (utf8_name);
6770 utf8_value = mono_string_to_utf8_checked (value, &error);
6771 if (!mono_error_ok (&error)) {
6773 mono_error_set_pending_exception (&error);
6776 g_setenv (utf8_name, utf8_value, TRUE);
6779 g_free (utf8_value);
6784 ves_icall_System_Environment_Exit (int result)
6786 mono_environment_exitcode_set (result);
6788 /* FIXME: There are some cleanup hangs that should be worked out, but
6789 * if the program is going to exit, everything will be cleaned up when
6790 * NaCl exits anyway.
6792 #ifndef __native_client__
6793 if (!mono_runtime_try_shutdown ())
6794 mono_thread_exit ();
6796 /* Suspend all managed threads since the runtime is going away */
6797 mono_thread_suspend_all_other_threads ();
6799 mono_runtime_quit ();
6802 /* we may need to do some cleanup here... */
6806 ICALL_EXPORT MonoString*
6807 ves_icall_System_Environment_GetGacPath (void)
6809 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6812 ICALL_EXPORT MonoString*
6813 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6815 #if defined (HOST_WIN32)
6816 #ifndef CSIDL_FLAG_CREATE
6817 #define CSIDL_FLAG_CREATE 0x8000
6820 WCHAR path [MAX_PATH];
6821 /* Create directory if no existing */
6822 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6827 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6828 mono_error_raise_exception (&error);
6832 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6834 return mono_string_new (mono_domain_get (), "");
6837 ICALL_EXPORT MonoArray *
6838 ves_icall_System_Environment_GetLogicalDrives (void)
6841 gunichar2 buf [256], *ptr, *dname;
6843 guint initial_size = 127, size = 128;
6846 MonoString *drivestr;
6847 MonoDomain *domain = mono_domain_get ();
6853 while (size > initial_size) {
6854 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6855 if (size > initial_size) {
6858 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6859 initial_size = size;
6873 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6878 while (*u16) { u16++; len ++; }
6879 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6880 mono_error_raise_exception (&error);
6881 mono_array_setref (result, ndrives++, drivestr);
6891 ICALL_EXPORT MonoString *
6892 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6894 gunichar2 volume_name [MAX_PATH + 1];
6896 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6898 return mono_string_from_utf16 (volume_name);
6901 ICALL_EXPORT MonoString *
6902 ves_icall_System_Environment_InternalGetHome (void)
6904 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6907 static const char *encodings [] = {
6909 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6910 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6911 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6913 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6914 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6915 "x_unicode_2_0_utf_7",
6917 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6918 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6920 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6923 "unicodefffe", "utf_16be",
6930 * Returns the internal codepage, if the value of "int_code_page" is
6931 * 1 at entry, and we can not compute a suitable code page number,
6932 * returns the code page as a string
6934 ICALL_EXPORT MonoString*
6935 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6940 char *codepage = NULL;
6942 int want_name = *int_code_page;
6945 *int_code_page = -1;
6947 g_get_charset (&cset);
6948 c = codepage = strdup (cset);
6949 for (c = codepage; *c; c++){
6950 if (isascii (*c) && isalpha (*c))
6955 /* g_print ("charset: %s\n", cset); */
6957 /* handle some common aliases */
6960 for (i = 0; p != 0; ){
6963 p = encodings [++i];
6966 if (strcmp (p, codepage) == 0){
6967 *int_code_page = code;
6970 p = encodings [++i];
6973 if (strstr (codepage, "utf_8") != NULL)
6974 *int_code_page |= 0x10000000;
6977 if (want_name && *int_code_page == -1)
6978 return mono_string_new (mono_domain_get (), cset);
6983 ICALL_EXPORT MonoBoolean
6984 ves_icall_System_Environment_get_HasShutdownStarted (void)
6986 if (mono_runtime_is_shutting_down ())
6989 if (mono_domain_is_unloading (mono_domain_get ()))
6996 ves_icall_System_Environment_BroadcastSettingChange (void)
6999 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7004 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7010 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
7011 MonoReflectionMethod *method,
7012 MonoArray *out_args)
7014 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
7017 #ifndef DISABLE_REMOTING
7018 ICALL_EXPORT MonoBoolean
7019 ves_icall_IsTransparentProxy (MonoObject *proxy)
7024 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7030 ICALL_EXPORT MonoReflectionMethod *
7031 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7032 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7034 MonoReflectionMethod *ret = NULL;
7039 MonoMethod **vtable;
7040 MonoMethod *res = NULL;
7042 MONO_CHECK_ARG_NULL (rtype, NULL);
7043 MONO_CHECK_ARG_NULL (rmethod, NULL);
7045 method = rmethod->method;
7046 klass = mono_class_from_mono_type (rtype->type);
7047 mono_class_init_checked (klass, &error);
7048 mono_error_raise_exception (&error);
7050 if (MONO_CLASS_IS_INTERFACE (klass))
7053 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7056 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7057 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7063 mono_class_setup_vtable (klass);
7064 vtable = klass->vtable;
7066 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7067 gboolean variance_used = FALSE;
7068 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7069 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7071 res = vtable [offs + method->slot];
7073 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7076 if (method->slot != -1)
7077 res = vtable [method->slot];
7083 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7084 mono_error_raise_exception (&error);
7089 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7095 klass = mono_class_from_mono_type (type->type);
7096 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7097 if (!is_ok (&error)) {
7098 mono_error_set_pending_exception (&error);
7102 mono_vtable_set_is_remote (vtable, enable);
7105 #else /* DISABLE_REMOTING */
7108 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7110 g_assert_not_reached ();
7115 ICALL_EXPORT MonoObject *
7116 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7123 domain = mono_object_domain (type);
7124 klass = mono_class_from_mono_type (type->type);
7125 mono_class_init_checked (klass, &error);
7126 mono_error_raise_exception (&error);
7128 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7129 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7133 if (klass->rank >= 1) {
7134 g_assert (klass->rank == 1);
7135 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7137 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7138 if (!is_ok (&error)) {
7139 mono_error_set_pending_exception (&error);
7142 /* Bypass remoting object creation check */
7143 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7144 mono_error_set_pending_exception (&error);
7150 ICALL_EXPORT MonoString *
7151 ves_icall_System_IO_get_temp_path (void)
7153 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7156 #ifndef PLATFORM_NO_DRIVEINFO
7157 ICALL_EXPORT MonoBoolean
7158 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7159 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7163 ULARGE_INTEGER wapi_free_bytes_avail;
7164 ULARGE_INTEGER wapi_total_number_of_bytes;
7165 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7167 *error = ERROR_SUCCESS;
7168 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7169 &wapi_total_number_of_free_bytes);
7172 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7173 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7174 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7176 *free_bytes_avail = 0;
7177 *total_number_of_bytes = 0;
7178 *total_number_of_free_bytes = 0;
7179 *error = GetLastError ();
7185 ICALL_EXPORT guint32
7186 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7188 return GetDriveType (mono_string_chars (root_path_name));
7192 ICALL_EXPORT gpointer
7193 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7195 return mono_compile_method (method);
7198 ICALL_EXPORT MonoString *
7199 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7204 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7206 #if defined (HOST_WIN32)
7207 /* Avoid mixing '/' and '\\' */
7210 for (i = strlen (path) - 1; i >= 0; i--)
7211 if (path [i] == '/')
7215 mcpath = mono_string_new (mono_domain_get (), path);
7222 get_bundled_app_config (void)
7224 const gchar *app_config;
7227 gchar *config_file_name, *config_file_path;
7228 gsize len, config_file_path_length, config_ext_length;
7231 domain = mono_domain_get ();
7232 file = domain->setup->configuration_file;
7233 if (!file || file->length == 0)
7236 // Retrieve config file and remove the extension
7237 config_file_name = mono_string_to_utf8 (file);
7238 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7239 if (!config_file_path)
7240 config_file_path = config_file_name;
7242 config_file_path_length = strlen (config_file_path);
7243 config_ext_length = strlen (".config");
7244 if (config_file_path_length <= config_ext_length)
7247 len = config_file_path_length - config_ext_length;
7248 module = (gchar *)g_malloc0 (len + 1);
7249 memcpy (module, config_file_path, len);
7250 // Get the config file from the module name
7251 app_config = mono_config_string_for_assembly_file (module);
7254 if (config_file_name != config_file_path)
7255 g_free (config_file_name);
7256 g_free (config_file_path);
7261 return mono_string_new (mono_domain_get (), app_config);
7265 get_bundled_machine_config (void)
7267 const gchar *machine_config;
7269 machine_config = mono_get_machine_config ();
7271 if (!machine_config)
7274 return mono_string_new (mono_domain_get (), machine_config);
7277 ICALL_EXPORT MonoString *
7278 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7283 path = g_path_get_dirname (mono_get_config_dir ());
7285 #if defined (HOST_WIN32)
7286 /* Avoid mixing '/' and '\\' */
7289 for (i = strlen (path) - 1; i >= 0; i--)
7290 if (path [i] == '/')
7294 ipath = mono_string_new (mono_domain_get (), path);
7300 ICALL_EXPORT gboolean
7301 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7303 MonoPEResourceDataEntry *entry;
7306 if (!assembly || !result || !size)
7311 image = assembly->assembly->image;
7312 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7316 *result = mono_image_rva_map (image, entry->rde_data_offset);
7321 *size = entry->rde_size;
7326 ICALL_EXPORT MonoBoolean
7327 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7329 return mono_is_debugger_attached ();
7332 ICALL_EXPORT MonoBoolean
7333 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7335 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7336 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7342 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7344 if (mono_get_runtime_callbacks ()->debug_log)
7345 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7349 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7351 #if defined (HOST_WIN32)
7352 OutputDebugString (mono_string_chars (message));
7354 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7358 /* Only used for value types */
7359 ICALL_EXPORT MonoObject *
7360 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7367 domain = mono_object_domain (type);
7368 klass = mono_class_from_mono_type (type->type);
7369 mono_class_init_checked (klass, &error);
7370 mono_error_raise_exception (&error);
7372 if (mono_class_is_nullable (klass))
7373 /* No arguments -> null */
7376 result = mono_object_new_checked (domain, klass, &error);
7377 mono_error_raise_exception (&error);
7381 ICALL_EXPORT MonoReflectionMethod *
7382 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7384 MonoReflectionMethod *ret = NULL;
7387 MonoClass *klass, *parent;
7388 MonoGenericContext *generic_inst = NULL;
7389 MonoMethod *method = m->method;
7390 MonoMethod *result = NULL;
7393 if (method->klass == NULL)
7396 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7397 MONO_CLASS_IS_INTERFACE (method->klass) ||
7398 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7401 slot = mono_method_get_vtable_slot (method);
7405 klass = method->klass;
7406 if (klass->generic_class) {
7407 generic_inst = mono_class_get_context (klass);
7408 klass = klass->generic_class->container_class;
7412 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7413 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7414 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7415 or klass is the generic container class and generic_inst is the instantiation.
7417 when we go to the parent, if the parent is an open constructed type, we need to
7418 replace the type parameters by the definitions from the generic_inst, and then take it
7419 apart again into the klass and the generic_inst.
7421 For cases like this:
7422 class C<T> : B<T, int> {
7423 public override void Foo () { ... }
7425 class B<U,V> : A<HashMap<U,V>> {
7426 public override void Foo () { ... }
7429 public virtual void Foo () { ... }
7432 if at each iteration the parent isn't open, we can skip inflating it. if at some
7433 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7436 MonoGenericContext *parent_inst = NULL;
7437 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7439 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7440 if (!mono_error_ok (&error)) {
7441 mono_error_set_pending_exception (&error);
7445 if (parent->generic_class) {
7446 parent_inst = mono_class_get_context (parent);
7447 parent = parent->generic_class->container_class;
7450 mono_class_setup_vtable (parent);
7451 if (parent->vtable_size <= slot)
7454 generic_inst = parent_inst;
7457 klass = klass->parent;
7460 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7461 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7462 if (!mono_error_ok (&error)) {
7463 mono_error_set_pending_exception (&error);
7467 generic_inst = NULL;
7469 if (klass->generic_class) {
7470 generic_inst = mono_class_get_context (klass);
7471 klass = klass->generic_class->container_class;
7477 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7478 if (!mono_error_ok (&error)) {
7479 mono_error_set_pending_exception (&error);
7484 if (klass == method->klass)
7487 /*This is possible if definition == FALSE.
7488 * Do it here to be really sure we don't read invalid memory.
7490 if (slot >= klass->vtable_size)
7493 mono_class_setup_vtable (klass);
7495 result = klass->vtable [slot];
7496 if (result == NULL) {
7497 /* It is an abstract method */
7498 gpointer iter = NULL;
7499 while ((result = mono_class_get_methods (klass, &iter)))
7500 if (result->slot == slot)
7507 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7508 mono_error_raise_exception (&error);
7512 ICALL_EXPORT MonoString*
7513 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7515 MonoMethod *method = m->method;
7517 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7522 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7524 iter->sig = *(MonoMethodSignature**)argsp;
7526 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7527 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7530 /* FIXME: it's not documented what start is exactly... */
7534 iter->args = argsp + sizeof (gpointer);
7536 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7538 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7541 ICALL_EXPORT MonoTypedRef
7542 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7544 guint32 i, arg_size;
7548 i = iter->sig->sentinelpos + iter->next_arg;
7550 g_assert (i < iter->sig->param_count);
7552 res.type = iter->sig->params [i];
7553 res.klass = mono_class_from_mono_type (res.type);
7554 arg_size = mono_type_stack_size (res.type, &align);
7555 #if defined(__arm__) || defined(__mips__)
7556 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7558 res.value = iter->args;
7559 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7560 /* Values are stored as 8 byte register sized objects, but 'value'
7561 * is dereferenced as a pointer in other routines.
7563 res.value = (char*)res.value + 4;
7565 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7566 if (arg_size <= sizeof (gpointer)) {
7568 int padding = arg_size - mono_type_size (res.type, &dummy);
7569 res.value = (guint8*)res.value + padding;
7572 iter->args = (char*)iter->args + arg_size;
7575 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7580 ICALL_EXPORT MonoTypedRef
7581 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7583 guint32 i, arg_size;
7587 i = iter->sig->sentinelpos + iter->next_arg;
7589 g_assert (i < iter->sig->param_count);
7591 while (i < iter->sig->param_count) {
7592 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7594 res.type = iter->sig->params [i];
7595 res.klass = mono_class_from_mono_type (res.type);
7596 /* FIXME: endianess issue... */
7597 arg_size = mono_type_stack_size (res.type, &align);
7598 #if defined(__arm__) || defined(__mips__)
7599 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7601 res.value = iter->args;
7602 iter->args = (char*)iter->args + arg_size;
7604 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7607 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7615 ICALL_EXPORT MonoType*
7616 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7620 i = iter->sig->sentinelpos + iter->next_arg;
7622 g_assert (i < iter->sig->param_count);
7624 return iter->sig->params [i];
7627 ICALL_EXPORT MonoObject*
7628 mono_TypedReference_ToObject (MonoTypedRef* tref)
7631 MonoObject *result = NULL;
7632 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7633 MonoObject** objp = (MonoObject **)tref->value;
7637 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7638 mono_error_set_pending_exception (&error);
7642 ICALL_EXPORT MonoTypedRef
7643 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7646 MonoReflectionField *f;
7648 MonoType *ftype = NULL;
7652 memset (&res, 0, sizeof (res));
7655 g_assert (mono_array_length (fields) > 0);
7657 klass = target->vtable->klass;
7659 for (i = 0; i < mono_array_length (fields); ++i) {
7660 f = mono_array_get (fields, MonoReflectionField*, i);
7662 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7665 if (f->field->parent != klass) {
7666 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7670 p = (guint8*)target + f->field->offset;
7672 p += f->field->offset - sizeof (MonoObject);
7673 klass = mono_class_from_mono_type (f->field->type);
7674 ftype = f->field->type;
7678 res.klass = mono_class_from_mono_type (ftype);
7685 prelink_method (MonoMethod *method, MonoError *error)
7687 const char *exc_class, *exc_arg;
7689 mono_error_init (error);
7690 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7692 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7694 mono_error_set_exception_instance (error,
7695 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7698 /* create the wrapper, too? */
7702 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7706 prelink_method (method->method, &error);
7707 mono_error_raise_exception (&error);
7711 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7714 MonoClass *klass = mono_class_from_mono_type (type->type);
7716 gpointer iter = NULL;
7718 mono_class_init_checked (klass, &error);
7719 mono_error_raise_exception (&error);
7721 while ((m = mono_class_get_methods (klass, &iter))) {
7722 prelink_method (m, &error);
7723 mono_error_raise_exception (&error);
7727 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7729 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7730 gint32 const **exponents,
7731 gunichar2 const **digitLowerTable,
7732 gunichar2 const **digitUpperTable,
7733 gint64 const **tenPowersList,
7734 gint32 const **decHexDigits)
7736 *mantissas = Formatter_MantissaBitsTable;
7737 *exponents = Formatter_TensExponentTable;
7738 *digitLowerTable = Formatter_DigitLowerTable;
7739 *digitUpperTable = Formatter_DigitUpperTable;
7740 *tenPowersList = Formatter_TenPowersList;
7741 *decHexDigits = Formatter_DecHexDigits;
7745 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7746 * and avoid useless allocations.
7749 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7751 MonoReflectionType *rt;
7755 mono_error_init (error);
7756 for (i = 0; i < type->num_mods; ++i) {
7757 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7762 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7764 for (i = 0; i < type->num_mods; ++i) {
7765 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7766 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7767 return_val_if_nok (error, NULL);
7769 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7770 return_val_if_nok (error, NULL);
7772 mono_array_setref (res, count, rt);
7779 ICALL_EXPORT MonoArray*
7780 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7783 MonoType *type = param->ClassImpl->type;
7784 MonoClass *member_class = mono_object_class (param->MemberImpl);
7785 MonoMethod *method = NULL;
7788 MonoMethodSignature *sig;
7791 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7792 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7793 method = rmethod->method;
7794 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7795 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7796 if (!(method = prop->property->get))
7797 method = prop->property->set;
7800 char *type_name = mono_type_get_full_name (member_class);
7801 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7802 MonoException *ex = mono_get_exception_not_supported (msg);
7805 mono_set_pending_exception (ex);
7809 image = method->klass->image;
7810 pos = param->PositionImpl;
7811 sig = mono_method_signature (method);
7815 type = sig->params [pos];
7817 res = type_array_from_modifiers (image, type, optional, &error);
7818 mono_error_raise_exception (&error);
7823 get_property_type (MonoProperty *prop)
7825 MonoMethodSignature *sig;
7827 sig = mono_method_signature (prop->get);
7829 } else if (prop->set) {
7830 sig = mono_method_signature (prop->set);
7831 return sig->params [sig->param_count - 1];
7836 ICALL_EXPORT MonoArray*
7837 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7840 MonoType *type = get_property_type (property->property);
7841 MonoImage *image = property->klass->image;
7846 res = type_array_from_modifiers (image, type, optional, &error);
7847 mono_error_raise_exception (&error);
7852 *Construct a MonoType suited to be used to decode a constant blob object.
7854 * @type is the target type which will be constructed
7855 * @blob_type is the blob type, for example, that comes from the constant table
7856 * @real_type is the expected constructed type.
7859 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7861 type->type = blob_type;
7862 type->data.klass = NULL;
7863 if (blob_type == MONO_TYPE_CLASS)
7864 type->data.klass = mono_defaults.object_class;
7865 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7866 /* For enums, we need to use the base type */
7867 type->type = MONO_TYPE_VALUETYPE;
7868 type->data.klass = mono_class_from_mono_type (real_type);
7870 type->data.klass = mono_class_from_mono_type (real_type);
7873 ICALL_EXPORT MonoObject*
7874 property_info_get_default_value (MonoReflectionProperty *property)
7878 MonoProperty *prop = property->property;
7879 MonoType *type = get_property_type (prop);
7880 MonoDomain *domain = mono_object_domain (property);
7881 MonoTypeEnum def_type;
7882 const char *def_value;
7885 mono_class_init (prop->parent);
7887 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7888 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7892 def_value = mono_class_get_property_default_value (prop, &def_type);
7894 mono_type_from_blob_type (&blob_type, def_type, type);
7895 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7897 mono_error_set_pending_exception (&error);
7901 ICALL_EXPORT MonoBoolean
7902 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7905 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7906 MonoCustomAttrInfo *cinfo;
7909 mono_class_init_checked (attr_class, &error);
7910 mono_error_raise_exception (&error);
7912 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7913 if (!is_ok (&error)) {
7914 mono_error_set_pending_exception (&error);
7919 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7921 mono_custom_attrs_free (cinfo);
7925 ICALL_EXPORT MonoArray*
7926 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7928 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7933 mono_class_init_checked (attr_class, &error);
7934 mono_error_raise_exception (&error);
7937 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7938 if (!mono_error_ok (&error)) {
7939 mono_error_set_pending_exception (&error);
7946 ICALL_EXPORT MonoArray*
7947 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7951 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7952 mono_error_set_pending_exception (&error);
7957 ICALL_EXPORT MonoString*
7958 ves_icall_Mono_Runtime_GetDisplayName (void)
7961 MonoString *display_name;
7963 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7964 display_name = mono_string_new (mono_domain_get (), info);
7966 return display_name;
7969 ICALL_EXPORT MonoString*
7970 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7973 MonoString *message;
7977 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7978 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7981 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7983 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7984 mono_error_raise_exception (&error);
7990 ICALL_EXPORT gpointer
7991 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
7993 return GetCurrentProcess ();
7996 ICALL_EXPORT MonoBoolean
7997 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
7999 return GetExitCodeProcess (handle, (guint32*) exitcode);
8002 ICALL_EXPORT MonoBoolean
8003 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8005 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8006 return CloseHandle (handle);
8008 return CloseProcess (handle);
8012 ICALL_EXPORT MonoBoolean
8013 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8015 return TerminateProcess (handle, exitcode);
8019 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8021 return WaitForInputIdle (handle, milliseconds);
8024 ICALL_EXPORT MonoBoolean
8025 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8027 return GetProcessWorkingSetSize (handle, min, max);
8030 ICALL_EXPORT MonoBoolean
8031 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8033 return SetProcessWorkingSetSize (handle, min, max);
8036 ICALL_EXPORT MonoBoolean
8037 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8039 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8043 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8045 return mono_process_current_pid ();
8049 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8051 return GetPriorityClass (handle);
8054 ICALL_EXPORT MonoBoolean
8055 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8057 return SetPriorityClass (handle, priorityClass);
8060 #ifndef DISABLE_ICALL_TABLES
8062 #define ICALL_TYPE(id,name,first)
8063 #define ICALL(id,name,func) Icall_ ## id,
8066 #include "metadata/icall-def.h"
8072 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8073 #define ICALL(id,name,func)
8075 #include "metadata/icall-def.h"
8081 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8082 #define ICALL(id,name,func)
8084 guint16 first_icall;
8087 static const IcallTypeDesc
8088 icall_type_descs [] = {
8089 #include "metadata/icall-def.h"
8093 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8096 #define ICALL_TYPE(id,name,first)
8099 #ifdef HAVE_ARRAY_ELEM_INIT
8100 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8101 #define MSGSTRFIELD1(line) str##line
8103 static const struct msgstrtn_t {
8104 #define ICALL(id,name,func)
8106 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8107 #include "metadata/icall-def.h"
8109 } icall_type_names_str = {
8110 #define ICALL_TYPE(id,name,first) (name),
8111 #include "metadata/icall-def.h"
8114 static const guint16 icall_type_names_idx [] = {
8115 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8116 #include "metadata/icall-def.h"
8119 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8121 static const struct msgstr_t {
8123 #define ICALL_TYPE(id,name,first)
8124 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8125 #include "metadata/icall-def.h"
8127 } icall_names_str = {
8128 #define ICALL(id,name,func) (name),
8129 #include "metadata/icall-def.h"
8132 static const guint16 icall_names_idx [] = {
8133 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8134 #include "metadata/icall-def.h"
8137 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8143 #define ICALL_TYPE(id,name,first) name,
8144 #define ICALL(id,name,func)
8145 static const char* const
8146 icall_type_names [] = {
8147 #include "metadata/icall-def.h"
8151 #define icall_type_name_get(id) (icall_type_names [(id)])
8155 #define ICALL_TYPE(id,name,first)
8156 #define ICALL(id,name,func) name,
8157 static const char* const
8159 #include "metadata/icall-def.h"
8162 #define icall_name_get(id) icall_names [(id)]
8164 #endif /* !HAVE_ARRAY_ELEM_INIT */
8168 #define ICALL_TYPE(id,name,first)
8169 #define ICALL(id,name,func) func,
8170 static const gconstpointer
8171 icall_functions [] = {
8172 #include "metadata/icall-def.h"
8176 #ifdef ENABLE_ICALL_SYMBOL_MAP
8179 #define ICALL_TYPE(id,name,first)
8180 #define ICALL(id,name,func) #func,
8181 static const gconstpointer
8182 icall_symbols [] = {
8183 #include "metadata/icall-def.h"
8188 #endif /* DISABLE_ICALL_TABLES */
8190 static mono_mutex_t icall_mutex;
8191 static GHashTable *icall_hash = NULL;
8192 static GHashTable *jit_icall_hash_name = NULL;
8193 static GHashTable *jit_icall_hash_addr = NULL;
8196 mono_icall_init (void)
8198 #ifndef DISABLE_ICALL_TABLES
8201 /* check that tables are sorted: disable in release */
8204 const char *prev_class = NULL;
8205 const char *prev_method;
8207 for (i = 0; i < Icall_type_num; ++i) {
8208 const IcallTypeDesc *desc;
8211 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8212 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8213 prev_class = icall_type_name_get (i);
8214 desc = &icall_type_descs [i];
8215 num_icalls = icall_desc_num_icalls (desc);
8216 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8217 for (j = 0; j < num_icalls; ++j) {
8218 const char *methodn = icall_name_get (desc->first_icall + j);
8219 if (prev_method && strcmp (prev_method, methodn) >= 0)
8220 g_print ("method %s should come before method %s\n", methodn, prev_method);
8221 prev_method = methodn;
8227 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8228 mono_os_mutex_init (&icall_mutex);
8232 mono_icall_lock (void)
8234 mono_locks_os_acquire (&icall_mutex, IcallLock);
8238 mono_icall_unlock (void)
8240 mono_locks_os_release (&icall_mutex, IcallLock);
8244 mono_icall_cleanup (void)
8246 g_hash_table_destroy (icall_hash);
8247 g_hash_table_destroy (jit_icall_hash_name);
8248 g_hash_table_destroy (jit_icall_hash_addr);
8249 mono_os_mutex_destroy (&icall_mutex);
8253 * mono_add_internal_call:
8254 * @name: method specification to surface to the managed world
8255 * @method: pointer to a C method to invoke when the method is called
8257 * This method surfaces the C function pointed by @method as a method
8258 * that has been surfaced in managed code with the method specified in
8259 * @name as an internal call.
8261 * Internal calls are surfaced to all app domains loaded and they are
8262 * accessibly by a type with the specified name.
8264 * You must provide a fully qualified type name, that is namespaces
8265 * and type name, followed by a colon and the method name, with an
8266 * optional signature to bind.
8268 * For example, the following are all valid declarations:
8270 * "MyApp.Services.ScriptService:Accelerate"
8271 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8273 * You use method parameters in cases where there might be more than
8274 * one surface method to managed code. That way you can register different
8275 * internal calls for different method overloads.
8277 * The internal calls are invoked with no marshalling. This means that .NET
8278 * types like System.String are exposed as `MonoString *` parameters. This is
8279 * different than the way that strings are surfaced in P/Invoke.
8281 * For more information on how the parameters are marshalled, see the
8282 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8285 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8286 * reference for more information on the format of method descriptions.
8289 mono_add_internal_call (const char *name, gconstpointer method)
8293 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8295 mono_icall_unlock ();
8298 #ifndef DISABLE_ICALL_TABLES
8300 #ifdef HAVE_ARRAY_ELEM_INIT
8302 compare_method_imap (const void *key, const void *elem)
8304 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8305 return strcmp (key, method_name);
8309 find_method_icall (const IcallTypeDesc *imap, const char *name)
8311 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);
8314 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8318 compare_class_imap (const void *key, const void *elem)
8320 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8321 return strcmp (key, class_name);
8324 static const IcallTypeDesc*
8325 find_class_icalls (const char *name)
8327 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);
8330 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8333 #else /* HAVE_ARRAY_ELEM_INIT */
8336 compare_method_imap (const void *key, const void *elem)
8338 const char** method_name = (const char**)elem;
8339 return strcmp (key, *method_name);
8343 find_method_icall (const IcallTypeDesc *imap, const char *name)
8345 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8348 return (gpointer)icall_functions [(nameslot - icall_names)];
8352 compare_class_imap (const void *key, const void *elem)
8354 const char** class_name = (const char**)elem;
8355 return strcmp (key, *class_name);
8358 static const IcallTypeDesc*
8359 find_class_icalls (const char *name)
8361 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8364 return &icall_type_descs [nameslot - icall_type_names];
8367 #endif /* HAVE_ARRAY_ELEM_INIT */
8369 #endif /* DISABLE_ICALL_TABLES */
8372 * we should probably export this as an helper (handle nested types).
8373 * Returns the number of chars written in buf.
8376 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8378 int nspacelen, cnamelen;
8379 nspacelen = strlen (klass->name_space);
8380 cnamelen = strlen (klass->name);
8381 if (nspacelen + cnamelen + 2 > bufsize)
8384 memcpy (buf, klass->name_space, nspacelen);
8385 buf [nspacelen ++] = '.';
8387 memcpy (buf + nspacelen, klass->name, cnamelen);
8388 buf [nspacelen + cnamelen] = 0;
8389 return nspacelen + cnamelen;
8392 #ifdef DISABLE_ICALL_TABLES
8394 no_icall_table (void)
8396 g_assert_not_reached ();
8401 mono_lookup_internal_call (MonoMethod *method)
8406 int typelen = 0, mlen, siglen;
8408 #ifndef DISABLE_ICALL_TABLES
8409 const IcallTypeDesc *imap = NULL;
8412 g_assert (method != NULL);
8414 if (method->is_inflated)
8415 method = ((MonoMethodInflated *) method)->declaring;
8417 if (method->klass->nested_in) {
8418 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8422 mname [pos++] = '/';
8425 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8431 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8436 #ifndef DISABLE_ICALL_TABLES
8437 imap = find_class_icalls (mname);
8440 mname [typelen] = ':';
8441 mname [typelen + 1] = ':';
8443 mlen = strlen (method->name);
8444 memcpy (mname + typelen + 2, method->name, mlen);
8445 sigstart = mname + typelen + 2 + mlen;
8448 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8449 siglen = strlen (tmpsig);
8450 if (typelen + mlen + siglen + 6 > sizeof (mname))
8453 memcpy (sigstart + 1, tmpsig, siglen);
8454 sigstart [siglen + 1] = ')';
8455 sigstart [siglen + 2] = 0;
8460 res = g_hash_table_lookup (icall_hash, mname);
8462 mono_icall_unlock ();;
8465 /* try without signature */
8467 res = g_hash_table_lookup (icall_hash, mname);
8469 mono_icall_unlock ();
8473 #ifdef DISABLE_ICALL_TABLES
8474 mono_icall_unlock ();
8475 /* Fail only when the result is actually used */
8476 /* mono_marshal_get_native_wrapper () depends on this */
8477 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8478 return ves_icall_System_String_ctor_RedirectToCreateString;
8480 return no_icall_table;
8482 /* it wasn't found in the static call tables */
8484 mono_icall_unlock ();
8487 res = find_method_icall (imap, sigstart - mlen);
8489 mono_icall_unlock ();
8492 /* try _with_ signature */
8494 res = find_method_icall (imap, sigstart - mlen);
8496 mono_icall_unlock ();
8500 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8501 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8502 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8503 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8504 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");
8505 g_print ("If you see other errors or faults after this message they are probably related\n");
8506 g_print ("and you need to fix your mono install first.\n");
8508 mono_icall_unlock ();
8514 #ifdef ENABLE_ICALL_SYMBOL_MAP
8516 func_cmp (gconstpointer key, gconstpointer p)
8518 return (gsize)key - (gsize)*(gsize*)p;
8523 * mono_lookup_icall_symbol:
8525 * Given the icall METHOD, returns its C symbol.
8528 mono_lookup_icall_symbol (MonoMethod *m)
8530 #ifdef DISABLE_ICALL_TABLES
8531 g_assert_not_reached ();
8534 #ifdef ENABLE_ICALL_SYMBOL_MAP
8538 static gconstpointer *functions_sorted;
8539 static const char**symbols_sorted;
8540 static gboolean inited;
8545 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8546 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8547 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8548 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8549 /* Bubble sort the two arrays */
8553 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8554 if (functions_sorted [i] > functions_sorted [i + 1]) {
8557 tmp = functions_sorted [i];
8558 functions_sorted [i] = functions_sorted [i + 1];
8559 functions_sorted [i + 1] = tmp;
8560 tmp = symbols_sorted [i];
8561 symbols_sorted [i] = symbols_sorted [i + 1];
8562 symbols_sorted [i + 1] = tmp;
8569 func = mono_lookup_internal_call (m);
8572 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8576 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8578 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8579 g_assert_not_reached ();
8586 type_from_typename (char *type_name)
8588 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8590 if (!strcmp (type_name, "int"))
8591 klass = mono_defaults.int_class;
8592 else if (!strcmp (type_name, "ptr"))
8593 klass = mono_defaults.int_class;
8594 else if (!strcmp (type_name, "void"))
8595 klass = mono_defaults.void_class;
8596 else if (!strcmp (type_name, "int32"))
8597 klass = mono_defaults.int32_class;
8598 else if (!strcmp (type_name, "uint32"))
8599 klass = mono_defaults.uint32_class;
8600 else if (!strcmp (type_name, "int8"))
8601 klass = mono_defaults.sbyte_class;
8602 else if (!strcmp (type_name, "uint8"))
8603 klass = mono_defaults.byte_class;
8604 else if (!strcmp (type_name, "int16"))
8605 klass = mono_defaults.int16_class;
8606 else if (!strcmp (type_name, "uint16"))
8607 klass = mono_defaults.uint16_class;
8608 else if (!strcmp (type_name, "long"))
8609 klass = mono_defaults.int64_class;
8610 else if (!strcmp (type_name, "ulong"))
8611 klass = mono_defaults.uint64_class;
8612 else if (!strcmp (type_name, "float"))
8613 klass = mono_defaults.single_class;
8614 else if (!strcmp (type_name, "double"))
8615 klass = mono_defaults.double_class;
8616 else if (!strcmp (type_name, "object"))
8617 klass = mono_defaults.object_class;
8618 else if (!strcmp (type_name, "obj"))
8619 klass = mono_defaults.object_class;
8620 else if (!strcmp (type_name, "string"))
8621 klass = mono_defaults.string_class;
8622 else if (!strcmp (type_name, "bool"))
8623 klass = mono_defaults.boolean_class;
8624 else if (!strcmp (type_name, "boolean"))
8625 klass = mono_defaults.boolean_class;
8627 g_error ("%s", type_name);
8628 g_assert_not_reached ();
8630 return &klass->byval_arg;
8634 * LOCKING: Take the corlib image lock.
8636 MonoMethodSignature*
8637 mono_create_icall_signature (const char *sigstr)
8642 MonoMethodSignature *res, *res2;
8643 MonoImage *corlib = mono_defaults.corlib;
8645 mono_image_lock (corlib);
8646 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8647 mono_image_unlock (corlib);
8652 parts = g_strsplit (sigstr, " ", 256);
8661 res = mono_metadata_signature_alloc (corlib, len - 1);
8666 * Under windows, the default pinvoke calling convention is STDCALL but
8669 res->call_convention = MONO_CALL_C;
8672 res->ret = type_from_typename (parts [0]);
8673 for (i = 1; i < len; ++i) {
8674 res->params [i - 1] = type_from_typename (parts [i]);
8679 mono_image_lock (corlib);
8680 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8682 res = res2; /*Value is allocated in the image pool*/
8684 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8685 mono_image_unlock (corlib);
8691 mono_find_jit_icall_by_name (const char *name)
8693 MonoJitICallInfo *info;
8694 g_assert (jit_icall_hash_name);
8697 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8698 mono_icall_unlock ();
8703 mono_find_jit_icall_by_addr (gconstpointer addr)
8705 MonoJitICallInfo *info;
8706 g_assert (jit_icall_hash_addr);
8709 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8710 mono_icall_unlock ();
8716 * mono_get_jit_icall_info:
8718 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8719 * caller should access it while holding the icall lock.
8722 mono_get_jit_icall_info (void)
8724 return jit_icall_hash_name;
8728 * mono_lookup_jit_icall_symbol:
8730 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8733 mono_lookup_jit_icall_symbol (const char *name)
8735 MonoJitICallInfo *info;
8736 const char *res = NULL;
8739 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8741 res = info->c_symbol;
8742 mono_icall_unlock ();
8747 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8750 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8751 mono_icall_unlock ();
8755 * 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
8756 * icalls without wrappers in some cases.
8759 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8761 MonoJitICallInfo *info;
8768 if (!jit_icall_hash_name) {
8769 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8770 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8773 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8774 g_warning ("jit icall already defined \"%s\"\n", name);
8775 g_assert_not_reached ();
8778 info = g_new0 (MonoJitICallInfo, 1);
8783 info->c_symbol = c_symbol;
8784 info->no_raise = no_raise;
8787 info->wrapper = func;
8789 info->wrapper = NULL;
8792 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8793 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8795 mono_icall_unlock ();
8800 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8802 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);