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)
1316 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1327 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1329 MonoMethod **dest = (MonoMethod **)data;
1331 /* skip unmanaged frames */
1335 if (m->wrapper_type != MONO_WRAPPER_NONE)
1343 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1344 || (!strcmp (m->klass->name_space, "System"))))
1354 static MonoReflectionType *
1355 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1357 MonoMethod *m, *dest;
1359 MonoType *type = NULL;
1360 MonoAssembly *assembly = NULL;
1361 gboolean type_resolve = FALSE;
1362 MonoImage *rootimage = NULL;
1364 mono_error_init (error);
1367 * We must compute the calling assembly as type loading must happen under a metadata context.
1368 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1369 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1371 m = mono_method_get_last_managed ();
1374 /* Ugly hack: type_from_parsed_name is called from
1375 * System.Type.internal_from_name, which is called most
1376 * directly from System.Type.GetType(string,bool,bool) but
1377 * also indirectly from places such as
1378 * System.Type.GetType(string,func,func) (via
1379 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1380 * so we need to skip over all of those to find the true caller.
1382 * It would be nice if we had stack marks.
1384 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1390 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1391 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1392 * to crash. This only seems to happen in some strange remoting
1393 * scenarios and I was unable to figure out what's happening there.
1394 * Dec 10, 2005 - Martin.
1398 assembly = dest->klass->image->assembly;
1399 type_resolve = TRUE;
1400 rootimage = assembly->image;
1402 g_warning (G_STRLOC);
1405 if (info->assembly.name)
1406 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1409 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1410 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1411 return_val_if_nok (error, NULL);
1415 // Say we're looking for System.Generic.Dict<int, Local>
1416 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1417 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1418 // is messed up when we go to construct the Local as the type arg...
1420 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1421 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1422 if (!info->assembly.name && !type) {
1424 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1425 return_val_if_nok (error, NULL);
1427 if (assembly && !type && type_resolve) {
1428 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1429 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1430 return_val_if_nok (error, NULL);
1436 return mono_type_get_object_checked (mono_domain_get (), type, error);
1439 ICALL_EXPORT MonoReflectionType*
1440 ves_icall_System_Type_internal_from_name (MonoString *name,
1441 MonoBoolean throwOnError,
1442 MonoBoolean ignoreCase)
1445 char *str = mono_string_to_utf8 (name);
1446 MonoTypeNameParse info;
1447 MonoReflectionType *type;
1450 parsedOk = mono_reflection_parse_type (str, &info);
1452 /* mono_reflection_parse_type() mangles the string */
1454 mono_reflection_free_type_info (&info);
1456 mono_error_init (&error);
1457 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1458 mono_error_set_pending_exception (&error);
1464 type = type_from_parsed_name (&info, ignoreCase, &error);
1466 mono_reflection_free_type_info (&info);
1469 if (!mono_error_ok (&error)) {
1471 mono_error_set_pending_exception (&error);
1473 mono_error_cleanup (&error);
1478 MonoException *e = NULL;
1481 e = mono_get_exception_type_load (name, NULL);
1484 mono_set_pending_exception (e);
1493 ICALL_EXPORT MonoReflectionType*
1494 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1497 MonoReflectionType *ret;
1498 MonoDomain *domain = mono_domain_get ();
1500 ret = mono_type_get_object_checked (domain, handle, &error);
1501 mono_error_raise_exception (&error);
1506 /* System.TypeCode */
1525 TYPECODE_STRING = 18
1528 ICALL_EXPORT guint32
1529 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1531 int t = type->type->type;
1533 if (type->type->byref)
1534 return TYPECODE_OBJECT;
1538 case MONO_TYPE_VOID:
1539 return TYPECODE_OBJECT;
1540 case MONO_TYPE_BOOLEAN:
1541 return TYPECODE_BOOLEAN;
1543 return TYPECODE_BYTE;
1545 return TYPECODE_SBYTE;
1547 return TYPECODE_UINT16;
1549 return TYPECODE_INT16;
1550 case MONO_TYPE_CHAR:
1551 return TYPECODE_CHAR;
1555 return TYPECODE_OBJECT;
1557 return TYPECODE_UINT32;
1559 return TYPECODE_INT32;
1561 return TYPECODE_UINT64;
1563 return TYPECODE_INT64;
1565 return TYPECODE_SINGLE;
1567 return TYPECODE_DOUBLE;
1568 case MONO_TYPE_VALUETYPE: {
1569 MonoClass *klass = type->type->data.klass;
1571 if (klass->enumtype) {
1572 t = mono_class_enum_basetype (klass)->type;
1574 } else if (mono_is_corlib_image (klass->image)) {
1575 if (strcmp (klass->name_space, "System") == 0) {
1576 if (strcmp (klass->name, "Decimal") == 0)
1577 return TYPECODE_DECIMAL;
1578 else if (strcmp (klass->name, "DateTime") == 0)
1579 return TYPECODE_DATETIME;
1582 return TYPECODE_OBJECT;
1584 case MONO_TYPE_STRING:
1585 return TYPECODE_STRING;
1586 case MONO_TYPE_SZARRAY:
1587 case MONO_TYPE_ARRAY:
1588 case MONO_TYPE_OBJECT:
1590 case MONO_TYPE_MVAR:
1591 case MONO_TYPE_TYPEDBYREF:
1592 return TYPECODE_OBJECT;
1593 case MONO_TYPE_CLASS:
1595 MonoClass *klass = type->type->data.klass;
1596 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1597 if (strcmp (klass->name, "DBNull") == 0)
1598 return TYPECODE_DBNULL;
1601 return TYPECODE_OBJECT;
1602 case MONO_TYPE_GENERICINST:
1603 return TYPECODE_OBJECT;
1605 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1611 mono_type_is_primitive (MonoType *type)
1613 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1614 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1618 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1620 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1621 return mono_class_enum_basetype (type->data.klass);
1622 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1623 return mono_class_enum_basetype (type->data.generic_class->container_class);
1627 ICALL_EXPORT guint32
1628 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1633 g_assert (type != NULL);
1635 klass = mono_class_from_mono_type (type->type);
1636 klassc = mono_class_from_mono_type (c->type);
1638 if (type->type->byref ^ c->type->byref)
1641 if (type->type->byref) {
1642 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1643 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1645 klass = mono_class_from_mono_type (t);
1646 klassc = mono_class_from_mono_type (ot);
1648 if (mono_type_is_primitive (t)) {
1649 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1650 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1651 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1652 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1653 return t->type == ot->type;
1655 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1658 if (klass->valuetype)
1659 return klass == klassc;
1660 return klass->valuetype == klassc->valuetype;
1663 return mono_class_is_assignable_from (klass, klassc);
1666 ICALL_EXPORT guint32
1667 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1670 MonoClass *klass = mono_class_from_mono_type (type->type);
1671 mono_class_init_checked (klass, &error);
1672 if (!is_ok (&error)) {
1673 mono_error_set_pending_exception (&error);
1676 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1677 mono_error_set_pending_exception (&error);
1681 ICALL_EXPORT guint32
1682 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1684 MonoClass *klass = mono_class_from_mono_type (type->type);
1685 return klass->flags;
1688 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1689 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1692 MonoClass *klass = field->field->parent;
1693 MonoMarshalType *info;
1697 if (klass->generic_container ||
1698 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1701 ftype = mono_field_get_type (field->field);
1702 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1705 info = mono_marshal_load_type_info (klass);
1707 for (i = 0; i < info->num_fields; ++i) {
1708 if (info->fields [i].field == field->field) {
1709 if (!info->fields [i].mspec)
1712 MonoReflectionMarshalAsAttribute* obj;
1713 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1714 if (!mono_error_ok (&error))
1715 mono_error_set_pending_exception (&error);
1724 ICALL_EXPORT MonoReflectionField*
1725 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1728 gboolean found = FALSE;
1735 klass = handle->parent;
1737 klass = mono_class_from_mono_type (type);
1739 /* Check that the field belongs to the class */
1740 for (k = klass; k; k = k->parent) {
1741 if (k == handle->parent) {
1748 /* The managed code will throw the exception */
1752 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1753 mono_error_raise_exception (&error);
1757 ICALL_EXPORT MonoArray*
1758 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1761 MonoType *type = mono_field_get_type_checked (field->field, &error);
1764 if (!mono_error_ok (&error)) {
1765 mono_error_set_pending_exception (&error);
1769 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1770 mono_error_raise_exception (&error);
1775 vell_icall_get_method_attributes (MonoMethod *method)
1777 return method->flags;
1781 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1784 MonoReflectionType *rt;
1785 MonoDomain *domain = mono_domain_get ();
1786 MonoMethodSignature* sig;
1788 sig = mono_method_signature_checked (method, &error);
1789 if (!mono_error_ok (&error)) {
1790 mono_error_set_pending_exception (&error);
1794 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1795 if (!mono_error_ok (&error)) {
1796 mono_error_set_pending_exception (&error);
1800 MONO_STRUCT_SETREF (info, parent, rt);
1802 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1803 if (!mono_error_ok (&error)) {
1804 mono_error_set_pending_exception (&error);
1808 MONO_STRUCT_SETREF (info, ret, rt);
1810 info->attrs = method->flags;
1811 info->implattrs = method->iflags;
1812 if (sig->call_convention == MONO_CALL_DEFAULT)
1813 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1815 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1820 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1823 ICALL_EXPORT MonoArray*
1824 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1827 MonoDomain *domain = mono_domain_get ();
1829 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1830 mono_error_set_pending_exception (&error);
1834 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1835 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1838 MonoDomain *domain = mono_domain_get ();
1839 MonoReflectionMarshalAsAttribute* res = NULL;
1840 MonoMarshalSpec **mspecs;
1843 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1844 mono_method_get_marshal_info (method, mspecs);
1847 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1848 if (!mono_error_ok (&error)) {
1849 mono_error_set_pending_exception (&error);
1854 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1856 mono_metadata_free_marshal_spec (mspecs [i]);
1863 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1865 MonoClass *parent = field->field->parent;
1866 if (!parent->size_inited)
1867 mono_class_init (parent);
1868 mono_class_setup_fields_locking (parent);
1870 return field->field->offset - sizeof (MonoObject);
1873 ICALL_EXPORT MonoReflectionType*
1874 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1877 MonoReflectionType *ret;
1880 parent = declaring? field->field->parent: field->klass;
1882 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1883 mono_error_raise_exception (&error);
1889 ICALL_EXPORT MonoObject *
1890 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1893 MonoClass *fklass = field->klass;
1894 MonoClassField *cf = field->field;
1895 MonoDomain *domain = mono_object_domain (field);
1897 if (fklass->image->assembly->ref_only) {
1898 mono_set_pending_exception (mono_get_exception_invalid_operation (
1899 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1903 if (mono_security_core_clr_enabled () &&
1904 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1905 mono_error_set_pending_exception (&error);
1909 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1910 mono_error_set_pending_exception (&error);
1915 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1918 MonoClassField *cf = field->field;
1922 if (field->klass->image->assembly->ref_only) {
1923 mono_set_pending_exception (mono_get_exception_invalid_operation (
1924 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1928 if (mono_security_core_clr_enabled () &&
1929 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1930 mono_error_set_pending_exception (&error);
1934 type = mono_field_get_type_checked (cf, &error);
1935 if (!mono_error_ok (&error)) {
1936 mono_error_set_pending_exception (&error);
1940 v = (gchar *) value;
1942 switch (type->type) {
1945 case MONO_TYPE_BOOLEAN:
1948 case MONO_TYPE_CHAR:
1957 case MONO_TYPE_VALUETYPE:
1960 v += sizeof (MonoObject);
1962 case MONO_TYPE_STRING:
1963 case MONO_TYPE_OBJECT:
1964 case MONO_TYPE_CLASS:
1965 case MONO_TYPE_ARRAY:
1966 case MONO_TYPE_SZARRAY:
1969 case MONO_TYPE_GENERICINST: {
1970 MonoGenericClass *gclass = type->data.generic_class;
1971 g_assert (!gclass->context.class_inst->is_open);
1973 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1974 MonoClass *nklass = mono_class_from_mono_type (type);
1975 MonoObject *nullable;
1978 * Convert the boxed vtype into a Nullable structure.
1979 * This is complicated by the fact that Nullables have
1980 * a variable structure.
1982 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1983 if (!mono_error_ok (&error)) {
1984 mono_error_set_pending_exception (&error);
1988 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1990 v = (gchar *)mono_object_unbox (nullable);
1993 if (gclass->container_class->valuetype && (v != NULL))
1994 v += sizeof (MonoObject);
1998 g_error ("type 0x%x not handled in "
1999 "ves_icall_FieldInfo_SetValueInternal", type->type);
2004 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2005 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2006 if (!is_ok (&error)) {
2007 mono_error_set_pending_exception (&error);
2010 if (!vtable->initialized) {
2011 if (!mono_runtime_class_init_full (vtable, &error)) {
2012 mono_error_set_pending_exception (&error);
2016 mono_field_static_set_value (vtable, cf, v);
2018 mono_field_set_value (obj, cf, v);
2023 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2032 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2033 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2037 if (MONO_TYPE_IS_REFERENCE (f->type))
2038 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2040 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2043 ICALL_EXPORT MonoObject *
2044 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2046 MonoObject *o = NULL;
2047 MonoClassField *field = rfield->field;
2049 MonoDomain *domain = mono_object_domain (rfield);
2051 MonoTypeEnum def_type;
2052 const char *def_value;
2056 mono_class_init (field->parent);
2058 t = mono_field_get_type_checked (field, &error);
2059 if (!mono_error_ok (&error)) {
2060 mono_error_set_pending_exception (&error);
2064 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2065 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2069 if (image_is_dynamic (field->parent->image)) {
2070 MonoClass *klass = field->parent;
2071 int fidx = field - klass->fields;
2073 g_assert (fidx >= 0 && fidx < klass->field.count);
2074 g_assert (klass->ext);
2075 g_assert (klass->ext->field_def_values);
2076 def_type = klass->ext->field_def_values [fidx].def_type;
2077 def_value = klass->ext->field_def_values [fidx].data;
2078 if (def_type == MONO_TYPE_END) {
2079 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2083 def_value = mono_class_get_field_default_value (field, &def_type);
2084 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2086 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2091 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2095 case MONO_TYPE_BOOLEAN:
2098 case MONO_TYPE_CHAR:
2106 case MONO_TYPE_R8: {
2109 /* boxed value type */
2110 t = g_new0 (MonoType, 1);
2112 klass = mono_class_from_mono_type (t);
2114 o = mono_object_new_checked (domain, klass, &error);
2115 if (!mono_error_ok (&error)) {
2116 mono_error_set_pending_exception (&error);
2119 v = ((gchar *) o) + sizeof (MonoObject);
2120 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2123 case MONO_TYPE_STRING:
2124 case MONO_TYPE_CLASS:
2125 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2128 g_assert_not_reached ();
2134 ICALL_EXPORT MonoReflectionType*
2135 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2138 MonoReflectionType *ret;
2141 type = mono_field_get_type_checked (ref_field->field, &error);
2142 if (!mono_error_ok (&error)) {
2143 mono_error_set_pending_exception (&error);
2147 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2148 if (!mono_error_ok (&error)) {
2149 mono_error_set_pending_exception (&error);
2156 /* From MonoProperty.cs */
2158 PInfo_Attributes = 1,
2159 PInfo_GetMethod = 1 << 1,
2160 PInfo_SetMethod = 1 << 2,
2161 PInfo_ReflectedType = 1 << 3,
2162 PInfo_DeclaringType = 1 << 4,
2167 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2170 MonoReflectionType *rt;
2171 MonoReflectionMethod *rm;
2172 MonoDomain *domain = mono_object_domain (property);
2173 const MonoProperty *pproperty = property->property;
2175 if ((req_info & PInfo_ReflectedType) != 0) {
2176 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2177 mono_error_raise_exception (&error);
2179 MONO_STRUCT_SETREF (info, parent, rt);
2181 if ((req_info & PInfo_DeclaringType) != 0) {
2182 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2183 mono_error_raise_exception (&error);
2185 MONO_STRUCT_SETREF (info, declaring_type, rt);
2188 if ((req_info & PInfo_Name) != 0)
2189 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2191 if ((req_info & PInfo_Attributes) != 0)
2192 info->attrs = pproperty->attrs;
2194 if ((req_info & PInfo_GetMethod) != 0) {
2195 if (pproperty->get &&
2196 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2197 pproperty->get->klass == property->klass)) {
2198 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2199 mono_error_raise_exception (&error);
2204 MONO_STRUCT_SETREF (info, get, rm);
2206 if ((req_info & PInfo_SetMethod) != 0) {
2207 if (pproperty->set &&
2208 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2209 pproperty->set->klass == property->klass)) {
2210 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2211 mono_error_raise_exception (&error);
2216 MONO_STRUCT_SETREF (info, set, rm);
2219 * There may be other methods defined for properties, though, it seems they are not exposed
2220 * in the reflection API
2225 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2228 MonoReflectionType *rt;
2229 MonoReflectionMethod *rm;
2230 MonoDomain *domain = mono_object_domain (event);
2232 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2233 mono_error_raise_exception (&error);
2235 MONO_STRUCT_SETREF (info, reflected_type, rt);
2237 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2238 mono_error_raise_exception (&error);
2240 MONO_STRUCT_SETREF (info, declaring_type, rt);
2242 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2243 info->attrs = event->event->attrs;
2245 if (event->event->add) {
2246 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2247 mono_error_raise_exception (&error);
2252 MONO_STRUCT_SETREF (info, add_method, rm);
2254 if (event->event->remove) {
2255 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2256 mono_error_raise_exception (&error);
2261 MONO_STRUCT_SETREF (info, remove_method, rm);
2263 if (event->event->raise) {
2264 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2265 mono_error_raise_exception (&error);
2270 MONO_STRUCT_SETREF (info, raise_method, rm);
2272 #ifndef MONO_SMALL_CONFIG
2273 if (event->event->other) {
2275 while (event->event->other [n])
2277 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2279 for (i = 0; i < n; i++) {
2280 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2281 mono_error_raise_exception (&error);
2282 mono_array_setref (info->other_methods, i, rm);
2289 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2294 mono_class_setup_interfaces (klass, error);
2295 if (!mono_error_ok (error))
2298 for (i = 0; i < klass->interface_count; i++) {
2299 ic = klass->interfaces [i];
2300 g_hash_table_insert (ifaces, ic, ic);
2302 collect_interfaces (ic, ifaces, error);
2303 if (!mono_error_ok (error))
2309 MonoArray *iface_array;
2310 MonoGenericContext *context;
2314 } FillIfaceArrayData;
2317 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2319 MonoReflectionType *rt;
2320 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2321 MonoClass *ic = (MonoClass *)key;
2322 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2324 if (!mono_error_ok (data->error))
2327 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2328 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2329 if (!mono_error_ok (data->error))
2333 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2334 if (!mono_error_ok (data->error))
2337 mono_array_setref (data->iface_array, data->next_idx++, rt);
2340 mono_metadata_free_type (inflated);
2344 get_interfaces_hash (gconstpointer v1)
2346 MonoClass *k = (MonoClass*)v1;
2348 return k->type_token;
2351 ICALL_EXPORT MonoArray*
2352 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2355 MonoClass *klass = mono_class_from_mono_type (type->type);
2357 FillIfaceArrayData data = { 0 };
2360 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2362 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2363 data.context = mono_class_get_context (klass);
2364 klass = klass->generic_class->container_class;
2367 for (parent = klass; parent; parent = parent->parent) {
2368 mono_class_setup_interfaces (parent, &error);
2369 if (!mono_error_ok (&error))
2371 collect_interfaces (parent, iface_hash, &error);
2372 if (!mono_error_ok (&error))
2376 data.error = &error;
2377 data.domain = mono_object_domain (type);
2379 len = g_hash_table_size (iface_hash);
2381 g_hash_table_destroy (iface_hash);
2382 if (!data.domain->empty_types)
2383 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2384 return data.domain->empty_types;
2387 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2388 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2389 if (!mono_error_ok (&error))
2392 g_hash_table_destroy (iface_hash);
2393 return data.iface_array;
2396 g_hash_table_destroy (iface_hash);
2397 mono_error_set_pending_exception (&error);
2402 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2404 gboolean variance_used;
2405 MonoClass *klass = mono_class_from_mono_type (type->type);
2406 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2407 MonoReflectionMethod *member;
2410 int i = 0, len, ioffset;
2414 mono_class_init_checked (klass, &error);
2415 mono_error_raise_exception (&error);
2416 mono_class_init_checked (iclass, &error);
2417 mono_error_raise_exception (&error);
2419 mono_class_setup_vtable (klass);
2421 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2425 len = mono_class_num_methods (iclass);
2426 domain = mono_object_domain (type);
2427 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2428 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2430 while ((method = mono_class_get_methods (iclass, &iter))) {
2431 member = mono_method_get_object_checked (domain, method, iclass, &error);
2432 mono_error_raise_exception (&error);
2433 mono_array_setref (*methods, i, member);
2434 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2435 mono_error_raise_exception (&error);
2436 mono_array_setref (*targets, i, member);
2443 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2446 MonoClass *klass = mono_class_from_mono_type (type->type);
2448 mono_class_init_checked (klass, &error);
2449 mono_error_raise_exception (&error);
2451 if (image_is_dynamic (klass->image)) {
2452 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2453 *packing = tb->packing_size;
2454 *size = tb->class_size;
2456 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2460 ICALL_EXPORT MonoReflectionType*
2461 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2464 MonoReflectionType *ret;
2467 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2468 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2469 mono_error_raise_exception (&error);
2474 klass = mono_class_from_mono_type (type->type);
2475 mono_class_init_checked (klass, &error);
2476 mono_error_raise_exception (&error);
2478 // GetElementType should only return a type for:
2479 // Array Pointer PassedByRef
2480 if (type->type->byref)
2481 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2482 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2483 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2484 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2485 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2489 mono_error_raise_exception (&error);
2494 ICALL_EXPORT MonoReflectionType*
2495 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2498 MonoReflectionType *ret;
2500 if (type->type->byref)
2503 MonoClass *klass = mono_class_from_mono_type (type->type);
2507 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2508 mono_error_raise_exception (&error);
2513 ICALL_EXPORT MonoBoolean
2514 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2516 return type->type->type == MONO_TYPE_PTR;
2519 ICALL_EXPORT MonoBoolean
2520 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2522 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)));
2525 ICALL_EXPORT MonoBoolean
2526 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2528 return type->type->byref;
2531 ICALL_EXPORT MonoBoolean
2532 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2535 MonoClass *klass = mono_class_from_mono_type (type->type);
2536 mono_class_init_checked (klass, &error);
2537 mono_error_raise_exception (&error);
2539 return mono_class_is_com_object (klass);
2542 ICALL_EXPORT guint32
2543 ves_icall_reflection_get_token (MonoObject* obj)
2546 guint32 result = mono_reflection_get_token_checked (obj, &error);
2547 mono_error_set_pending_exception (&error);
2551 ICALL_EXPORT MonoReflectionModule*
2552 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2555 MonoReflectionModule *result = NULL;
2556 MonoClass *klass = mono_class_from_mono_type (type->type);
2557 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2558 if (!mono_error_ok (&error))
2559 mono_error_set_pending_exception (&error);
2563 ICALL_EXPORT MonoReflectionAssembly*
2564 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2567 MonoDomain *domain = mono_domain_get ();
2568 MonoClass *klass = mono_class_from_mono_type (type->type);
2569 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2571 mono_error_set_pending_exception (&error);
2575 ICALL_EXPORT MonoReflectionType*
2576 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2579 MonoReflectionType *ret;
2580 MonoDomain *domain = mono_domain_get ();
2583 if (type->type->byref)
2585 if (type->type->type == MONO_TYPE_VAR) {
2586 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2587 klass = param ? param->owner.klass : NULL;
2588 } else if (type->type->type == MONO_TYPE_MVAR) {
2589 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2590 klass = param ? param->owner.method->klass : NULL;
2592 klass = mono_class_from_mono_type (type->type)->nested_in;
2598 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2599 mono_error_raise_exception (&error);
2604 ICALL_EXPORT MonoString*
2605 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2607 MonoDomain *domain = mono_domain_get ();
2608 MonoClass *klass = mono_class_from_mono_type (type->type);
2610 if (type->type->byref) {
2611 char *n = g_strdup_printf ("%s&", klass->name);
2612 MonoString *res = mono_string_new (domain, n);
2618 return mono_string_new (domain, klass->name);
2622 ICALL_EXPORT MonoString*
2623 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2625 MonoDomain *domain = mono_domain_get ();
2626 MonoClass *klass = mono_class_from_mono_type (type->type);
2628 while (klass->nested_in)
2629 klass = klass->nested_in;
2631 if (klass->name_space [0] == '\0')
2634 return mono_string_new (domain, klass->name_space);
2638 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2642 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2643 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2647 klass = mono_class_from_mono_type (type->type);
2653 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2656 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2660 ICALL_EXPORT MonoArray*
2661 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2664 MonoReflectionType *rt;
2666 MonoClass *klass, *pklass;
2667 MonoDomain *domain = mono_object_domain (type);
2670 klass = mono_class_from_mono_type (type->type);
2672 if (klass->generic_container) {
2673 MonoGenericContainer *container = klass->generic_container;
2674 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2675 for (i = 0; i < container->type_argc; ++i) {
2676 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2678 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2679 mono_error_raise_exception (&error);
2681 mono_array_setref (res, i, rt);
2683 } else if (klass->generic_class) {
2684 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2685 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2686 for (i = 0; i < inst->type_argc; ++i) {
2687 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2688 mono_error_raise_exception (&error);
2690 mono_array_setref (res, i, rt);
2698 ICALL_EXPORT gboolean
2699 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2703 if (!IS_MONOTYPE (type))
2706 if (type->type->byref)
2709 klass = mono_class_from_mono_type (type->type);
2710 return klass->generic_container != NULL;
2713 ICALL_EXPORT MonoReflectionType*
2714 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2717 MonoReflectionType *ret;
2720 if (type->type->byref)
2723 klass = mono_class_from_mono_type (type->type);
2725 if (klass->generic_container) {
2726 return type; /* check this one */
2728 if (klass->generic_class) {
2729 MonoClass *generic_class = klass->generic_class->container_class;
2732 tb = mono_class_get_ref_info (generic_class);
2734 if (generic_class->wastypebuilder && tb)
2735 return (MonoReflectionType *)tb;
2737 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2738 mono_error_raise_exception (&error);
2746 ICALL_EXPORT MonoReflectionType*
2747 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2750 MonoReflectionType *ret;
2752 MonoType *geninst, **types;
2755 g_assert (IS_MONOTYPE (type));
2756 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2757 mono_error_raise_exception (&error);
2759 count = mono_array_length (type_array);
2760 types = g_new0 (MonoType *, count);
2762 for (i = 0; i < count; i++) {
2763 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2764 types [i] = t->type;
2767 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2770 mono_error_set_pending_exception (&error);
2774 klass = mono_class_from_mono_type (geninst);
2776 /*we might inflate to the GTD*/
2777 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2778 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2782 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2783 mono_error_raise_exception (&error);
2788 ICALL_EXPORT gboolean
2789 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2793 if (!IS_MONOTYPE (type))
2796 if (type->type->byref)
2799 klass = mono_class_from_mono_type (type->type);
2800 return klass->generic_class != NULL || klass->generic_container != NULL;
2804 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2806 if (!IS_MONOTYPE (type))
2809 if (is_generic_parameter (type->type))
2810 return mono_type_get_generic_param_num (type->type);
2814 ICALL_EXPORT GenericParameterAttributes
2815 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2817 g_assert (IS_MONOTYPE (type));
2818 g_assert (is_generic_parameter (type->type));
2819 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2822 ICALL_EXPORT MonoArray *
2823 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2826 MonoReflectionType *rt;
2827 MonoGenericParamInfo *param_info;
2833 g_assert (IS_MONOTYPE (type));
2835 domain = mono_object_domain (type);
2836 param_info = mono_generic_param_info (type->type->data.generic_param);
2837 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2840 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2841 for (i = 0; i < count; i++) {
2842 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2843 mono_error_raise_exception (&error);
2845 mono_array_setref (res, i, rt);
2852 ICALL_EXPORT MonoBoolean
2853 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2855 return is_generic_parameter (type->type);
2858 ICALL_EXPORT MonoBoolean
2859 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2861 return is_generic_parameter (tb->type.type);
2865 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2866 MonoReflectionType *t)
2868 enumtype->type = t->type;
2871 ICALL_EXPORT MonoReflectionMethod*
2872 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2873 MonoReflectionMethod* generic)
2880 MonoReflectionMethod *ret = NULL;
2882 domain = ((MonoObject *)type)->vtable->domain;
2884 klass = mono_class_from_mono_type (type->type);
2885 mono_class_init_checked (klass, &error);
2886 mono_error_raise_exception (&error);
2889 while ((method = mono_class_get_methods (klass, &iter))) {
2890 if (method->token == generic->method->token) {
2891 ret = mono_method_get_object_checked (domain, method, klass, &error);
2892 mono_error_raise_exception (&error);
2899 ICALL_EXPORT MonoReflectionMethod *
2900 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2903 MonoType *type = ref_type->type;
2905 MonoReflectionMethod *ret = NULL;
2907 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2908 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2911 if (type->type == MONO_TYPE_VAR)
2914 method = mono_type_get_generic_param_owner (type)->owner.method;
2917 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2918 if (!mono_error_ok (&error))
2919 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2923 ICALL_EXPORT MonoBoolean
2924 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2926 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2930 ICALL_EXPORT MonoBoolean
2931 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2933 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2938 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2940 MonoDomain *domain = mono_domain_get ();
2941 MonoImage *image = method->method->klass->image;
2942 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2943 MonoTableInfo *tables = image->tables;
2944 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2945 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2946 guint32 im_cols [MONO_IMPLMAP_SIZE];
2947 guint32 scope_token;
2948 const char *import = NULL;
2949 const char *scope = NULL;
2951 if (image_is_dynamic (image)) {
2952 MonoReflectionMethodAux *method_aux =
2953 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2955 import = method_aux->dllentry;
2956 scope = method_aux->dll;
2959 if (!import || !scope) {
2960 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2965 if (piinfo->implmap_idx) {
2966 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2968 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2969 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2970 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2971 scope = mono_metadata_string_heap (image, scope_token);
2975 *flags = piinfo->piflags;
2976 *entry_point = mono_string_new (domain, import);
2977 *dll_name = mono_string_new (domain, scope);
2980 ICALL_EXPORT MonoReflectionMethod *
2981 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2983 MonoMethodInflated *imethod;
2985 MonoReflectionMethod *ret = NULL;
2988 if (method->method->is_generic)
2991 if (!method->method->is_inflated)
2994 imethod = (MonoMethodInflated *) method->method;
2996 result = imethod->declaring;
2997 /* Not a generic method. */
2998 if (!result->is_generic)
3001 if (image_is_dynamic (method->method->klass->image)) {
3002 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3003 MonoReflectionMethod *res;
3006 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3007 * the dynamic case as well ?
3009 mono_image_lock ((MonoImage*)image);
3010 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3011 mono_image_unlock ((MonoImage*)image);
3017 if (imethod->context.class_inst) {
3018 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3019 /*Generic methods gets the context of the GTD.*/
3020 if (mono_class_get_context (klass)) {
3021 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3022 if (!mono_error_ok (&error))
3027 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3029 if (!mono_error_ok (&error))
3030 mono_error_set_pending_exception (&error);
3034 ICALL_EXPORT gboolean
3035 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3037 return mono_method_signature (method->method)->generic_param_count != 0;
3040 ICALL_EXPORT gboolean
3041 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3043 return method->method->is_generic;
3046 ICALL_EXPORT MonoArray*
3047 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3050 MonoReflectionType *rt;
3055 domain = mono_object_domain (method);
3057 if (method->method->is_inflated) {
3058 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3061 count = inst->type_argc;
3062 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3064 for (i = 0; i < count; i++) {
3065 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3066 mono_error_raise_exception (&error);
3068 mono_array_setref (res, i, rt);
3075 count = mono_method_signature (method->method)->generic_param_count;
3076 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3078 for (i = 0; i < count; i++) {
3079 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3080 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3081 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3083 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3084 mono_error_raise_exception (&error);
3086 mono_array_setref (res, i, rt);
3092 ICALL_EXPORT MonoObject *
3093 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3097 * Invoke from reflection is supposed to always be a virtual call (the API
3098 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3099 * greater flexibility.
3101 MonoMethod *m = method->method;
3102 MonoMethodSignature *sig = mono_method_signature (m);
3105 void *obj = this_arg;
3109 if (mono_security_core_clr_enabled () &&
3110 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3111 mono_error_set_pending_exception (&error);
3115 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3116 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3117 mono_error_cleanup (&error); /* FIXME does this make sense? */
3118 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3123 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3124 if (!is_ok (&error)) {
3125 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3128 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3129 char *target_name = mono_type_get_full_name (m->klass);
3130 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3131 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3133 g_free (target_name);
3137 m = mono_object_get_virtual_method (this_arg, m);
3138 /* must pass the pointer to the value for valuetype methods */
3139 if (m->klass->valuetype)
3140 obj = mono_object_unbox (this_arg);
3141 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3142 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3147 if (sig->ret->byref) {
3148 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"));
3152 pcount = params? mono_array_length (params): 0;
3153 if (pcount != sig->param_count) {
3154 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3158 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3159 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."));
3163 image = m->klass->image;
3164 if (image->assembly->ref_only) {
3165 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."));
3169 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3170 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3174 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3178 intptr_t *lower_bounds;
3179 pcount = mono_array_length (params);
3180 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3181 /* Note: the synthetized array .ctors have int32 as argument type */
3182 for (i = 0; i < pcount; ++i)
3183 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3185 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3186 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3187 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3188 if (!mono_error_ok (&error)) {
3189 mono_error_set_pending_exception (&error);
3193 for (i = 0; i < mono_array_length (arr); ++i) {
3194 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3195 if (!mono_error_ok (&error)) {
3196 mono_error_set_pending_exception (&error);
3199 mono_array_setref_fast (arr, i, subarray);
3201 return (MonoObject*)arr;
3204 if (m->klass->rank == pcount) {
3205 /* Only lengths provided. */
3206 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3207 if (!mono_error_ok (&error)) {
3208 mono_error_set_pending_exception (&error);
3212 return (MonoObject*)arr;
3214 g_assert (pcount == (m->klass->rank * 2));
3215 /* The arguments are lower-bound-length pairs */
3216 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3218 for (i = 0; i < pcount / 2; ++i) {
3219 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3220 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3223 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3224 if (!mono_error_ok (&error)) {
3225 mono_error_set_pending_exception (&error);
3229 return (MonoObject*)arr;
3232 return mono_runtime_invoke_array (m, obj, params, NULL);
3235 #ifndef DISABLE_REMOTING
3236 ICALL_EXPORT MonoObject *
3237 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3240 MonoDomain *domain = mono_object_domain (method);
3241 MonoMethod *m = method->method;
3242 MonoMethodSignature *sig = mono_method_signature (m);
3243 MonoArray *out_args;
3245 int i, j, outarg_count = 0;
3247 if (m->klass == mono_defaults.object_class) {
3248 if (!strcmp (m->name, "FieldGetter")) {
3249 MonoClass *k = this_arg->vtable->klass;
3253 /* If this is a proxy, then it must be a CBO */
3254 if (k == mono_defaults.transparent_proxy_class) {
3255 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3256 this_arg = tp->rp->unwrapped_server;
3257 g_assert (this_arg);
3258 k = this_arg->vtable->klass;
3261 name = mono_array_get (params, MonoString *, 1);
3262 str = mono_string_to_utf8 (name);
3265 MonoClassField* field = mono_class_get_field_from_name (k, str);
3267 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3268 if (field_klass->valuetype) {
3269 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3270 mono_error_set_pending_exception (&error);
3271 /* fallthru to cleanup */
3273 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3275 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3276 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3277 mono_array_setref (out_args, 0, result);
3285 g_assert_not_reached ();
3287 } else if (!strcmp (m->name, "FieldSetter")) {
3288 MonoClass *k = this_arg->vtable->klass;
3294 /* If this is a proxy, then it must be a CBO */
3295 if (k == mono_defaults.transparent_proxy_class) {
3296 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3297 this_arg = tp->rp->unwrapped_server;
3298 g_assert (this_arg);
3299 k = this_arg->vtable->klass;
3302 name = mono_array_get (params, MonoString *, 1);
3303 str = mono_string_to_utf8 (name);
3306 MonoClassField* field = mono_class_get_field_from_name (k, str);
3308 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3309 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3311 if (field_klass->valuetype) {
3312 size = mono_type_size (field->type, &align);
3313 g_assert (size == mono_class_value_size (field_klass, NULL));
3314 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3316 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3319 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3320 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3330 g_assert_not_reached ();
3335 for (i = 0; i < mono_array_length (params); i++) {
3336 if (sig->params [i]->byref)
3340 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3342 /* handle constructors only for objects already allocated */
3343 if (!strcmp (method->method->name, ".ctor"))
3344 g_assert (this_arg);
3346 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3347 g_assert (!method->method->klass->valuetype);
3348 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3350 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3351 if (sig->params [i]->byref) {
3353 arg = mono_array_get (params, gpointer, i);
3354 mono_array_setref (out_args, j, arg);
3359 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3366 read_enum_value (const char *mem, int type)
3369 case MONO_TYPE_BOOLEAN:
3371 return *(guint8*)mem;
3373 return *(gint8*)mem;
3374 case MONO_TYPE_CHAR:
3376 return read16 (mem);
3378 return (gint16) read16 (mem);
3380 return read32 (mem);
3382 return (gint32) read32 (mem);
3385 return read64 (mem);
3387 g_assert_not_reached ();
3393 write_enum_value (char *mem, int type, guint64 value)
3397 case MONO_TYPE_I1: {
3398 guint8 *p = (guint8*)mem;
3403 case MONO_TYPE_I2: {
3404 guint16 *p = (guint16 *)mem;
3409 case MONO_TYPE_I4: {
3410 guint32 *p = (guint32 *)mem;
3415 case MONO_TYPE_I8: {
3416 guint64 *p = (guint64 *)mem;
3421 g_assert_not_reached ();
3426 ICALL_EXPORT MonoObject *
3427 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3435 domain = mono_object_domain (enumType);
3436 enumc = mono_class_from_mono_type (enumType->type);
3438 mono_class_init_checked (enumc, &error);
3439 mono_error_raise_exception (&error);
3441 etype = mono_class_enum_basetype (enumc);
3443 res = mono_object_new_checked (domain, enumc, &error);
3444 mono_error_raise_exception (&error);
3445 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3450 ICALL_EXPORT MonoBoolean
3451 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3453 int size = mono_class_value_size (a->vtable->klass, NULL);
3454 guint64 a_val = 0, b_val = 0;
3456 memcpy (&a_val, mono_object_unbox (a), size);
3457 memcpy (&b_val, mono_object_unbox (b), size);
3459 return (a_val & b_val) == b_val;
3462 ICALL_EXPORT MonoObject *
3463 ves_icall_System_Enum_get_value (MonoObject *eobj)
3475 g_assert (eobj->vtable->klass->enumtype);
3477 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3478 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3479 mono_error_raise_exception (&error);
3480 dst = (char *)res + sizeof (MonoObject);
3481 src = (char *)eobj + sizeof (MonoObject);
3482 size = mono_class_value_size (enumc, NULL);
3484 memcpy (dst, src, size);
3489 ICALL_EXPORT MonoReflectionType *
3490 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3493 MonoReflectionType *ret;
3497 klass = mono_class_from_mono_type (type->type);
3498 mono_class_init_checked (klass, &error);
3499 mono_error_raise_exception (&error);
3501 etype = mono_class_enum_basetype (klass);
3503 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3507 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3508 mono_error_raise_exception (&error);
3514 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3516 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3517 gpointer odata = (char *)other + sizeof (MonoObject);
3518 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3519 g_assert (basetype);
3524 if (eobj->vtable->klass != other->vtable->klass)
3527 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3528 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3529 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3532 return me > other ? 1 : -1; \
3535 switch (basetype->type) {
3537 COMPARE_ENUM_VALUES (guint8);
3539 COMPARE_ENUM_VALUES (gint8);
3540 case MONO_TYPE_CHAR:
3542 COMPARE_ENUM_VALUES (guint16);
3544 COMPARE_ENUM_VALUES (gint16);
3546 COMPARE_ENUM_VALUES (guint32);
3548 COMPARE_ENUM_VALUES (gint32);
3550 COMPARE_ENUM_VALUES (guint64);
3552 COMPARE_ENUM_VALUES (gint64);
3556 #undef COMPARE_ENUM_VALUES
3557 /* indicates that the enum was of an unsupported unerlying type */
3562 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3564 gpointer data = (char *)eobj + sizeof (MonoObject);
3565 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3566 g_assert (basetype);
3568 switch (basetype->type) {
3569 case MONO_TYPE_I1: {
3570 gint8 value = *((gint8*)data);
3571 return ((int)value ^ (int)value << 8);
3574 return *((guint8*)data);
3575 case MONO_TYPE_CHAR:
3577 return *((guint16*)data);
3579 case MONO_TYPE_I2: {
3580 gint16 value = *((gint16*)data);
3581 return ((int)(guint16)value | (((int)value) << 16));
3584 return *((guint32*)data);
3586 return *((gint32*)data);
3588 case MONO_TYPE_I8: {
3589 gint64 value = *((gint64*)data);
3590 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3593 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3598 ICALL_EXPORT MonoBoolean
3599 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3602 MonoDomain *domain = mono_object_domain (type);
3603 MonoClass *enumc = mono_class_from_mono_type (type->type);
3604 guint j = 0, nvalues;
3606 MonoClassField *field;
3608 guint64 field_value, previous_value = 0;
3609 gboolean sorted = TRUE;
3611 mono_class_init_checked (enumc, &error);
3612 mono_error_raise_exception (&error);
3614 if (!enumc->enumtype) {
3615 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3619 base_type = mono_class_enum_basetype (enumc)->type;
3621 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3622 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3623 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3626 while ((field = mono_class_get_fields (enumc, &iter))) {
3628 MonoTypeEnum def_type;
3630 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3632 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3634 if (mono_field_is_deleted (field))
3636 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3638 p = mono_class_get_field_default_value (field, &def_type);
3639 /* len = */ mono_metadata_decode_blob_size (p, &p);
3641 field_value = read_enum_value (p, base_type);
3642 mono_array_set (*values, guint64, j, field_value);
3644 if (previous_value > field_value)
3647 previous_value = field_value;
3655 BFLAGS_IgnoreCase = 1,
3656 BFLAGS_DeclaredOnly = 2,
3657 BFLAGS_Instance = 4,
3659 BFLAGS_Public = 0x10,
3660 BFLAGS_NonPublic = 0x20,
3661 BFLAGS_FlattenHierarchy = 0x40,
3662 BFLAGS_InvokeMethod = 0x100,
3663 BFLAGS_CreateInstance = 0x200,
3664 BFLAGS_GetField = 0x400,
3665 BFLAGS_SetField = 0x800,
3666 BFLAGS_GetProperty = 0x1000,
3667 BFLAGS_SetProperty = 0x2000,
3668 BFLAGS_ExactBinding = 0x10000,
3669 BFLAGS_SuppressChangeType = 0x20000,
3670 BFLAGS_OptionalParamBinding = 0x40000
3673 ICALL_EXPORT MonoArray*
3674 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3678 MonoClass *startklass, *klass, *refklass;
3683 char *utf8_name = NULL;
3684 int (*compare_func) (const char *s1, const char *s2) = NULL;
3685 MonoClassField *field;
3686 MonoPtrArray tmp_array;
3688 domain = ((MonoObject *)type)->vtable->domain;
3689 if (type->type->byref)
3690 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3692 klass = startklass = mono_class_from_mono_type (type->type);
3693 refklass = mono_class_from_mono_type (reftype->type);
3695 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3698 if (mono_class_has_failure (klass)) {
3699 mono_ptr_array_destroy (tmp_array);
3700 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3705 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3706 guint32 flags = mono_field_get_flags (field);
3708 if (mono_field_is_deleted_with_flags (field, flags))
3710 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3711 if (bflags & BFLAGS_Public)
3713 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3714 if (bflags & BFLAGS_NonPublic) {
3721 if (flags & FIELD_ATTRIBUTE_STATIC) {
3722 if (bflags & BFLAGS_Static)
3723 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3726 if (bflags & BFLAGS_Instance)
3734 if (utf8_name == NULL) {
3735 utf8_name = mono_string_to_utf8 (name);
3736 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3739 if (compare_func (mono_field_get_name (field), utf8_name))
3743 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3744 if (!mono_error_ok (&error))
3746 mono_ptr_array_append (tmp_array, member);
3748 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3751 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3753 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3754 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3756 mono_ptr_array_destroy (tmp_array);
3758 if (utf8_name != NULL)
3763 mono_ptr_array_destroy (tmp_array);
3764 mono_error_raise_exception (&error);
3765 g_assert_not_reached ();
3769 method_nonpublic (MonoMethod* method, gboolean start_klass)
3771 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3772 case METHOD_ATTRIBUTE_ASSEM:
3773 return (start_klass || mono_defaults.generic_ilist_class);
3774 case METHOD_ATTRIBUTE_PRIVATE:
3776 case METHOD_ATTRIBUTE_PUBLIC:
3784 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3787 MonoClass *startklass;
3791 /*FIXME, use MonoBitSet*/
3792 guint32 method_slots_default [8];
3793 guint32 *method_slots = NULL;
3794 int (*compare_func) (const char *s1, const char *s2) = NULL;
3796 array = g_ptr_array_new ();
3801 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3803 /* An optimization for calls made from Delegate:CreateDelegate () */
3804 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3805 method = mono_get_delegate_invoke (klass);
3808 g_ptr_array_add (array, method);
3812 mono_class_setup_methods (klass);
3813 mono_class_setup_vtable (klass);
3814 if (mono_class_has_failure (klass))
3817 if (is_generic_parameter (&klass->byval_arg))
3818 nslots = mono_class_get_vtable_size (klass->parent);
3820 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3821 if (nslots >= sizeof (method_slots_default) * 8) {
3822 method_slots = g_new0 (guint32, nslots / 32 + 1);
3824 method_slots = method_slots_default;
3825 memset (method_slots, 0, sizeof (method_slots_default));
3828 mono_class_setup_methods (klass);
3829 mono_class_setup_vtable (klass);
3830 if (mono_class_has_failure (klass))
3834 while ((method = mono_class_get_methods (klass, &iter))) {
3836 if (method->slot != -1) {
3837 g_assert (method->slot < nslots);
3838 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3840 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3841 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3844 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3846 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3847 if (bflags & BFLAGS_Public)
3849 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3855 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3856 if (bflags & BFLAGS_Static)
3857 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3860 if (bflags & BFLAGS_Instance)
3868 if (compare_func (name, method->name))
3873 g_ptr_array_add (array, method);
3875 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3877 if (method_slots != method_slots_default)
3878 g_free (method_slots);
3883 if (method_slots != method_slots_default)
3884 g_free (method_slots);
3885 g_ptr_array_free (array, TRUE);
3887 if (mono_class_has_failure (klass)) {
3888 *ex = mono_class_get_exception_for_failure (klass);
3890 *ex = mono_get_exception_execution_engine ("Unknown error");
3895 ICALL_EXPORT MonoArray*
3896 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3898 static MonoClass *MethodInfo_array;
3902 MonoVTable *array_vtable;
3903 MonoException *ex = NULL;
3904 const char *mname = NULL;
3905 GPtrArray *method_array;
3906 MonoClass *klass, *refklass;
3909 mono_error_init (&error);
3911 if (!MethodInfo_array) {
3912 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3913 mono_memory_barrier ();
3914 MethodInfo_array = klass;
3917 klass = mono_class_from_mono_type (type->type);
3918 refklass = mono_class_from_mono_type (reftype->type);
3919 domain = ((MonoObject *)type)->vtable->domain;
3920 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3921 if (!is_ok (&error)) {
3922 mono_error_set_pending_exception (&error);
3925 if (type->type->byref) {
3926 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3927 mono_error_set_pending_exception (&error);
3933 mname = mono_string_to_utf8 (name);
3935 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3936 g_free ((char*)mname);
3938 mono_set_pending_exception (ex);
3942 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3943 if (!mono_error_ok (&error)) {
3944 mono_error_set_pending_exception (&error);
3948 for (i = 0; i < method_array->len; ++i) {
3949 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3950 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3951 if (!mono_error_ok (&error))
3953 mono_array_setref (res, i, rm);
3957 g_ptr_array_free (method_array, TRUE);
3958 if (!mono_error_ok (&error))
3959 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3963 ICALL_EXPORT MonoArray*
3964 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3967 MonoClass *startklass, *klass, *refklass;
3972 gpointer iter = NULL;
3973 MonoPtrArray tmp_array;
3976 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3978 domain = ((MonoObject *)type)->vtable->domain;
3979 if (type->type->byref)
3980 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3981 klass = startklass = mono_class_from_mono_type (type->type);
3982 refklass = mono_class_from_mono_type (reftype->type);
3984 mono_class_setup_methods (klass);
3985 if (mono_class_has_failure (klass)) {
3986 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3991 while ((method = mono_class_get_methods (klass, &iter))) {
3993 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3995 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3996 if (bflags & BFLAGS_Public)
3999 if (bflags & BFLAGS_NonPublic)
4005 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4006 if (bflags & BFLAGS_Static)
4007 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4010 if (bflags & BFLAGS_Instance)
4016 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
4017 if (!mono_error_ok (&error)) {
4018 mono_error_set_pending_exception (&error);
4022 mono_ptr_array_append (tmp_array, member);
4025 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
4027 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4028 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4030 mono_ptr_array_destroy (tmp_array);
4036 property_hash (gconstpointer data)
4038 MonoProperty *prop = (MonoProperty*)data;
4040 return g_str_hash (prop->name);
4044 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
4046 if (method1->is_inflated)
4047 method1 = ((MonoMethodInflated*) method1)->declaring;
4048 if (method2->is_inflated)
4049 method2 = ((MonoMethodInflated*) method2)->declaring;
4051 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4055 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4057 // Properties are hide-by-name-and-signature
4058 if (!g_str_equal (prop1->name, prop2->name))
4061 /* If we see a property in a generic method, we want to
4062 compare the generic signatures, not the inflated signatures
4063 because we might conflate two properties that were
4067 public T this[T t] { getter { return t; } } // method 1
4068 public U this[U u] { getter { return u; } } // method 2
4071 If we see int Foo<int,int>::Item[int] we need to know if
4072 the indexer came from method 1 or from method 2, and we
4073 shouldn't conflate them. (Bugzilla 36283)
4075 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
4078 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4085 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4090 return method_nonpublic (accessor, start_klass);
4093 ICALL_EXPORT MonoArray*
4094 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4098 MonoClass *startklass, *klass;
4104 gchar *propname = NULL;
4105 int (*compare_func) (const char *s1, const char *s2) = NULL;
4107 GHashTable *properties = NULL;
4108 MonoPtrArray tmp_array;
4110 mono_error_init (&error);
4112 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4114 domain = ((MonoObject *)type)->vtable->domain;
4115 if (type->type->byref)
4116 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
4117 klass = startklass = mono_class_from_mono_type (type->type);
4120 propname = mono_string_to_utf8 (name);
4121 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4124 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4126 mono_class_setup_methods (klass);
4127 mono_class_setup_vtable (klass);
4128 if (mono_class_has_failure (klass))
4132 while ((prop = mono_class_get_properties (klass, &iter))) {
4138 flags = method->flags;
4141 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4142 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4143 if (bflags & BFLAGS_Public)
4145 } else if (bflags & BFLAGS_NonPublic) {
4146 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4147 property_accessor_nonpublic(prop->set, startklass == klass)) {
4154 if (flags & METHOD_ATTRIBUTE_STATIC) {
4155 if (bflags & BFLAGS_Static)
4156 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4159 if (bflags & BFLAGS_Instance)
4168 if (compare_func (propname, prop->name))
4172 if (g_hash_table_lookup (properties, prop))
4175 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4178 mono_ptr_array_append (tmp_array, pr);
4180 g_hash_table_insert (properties, prop, prop);
4182 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4185 g_hash_table_destroy (properties);
4188 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4189 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4190 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4192 mono_ptr_array_destroy (tmp_array);
4199 if (mono_class_has_failure (klass)) {
4200 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4205 g_hash_table_destroy (properties);
4208 mono_ptr_array_destroy (tmp_array);
4210 mono_error_set_pending_exception (&error);
4216 event_hash (gconstpointer data)
4218 MonoEvent *event = (MonoEvent*)data;
4220 return g_str_hash (event->name);
4224 event_equal (MonoEvent *event1, MonoEvent *event2)
4226 // Events are hide-by-name
4227 return g_str_equal (event1->name, event2->name);
4230 ICALL_EXPORT MonoArray*
4231 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4235 MonoClass *startklass, *klass;
4241 char *utf8_name = NULL;
4242 int (*compare_func) (const char *s1, const char *s2) = NULL;
4243 GHashTable *events = NULL;
4244 MonoPtrArray tmp_array;
4246 mono_error_init (&error);
4248 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4250 domain = mono_object_domain (type);
4251 if (type->type->byref)
4252 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4253 klass = startklass = mono_class_from_mono_type (type->type);
4255 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4257 mono_class_setup_methods (klass);
4258 mono_class_setup_vtable (klass);
4259 if (mono_class_has_failure (klass))
4263 while ((event = mono_class_get_events (klass, &iter))) {
4265 method = event->add;
4267 method = event->remove;
4269 method = event->raise;
4271 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4272 if (bflags & BFLAGS_Public)
4274 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4275 if (bflags & BFLAGS_NonPublic)
4280 if (bflags & BFLAGS_NonPublic)
4286 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4287 if (bflags & BFLAGS_Static)
4288 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4291 if (bflags & BFLAGS_Instance)
4296 if (bflags & BFLAGS_Instance)
4302 if (utf8_name == NULL) {
4303 utf8_name = mono_string_to_utf8 (name);
4304 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4307 if (compare_func (event->name, utf8_name))
4311 if (g_hash_table_lookup (events, event))
4314 MonoReflectionEvent *ev_obj;
4315 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4318 mono_ptr_array_append (tmp_array, ev_obj);
4320 g_hash_table_insert (events, event, event);
4322 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4325 g_hash_table_destroy (events);
4327 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4329 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4330 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4332 mono_ptr_array_destroy (tmp_array);
4334 if (utf8_name != NULL)
4340 if (mono_class_has_failure (klass)) {
4341 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4347 g_hash_table_destroy (events);
4348 if (utf8_name != NULL)
4351 mono_ptr_array_destroy (tmp_array);
4353 mono_error_set_pending_exception (&error);
4357 ICALL_EXPORT MonoArray*
4358 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4361 MonoReflectionType *rt;
4369 MonoPtrArray tmp_array;
4371 domain = ((MonoObject *)type)->vtable->domain;
4372 if (type->type->byref)
4373 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4374 klass = mono_class_from_mono_type (type->type);
4377 * If a nested type is generic, return its generic type definition.
4378 * Note that this means that the return value is essentially the set
4379 * of nested types of the generic type definition of @klass.
4381 * A note in MSDN claims that a generic type definition can have
4382 * nested types that aren't generic. In any case, the container of that
4383 * nested type would be the generic type definition.
4385 if (klass->generic_class)
4386 klass = klass->generic_class->container_class;
4388 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4390 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4392 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4393 if (bflags & BFLAGS_Public)
4396 if (bflags & BFLAGS_NonPublic)
4404 str = mono_string_to_utf8 (name);
4405 mono_identifier_unescape_type_name_chars (str);
4408 if (strcmp (nested->name, str))
4412 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4413 mono_error_raise_exception (&error);
4415 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4418 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4420 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4421 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4423 mono_ptr_array_destroy (tmp_array);
4430 ICALL_EXPORT MonoReflectionType*
4431 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4434 MonoReflectionType *ret;
4436 MonoType *type = NULL;
4437 MonoTypeNameParse info;
4438 gboolean type_resolve;
4440 /* On MS.NET, this does not fire a TypeResolve event */
4441 type_resolve = TRUE;
4442 str = mono_string_to_utf8 (name);
4443 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4444 if (!mono_reflection_parse_type (str, &info)) {
4446 mono_reflection_free_type_info (&info);
4448 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4451 /*g_print ("failed parse\n");*/
4455 if (info.assembly.name) {
4457 mono_reflection_free_type_info (&info);
4459 /* 1.0 and 2.0 throw different exceptions */
4460 if (mono_defaults.generic_ilist_class)
4461 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4463 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4469 if (module != NULL) {
4470 if (module->image) {
4471 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4472 if (!is_ok (&error)) {
4474 mono_reflection_free_type_info (&info);
4475 mono_error_set_pending_exception (&error);
4482 if (assembly_is_dynamic (assembly->assembly)) {
4483 /* Enumerate all modules */
4484 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4488 if (abuilder->modules) {
4489 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4490 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4491 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4492 if (!is_ok (&error)) {
4494 mono_reflection_free_type_info (&info);
4495 mono_error_set_pending_exception (&error);
4503 if (!type && abuilder->loaded_modules) {
4504 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4505 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4506 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4507 if (!is_ok (&error)) {
4509 mono_reflection_free_type_info (&info);
4510 mono_error_set_pending_exception (&error);
4519 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4520 if (!is_ok (&error)) {
4522 mono_reflection_free_type_info (&info);
4523 mono_error_set_pending_exception (&error);
4528 mono_reflection_free_type_info (&info);
4530 MonoException *e = NULL;
4533 e = mono_get_exception_type_load (name, NULL);
4536 mono_set_pending_exception (e);
4540 if (type->type == MONO_TYPE_CLASS) {
4541 MonoClass *klass = mono_type_get_class (type);
4543 /* need to report exceptions ? */
4544 if (throwOnError && mono_class_has_failure (klass)) {
4545 /* report SecurityException (or others) that occured when loading the assembly */
4546 MonoException *exc = mono_class_get_exception_for_failure (klass);
4547 mono_set_pending_exception (exc);
4552 /* g_print ("got it\n"); */
4553 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4554 mono_error_set_pending_exception (&error);
4560 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4563 gchar *shadow_ini_file;
4566 /* Check for shadow-copied assembly */
4567 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4568 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4570 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4571 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4577 g_free (shadow_ini_file);
4578 if (content != NULL) {
4581 *filename = content;
4588 ICALL_EXPORT MonoString *
4589 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4591 MonoDomain *domain = mono_object_domain (assembly);
4592 MonoAssembly *mass = assembly->assembly;
4593 MonoString *res = NULL;
4598 if (g_path_is_absolute (mass->image->name)) {
4599 absolute = g_strdup (mass->image->name);
4600 dirname = g_path_get_dirname (absolute);
4602 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4603 dirname = g_strdup (mass->basedir);
4606 replace_shadow_path (domain, dirname, &absolute);
4611 for (i = strlen (absolute) - 1; i >= 0; i--)
4612 if (absolute [i] == '\\')
4617 uri = g_filename_to_uri (absolute, NULL, NULL);
4619 const char *prepend = "file://";
4621 if (*absolute == '/' && *(absolute + 1) == '/') {
4624 prepend = "file:///";
4627 uri = g_strconcat (prepend, absolute, NULL);
4631 res = mono_string_new (domain, uri);
4638 ICALL_EXPORT MonoBoolean
4639 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4641 MonoAssembly *mass = assembly->assembly;
4643 return mass->in_gac;
4646 ICALL_EXPORT MonoReflectionAssembly*
4647 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4652 MonoImageOpenStatus status;
4653 MonoReflectionAssembly* result = NULL;
4655 name = mono_string_to_utf8 (mname);
4656 res = mono_assembly_load_with_partial_name (name, &status);
4662 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4664 mono_error_set_pending_exception (&error);
4668 ICALL_EXPORT MonoString *
4669 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4671 MonoDomain *domain = mono_object_domain (assembly);
4674 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4679 ICALL_EXPORT MonoBoolean
4680 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4682 return assembly->assembly->ref_only;
4685 ICALL_EXPORT MonoString *
4686 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4688 MonoDomain *domain = mono_object_domain (assembly);
4690 return mono_string_new (domain, assembly->assembly->image->version);
4693 ICALL_EXPORT MonoReflectionMethod*
4694 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4697 MonoReflectionMethod *res = NULL;
4700 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4704 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4705 if (!mono_error_ok (&error))
4708 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4711 if (!mono_error_ok (&error))
4712 mono_error_set_pending_exception (&error);
4716 ICALL_EXPORT MonoReflectionModule*
4717 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4720 MonoReflectionModule *result = NULL;
4721 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4722 if (!mono_error_ok (&error))
4723 mono_error_set_pending_exception (&error);
4727 ICALL_EXPORT MonoArray*
4728 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4730 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4731 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4735 for (i = 0; i < table->rows; ++i) {
4736 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4737 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4743 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4745 static MonoMethod *create_version = NULL;
4749 mono_error_init (error);
4752 if (!create_version) {
4753 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4754 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4755 g_assert (create_version);
4756 mono_method_desc_free (desc);
4762 args [3] = &revision;
4763 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4764 return_val_if_nok (error, NULL);
4766 mono_runtime_invoke_checked (create_version, result, args, error);
4767 return_val_if_nok (error, NULL);
4772 ICALL_EXPORT MonoArray*
4773 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4777 MonoDomain *domain = mono_object_domain (assembly);
4779 static MonoMethod *create_culture = NULL;
4780 MonoImage *image = assembly->assembly->image;
4784 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4787 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4789 if (count > 0 && !create_culture) {
4790 MonoMethodDesc *desc = mono_method_desc_new (
4791 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4792 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4793 g_assert (create_culture);
4794 mono_method_desc_free (desc);
4797 for (i = 0; i < count; i++) {
4798 MonoObject *version;
4799 MonoReflectionAssemblyName *aname;
4800 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4802 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4804 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4805 domain, mono_class_get_assembly_name_class (), &error);
4806 mono_error_raise_exception (&error);
4808 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4810 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4811 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4812 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4813 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4814 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4815 aname->versioncompat = 1; /* SameMachine (default) */
4816 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4818 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4819 mono_error_raise_exception (&error);
4821 MONO_OBJECT_SETREF (aname, version, version);
4823 if (create_culture) {
4825 MonoBoolean assembly_ref = 1;
4826 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4827 args [1] = &assembly_ref;
4829 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4830 mono_error_raise_exception (&error);
4832 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4835 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4836 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4837 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4839 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4840 /* public key token isn't copied - the class library will
4841 automatically generate it from the public key if required */
4842 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4843 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4845 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4846 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4849 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4852 /* note: this function doesn't return the codebase on purpose (i.e. it can
4853 be used under partial trust as path information isn't present). */
4855 mono_array_setref (result, i, aname);
4860 /* move this in some file in mono/util/ */
4862 g_concat_dir_and_file (const char *dir, const char *file)
4864 g_return_val_if_fail (dir != NULL, NULL);
4865 g_return_val_if_fail (file != NULL, NULL);
4868 * If the directory name doesn't have a / on the end, we need
4869 * to add one so we get a proper path to the file
4871 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4872 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4874 return g_strconcat (dir, file, NULL);
4878 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4881 char *n = mono_string_to_utf8 (name);
4882 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4884 guint32 cols [MONO_MANIFEST_SIZE];
4885 guint32 impl, file_idx;
4889 for (i = 0; i < table->rows; ++i) {
4890 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4891 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4892 if (strcmp (val, n) == 0)
4896 if (i == table->rows)
4899 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4902 * this code should only be called after obtaining the
4903 * ResourceInfo and handling the other cases.
4905 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4906 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4908 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4913 module = assembly->assembly->image;
4916 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4917 mono_error_raise_exception (&error);
4918 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4920 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4923 ICALL_EXPORT gboolean
4924 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4927 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4929 guint32 cols [MONO_MANIFEST_SIZE];
4930 guint32 file_cols [MONO_FILE_SIZE];
4934 n = mono_string_to_utf8 (name);
4935 for (i = 0; i < table->rows; ++i) {
4936 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4937 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4938 if (strcmp (val, n) == 0)
4942 if (i == table->rows)
4945 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4946 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4949 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4950 case MONO_IMPLEMENTATION_FILE:
4951 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4952 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4953 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4954 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4955 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4956 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4959 info->location = RESOURCE_LOCATION_EMBEDDED;
4962 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4963 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4964 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4965 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4966 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4967 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4969 mono_set_pending_exception (ex);
4972 MonoReflectionAssembly *assm_obj;
4973 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4975 mono_error_set_pending_exception (&error);
4978 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4980 /* Obtain info recursively */
4981 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4982 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4985 case MONO_IMPLEMENTATION_EXP_TYPE:
4986 g_assert_not_reached ();
4994 ICALL_EXPORT MonoObject*
4995 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4997 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4998 MonoArray *result = NULL;
5003 /* check hash if needed */
5005 n = mono_string_to_utf8 (name);
5006 for (i = 0; i < table->rows; ++i) {
5007 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5008 if (strcmp (val, n) == 0) {
5011 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5012 fn = mono_string_new (mono_object_domain (assembly), n);
5014 return (MonoObject*)fn;
5022 for (i = 0; i < table->rows; ++i) {
5023 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5027 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
5030 for (i = 0; i < table->rows; ++i) {
5031 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5032 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5033 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5034 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5039 return (MonoObject*)result;
5042 ICALL_EXPORT MonoArray*
5043 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5046 MonoDomain *domain = mono_domain_get();
5049 int i, j, file_count = 0;
5050 MonoImage **modules;
5051 guint32 module_count, real_module_count;
5052 MonoTableInfo *table;
5053 guint32 cols [MONO_FILE_SIZE];
5054 MonoImage *image = assembly->assembly->image;
5056 g_assert (image != NULL);
5057 g_assert (!assembly_is_dynamic (assembly->assembly));
5059 table = &image->tables [MONO_TABLE_FILE];
5060 file_count = table->rows;
5062 modules = image->modules;
5063 module_count = image->module_count;
5065 real_module_count = 0;
5066 for (i = 0; i < module_count; ++i)
5068 real_module_count ++;
5070 klass = mono_class_get_module_class ();
5071 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
5073 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5074 mono_error_raise_exception (&error);
5075 mono_array_setref (res, 0, image_obj);
5077 for (i = 0; i < module_count; ++i)
5079 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5080 mono_error_raise_exception (&error);
5081 mono_array_setref (res, j, rm);
5085 for (i = 0; i < file_count; ++i, ++j) {
5086 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5087 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5088 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5089 mono_error_raise_exception (&error);
5090 mono_array_setref (res, j, rm);
5093 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5095 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5096 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5099 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5100 mono_error_raise_exception (&error);
5101 mono_array_setref (res, j, rm);
5108 ICALL_EXPORT MonoReflectionMethod*
5109 ves_icall_GetCurrentMethod (void)
5111 MonoReflectionMethod *res = NULL;
5114 MonoMethod *m = mono_method_get_last_managed ();
5117 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5121 while (m->is_inflated)
5122 m = ((MonoMethodInflated*)m)->declaring;
5124 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5125 mono_error_raise_exception (&error);
5131 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5134 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5137 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5138 //method is inflated, we should inflate it on the other class
5139 MonoGenericContext ctx;
5140 ctx.method_inst = inflated->context.method_inst;
5141 ctx.class_inst = inflated->context.class_inst;
5142 if (klass->generic_class)
5143 ctx.class_inst = klass->generic_class->context.class_inst;
5144 else if (klass->generic_container)
5145 ctx.class_inst = klass->generic_container->context.class_inst;
5146 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5147 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5151 mono_class_setup_methods (method->klass);
5152 if (mono_class_has_failure (method->klass))
5154 for (i = 0; i < method->klass->method.count; ++i) {
5155 if (method->klass->methods [i] == method) {
5160 mono_class_setup_methods (klass);
5161 if (mono_class_has_failure (klass))
5163 g_assert (offset >= 0 && offset < klass->method.count);
5164 return klass->methods [offset];
5167 ICALL_EXPORT MonoReflectionMethod*
5168 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5170 MonoReflectionMethod *res = NULL;
5174 klass = mono_class_from_mono_type (type);
5175 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5177 if (method->klass != klass) {
5178 method = mono_method_get_equivalent_method (method, klass);
5183 klass = method->klass;
5184 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5185 mono_error_raise_exception (&error);
5189 ICALL_EXPORT MonoReflectionMethodBody*
5190 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5193 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5194 mono_error_set_pending_exception (&error);
5198 ICALL_EXPORT MonoReflectionAssembly*
5199 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5202 MonoReflectionAssembly *result;
5203 MonoMethod *dest = NULL;
5205 mono_stack_walk_no_il (get_executing, &dest);
5207 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5209 mono_error_set_pending_exception (&error);
5214 ICALL_EXPORT MonoReflectionAssembly*
5215 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5218 MonoReflectionAssembly *result;
5219 MonoDomain* domain = mono_domain_get ();
5221 if (!domain->entry_assembly)
5224 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5226 mono_error_set_pending_exception (&error);
5230 ICALL_EXPORT MonoReflectionAssembly*
5231 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5236 MonoReflectionAssembly *result;
5239 mono_stack_walk_no_il (get_executing, &dest);
5241 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5245 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5248 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5250 mono_error_set_pending_exception (&error);
5254 ICALL_EXPORT MonoString *
5255 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5256 gboolean assembly_qualified)
5258 MonoDomain *domain = mono_object_domain (object);
5259 MonoTypeNameFormat format;
5264 format = assembly_qualified ?
5265 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5266 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5268 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5270 name = mono_type_get_name_full (object->type, format);
5274 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5279 res = mono_string_new (domain, name);
5286 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5289 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5291 mono_class_init_checked (klass, &error);
5292 mono_error_raise_exception (&error);
5293 return mono_security_core_clr_class_level (klass);
5297 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5299 MonoClassField *field = rfield->field;
5300 return mono_security_core_clr_field_level (field, TRUE);
5304 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5306 MonoMethod *method = rfield->method;
5307 return mono_security_core_clr_method_level (method, TRUE);
5311 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)
5313 static MonoMethod *create_culture = NULL;
5317 const char *pkey_ptr;
5319 MonoBoolean assembly_ref = 0;
5321 mono_error_init (error);
5323 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5324 aname->major = name->major;
5325 aname->minor = name->minor;
5326 aname->build = name->build;
5327 aname->flags = name->flags;
5328 aname->revision = name->revision;
5329 aname->hashalg = name->hash_alg;
5330 aname->versioncompat = 1; /* SameMachine (default) */
5331 aname->processor_architecture = name->arch;
5333 if (by_default_version) {
5334 MonoObject *version;
5336 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5337 return_if_nok (error);
5339 MONO_OBJECT_SETREF (aname, version, version);
5343 if (absolute != NULL && *absolute != '\0') {
5344 const gchar *prepend = "file://";
5347 codebase = g_strdup (absolute);
5352 for (i = strlen (codebase) - 1; i >= 0; i--)
5353 if (codebase [i] == '\\')
5356 if (*codebase == '/' && *(codebase + 1) == '/') {
5359 prepend = "file:///";
5363 result = g_strconcat (prepend, codebase, NULL);
5369 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5373 if (!create_culture) {
5374 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5375 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5376 g_assert (create_culture);
5377 mono_method_desc_free (desc);
5380 if (name->culture) {
5381 args [0] = mono_string_new (domain, name->culture);
5382 args [1] = &assembly_ref;
5384 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5385 return_if_nok (error);
5387 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5390 if (name->public_key) {
5391 pkey_ptr = (char*)name->public_key;
5392 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5394 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5395 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5396 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5397 } else if (default_publickey) {
5398 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5399 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5402 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5403 if (name->public_key_token [0]) {
5407 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5408 p = mono_array_addr (aname->keyToken, char, 0);
5410 for (i = 0, j = 0; i < 8; i++) {
5411 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5412 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5415 } else if (default_token) {
5416 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5420 ICALL_EXPORT MonoString *
5421 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5423 MonoDomain *domain = mono_object_domain (assembly);
5424 MonoAssembly *mass = assembly->assembly;
5428 name = mono_stringify_assembly_name (&mass->aname);
5429 res = mono_string_new (domain, name);
5436 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5440 MonoAssembly *mass = assembly->assembly;
5442 if (g_path_is_absolute (mass->image->name)) {
5443 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5444 mono_error_set_pending_exception (&error);
5447 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5449 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5450 mono_error_set_pending_exception (&error);
5456 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5460 MonoImageOpenStatus status = MONO_IMAGE_OK;
5463 MonoAssemblyName name;
5466 filename = mono_string_to_utf8 (fname);
5468 dirname = g_path_get_dirname (filename);
5469 replace_shadow_path (mono_domain_get (), dirname, &filename);
5472 image = mono_image_open (filename, &status);
5478 if (status == MONO_IMAGE_IMAGE_INVALID)
5479 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5481 exc = mono_get_exception_file_not_found2 (NULL, fname);
5482 mono_set_pending_exception (exc);
5486 res = mono_assembly_fill_assembly_name (image, &name);
5488 mono_image_close (image);
5490 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5494 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5495 mono_error_set_pending_exception (&error);
5497 mono_image_close (image);
5501 ICALL_EXPORT MonoBoolean
5502 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5503 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5505 MonoBoolean result = FALSE;
5506 MonoDeclSecurityEntry entry;
5508 /* SecurityAction.RequestMinimum */
5509 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5510 *minimum = entry.blob;
5511 *minLength = entry.size;
5514 /* SecurityAction.RequestOptional */
5515 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5516 *optional = entry.blob;
5517 *optLength = entry.size;
5520 /* SecurityAction.RequestRefuse */
5521 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5522 *refused = entry.blob;
5523 *refLength = entry.size;
5531 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5533 guint32 attrs, visibility;
5535 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5536 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5537 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5540 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5546 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5548 MonoReflectionType *rt;
5551 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5554 mono_error_init (error);
5556 /* we start the count from 1 because we skip the special type <Module> */
5559 for (i = 1; i < tdef->rows; ++i) {
5560 if (mono_module_type_is_visible (tdef, image, i + 1))
5564 count = tdef->rows - 1;
5566 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5567 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5569 for (i = 1; i < tdef->rows; ++i) {
5570 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5571 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5574 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5575 return_val_if_nok (error, NULL);
5577 mono_array_setref (res, count, rt);
5579 MonoException *ex = mono_error_convert_to_exception (error);
5580 mono_array_setref (*exceptions, count, ex);
5589 ICALL_EXPORT MonoArray*
5590 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5593 MonoArray *res = NULL;
5594 MonoArray *exceptions = NULL;
5595 MonoImage *image = NULL;
5596 MonoTableInfo *table = NULL;
5599 int i, len, ex_count;
5601 domain = mono_object_domain (assembly);
5603 g_assert (!assembly_is_dynamic (assembly->assembly));
5604 image = assembly->assembly->image;
5605 table = &image->tables [MONO_TABLE_FILE];
5606 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5607 mono_error_raise_exception (&error);
5609 /* Append data from all modules in the assembly */
5610 for (i = 0; i < table->rows; ++i) {
5611 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5612 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5617 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5618 mono_error_raise_exception (&error);
5620 /* Append the new types to the end of the array */
5621 if (mono_array_length (res2) > 0) {
5623 MonoArray *res3, *ex3;
5625 len1 = mono_array_length (res);
5626 len2 = mono_array_length (res2);
5628 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5629 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5630 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5633 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5634 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5635 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5642 /* the ReflectionTypeLoadException must have all the types (Types property),
5643 * NULL replacing types which throws an exception. The LoaderException must
5644 * contain all exceptions for NULL items.
5647 len = mono_array_length (res);
5650 for (i = 0; i < len; i++) {
5651 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5655 klass = mono_type_get_class (t->type);
5656 if ((klass != NULL) && mono_class_has_failure (klass)) {
5657 /* keep the class in the list */
5658 list = g_list_append (list, klass);
5659 /* and replace Type with NULL */
5660 mono_array_setref (res, i, NULL);
5667 if (list || ex_count) {
5669 MonoException *exc = NULL;
5670 MonoArray *exl = NULL;
5671 int j, length = g_list_length (list) + ex_count;
5673 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5674 /* Types for which mono_class_get_checked () succeeded */
5675 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5676 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5677 mono_array_setref (exl, i, exc);
5679 /* Types for which it don't */
5680 for (j = 0; j < mono_array_length (exceptions); ++j) {
5681 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5683 g_assert (i < length);
5684 mono_array_setref (exl, i, exc);
5691 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5692 if (!is_ok (&error)) {
5693 mono_error_set_pending_exception (&error);
5696 mono_set_pending_exception (exc);
5703 ICALL_EXPORT gboolean
5704 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5707 MonoAssemblyName aname;
5708 MonoDomain *domain = mono_object_domain (name);
5710 gboolean is_version_defined;
5711 gboolean is_token_defined;
5713 aname.public_key = NULL;
5714 val = mono_string_to_utf8 (assname);
5715 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5716 g_free ((guint8*) aname.public_key);
5721 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5722 mono_error_set_pending_exception (&error);
5724 mono_assembly_name_free (&aname);
5725 g_free ((guint8*) aname.public_key);
5731 ICALL_EXPORT MonoReflectionType*
5732 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5735 MonoReflectionType *ret;
5736 MonoDomain *domain = mono_object_domain (module);
5739 g_assert (module->image);
5741 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5742 /* These images do not have a global type */
5745 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5746 if (!mono_error_ok (&error)) {
5747 mono_error_set_pending_exception (&error);
5751 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5752 if (!mono_error_ok (&error)) {
5753 mono_error_set_pending_exception (&error);
5761 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5763 /*if (module->image)
5764 mono_image_close (module->image);*/
5767 ICALL_EXPORT MonoString*
5768 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5770 MonoDomain *domain = mono_object_domain (module);
5772 g_assert (module->image);
5773 return mono_string_new (domain, module->image->guid);
5776 ICALL_EXPORT gpointer
5777 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5780 if (module->image && module->image->is_module_handle)
5781 return module->image->raw_data;
5784 return (gpointer) (-1);
5788 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5790 if (image_is_dynamic (image)) {
5791 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5792 *pe_kind = dyn->pe_kind;
5793 *machine = dyn->machine;
5796 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5797 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5802 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5804 return (image->md_version_major << 16) | (image->md_version_minor);
5807 ICALL_EXPORT MonoArray*
5808 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5811 MonoArray *exceptions;
5815 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5819 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5820 mono_error_raise_exception (&error);
5822 for (i = 0; i < mono_array_length (exceptions); ++i) {
5823 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5825 mono_set_pending_exception (ex);
5834 mono_memberref_is_method (MonoImage *image, guint32 token)
5836 if (!image_is_dynamic (image)) {
5837 guint32 cols [MONO_MEMBERREF_SIZE];
5839 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5840 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5841 mono_metadata_decode_blob_size (sig, &sig);
5842 return (*sig != 0x6);
5845 MonoClass *handle_class;
5847 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5848 mono_error_cleanup (&error); /* just probing, ignore error */
5852 return mono_defaults.methodhandle_class == handle_class;
5857 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5860 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5861 mono_array_addr (type_args, MonoType*, 0));
5863 context->class_inst = NULL;
5865 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5866 mono_array_addr (method_args, MonoType*, 0));
5868 context->method_inst = NULL;
5871 ICALL_EXPORT MonoType*
5872 ves_icall_System_Reflection_Module_ResolveTypeToken (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_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5884 (table != MONO_TABLE_TYPESPEC)) {
5885 *resolve_error = ResolveTokenError_BadTable;
5889 if (image_is_dynamic (image)) {
5890 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5891 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5892 mono_error_cleanup (&error);
5893 return klass ? &klass->byval_arg : NULL;
5896 init_generic_context_from_args (&context, type_args, method_args);
5897 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5898 mono_error_cleanup (&error);
5899 return klass ? &klass->byval_arg : NULL;
5902 if ((index <= 0) || (index > image->tables [table].rows)) {
5903 *resolve_error = ResolveTokenError_OutOfRange;
5907 init_generic_context_from_args (&context, type_args, method_args);
5908 klass = mono_class_get_checked (image, token, &error);
5910 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5911 if (!mono_error_ok (&error)) {
5912 mono_error_set_pending_exception (&error);
5917 return &klass->byval_arg;
5922 ICALL_EXPORT MonoMethod*
5923 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5926 int table = mono_metadata_token_table (token);
5927 int index = mono_metadata_token_index (token);
5928 MonoGenericContext context;
5931 *resolve_error = ResolveTokenError_Other;
5933 /* Validate token */
5934 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5935 (table != MONO_TABLE_MEMBERREF)) {
5936 *resolve_error = ResolveTokenError_BadTable;
5940 if (image_is_dynamic (image)) {
5941 if (table == MONO_TABLE_METHOD) {
5942 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5943 mono_error_cleanup (&error);
5947 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5948 *resolve_error = ResolveTokenError_BadTable;
5952 init_generic_context_from_args (&context, type_args, method_args);
5953 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5954 mono_error_cleanup (&error);
5958 if ((index <= 0) || (index > image->tables [table].rows)) {
5959 *resolve_error = ResolveTokenError_OutOfRange;
5962 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5963 *resolve_error = ResolveTokenError_BadTable;
5967 init_generic_context_from_args (&context, type_args, method_args);
5968 method = mono_get_method_checked (image, token, NULL, &context, &error);
5969 mono_error_set_pending_exception (&error);
5974 ICALL_EXPORT MonoString*
5975 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5978 int index = mono_metadata_token_index (token);
5980 *resolve_error = ResolveTokenError_Other;
5982 /* Validate token */
5983 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5984 *resolve_error = ResolveTokenError_BadTable;
5988 if (image_is_dynamic (image)) {
5989 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5990 mono_error_cleanup (&error);
5994 if ((index <= 0) || (index >= image->heap_us.size)) {
5995 *resolve_error = ResolveTokenError_OutOfRange;
5999 /* FIXME: What to do if the index points into the middle of a string ? */
6001 return mono_ldstr (mono_domain_get (), image, index);
6004 ICALL_EXPORT MonoClassField*
6005 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6009 int table = mono_metadata_token_table (token);
6010 int index = mono_metadata_token_index (token);
6011 MonoGenericContext context;
6012 MonoClassField *field;
6014 *resolve_error = ResolveTokenError_Other;
6016 /* Validate token */
6017 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6018 *resolve_error = ResolveTokenError_BadTable;
6022 if (image_is_dynamic (image)) {
6023 if (table == MONO_TABLE_FIELD) {
6024 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6025 mono_error_cleanup (&error);
6029 if (mono_memberref_is_method (image, token)) {
6030 *resolve_error = ResolveTokenError_BadTable;
6034 init_generic_context_from_args (&context, type_args, method_args);
6035 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6036 mono_error_cleanup (&error);
6040 if ((index <= 0) || (index > image->tables [table].rows)) {
6041 *resolve_error = ResolveTokenError_OutOfRange;
6044 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6045 *resolve_error = ResolveTokenError_BadTable;
6049 init_generic_context_from_args (&context, type_args, method_args);
6050 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6051 mono_error_set_pending_exception (&error);
6057 ICALL_EXPORT MonoObject*
6058 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6062 int table = mono_metadata_token_table (token);
6064 *error = ResolveTokenError_Other;
6067 case MONO_TABLE_TYPEDEF:
6068 case MONO_TABLE_TYPEREF:
6069 case MONO_TABLE_TYPESPEC: {
6070 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6072 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6073 mono_error_raise_exception (&merror);
6080 case MONO_TABLE_METHOD:
6081 case MONO_TABLE_METHODSPEC: {
6082 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6084 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6085 mono_error_raise_exception (&merror);
6091 case MONO_TABLE_FIELD: {
6092 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6094 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6095 mono_error_raise_exception (&merror);
6101 case MONO_TABLE_MEMBERREF:
6102 if (mono_memberref_is_method (image, token)) {
6103 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6105 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6106 mono_error_raise_exception (&merror);
6113 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6115 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6116 mono_error_raise_exception (&merror);
6125 *error = ResolveTokenError_BadTable;
6131 ICALL_EXPORT MonoArray*
6132 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
6134 int table = mono_metadata_token_table (token);
6135 int idx = mono_metadata_token_index (token);
6136 MonoTableInfo *tables = image->tables;
6141 *error = ResolveTokenError_OutOfRange;
6143 /* FIXME: Support other tables ? */
6144 if (table != MONO_TABLE_STANDALONESIG)
6147 if (image_is_dynamic (image))
6150 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6153 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6155 ptr = mono_metadata_blob_heap (image, sig);
6156 len = mono_metadata_decode_blob_size (ptr, &ptr);
6158 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
6159 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6163 ICALL_EXPORT MonoReflectionType*
6164 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6167 MonoReflectionType *ret;
6169 int isbyref = 0, rank;
6170 char *str = mono_string_to_utf8 (smodifiers);
6173 klass = mono_class_from_mono_type (tb->type.type);
6175 /* logic taken from mono_reflection_parse_type(): keep in sync */
6179 if (isbyref) { /* only one level allowed by the spec */
6188 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6189 mono_error_raise_exception (&error);
6193 klass = mono_ptr_class_get (&klass->byval_arg);
6194 mono_class_init (klass);
6205 else if (*p != '*') { /* '*' means unknown lower bound */
6216 klass = mono_array_class_get (klass, rank);
6217 mono_class_init (klass);
6226 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6227 mono_error_raise_exception (&error);
6232 ICALL_EXPORT MonoBoolean
6233 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6239 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6245 check_for_invalid_type (MonoClass *klass, MonoError *error)
6250 mono_error_init (error);
6252 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6255 name = mono_type_get_full_name (klass);
6256 str = mono_string_new (mono_domain_get (), name);
6258 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6261 ICALL_EXPORT MonoReflectionType *
6262 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6265 MonoReflectionType *ret;
6266 MonoClass *klass, *aklass;
6268 klass = mono_class_from_mono_type (type->type);
6269 check_for_invalid_type (klass, &error);
6270 mono_error_raise_exception (&error);
6272 if (rank == 0) //single dimentional array
6273 aklass = mono_array_class_get (klass, 1);
6275 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6277 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6278 mono_error_raise_exception (&error);
6283 ICALL_EXPORT MonoReflectionType *
6284 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6287 MonoReflectionType *ret;
6290 klass = mono_class_from_mono_type (type->type);
6291 mono_class_init_checked (klass, &error);
6292 mono_error_raise_exception (&error);
6293 check_for_invalid_type (klass, &error);
6294 mono_error_raise_exception (&error);
6296 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6297 mono_error_raise_exception (&error);
6302 ICALL_EXPORT MonoReflectionType *
6303 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6306 MonoReflectionType *ret;
6307 MonoClass *klass, *pklass;
6309 klass = mono_class_from_mono_type (type->type);
6310 mono_class_init_checked (klass, &error);
6311 mono_error_raise_exception (&error);
6312 check_for_invalid_type (klass, &error);
6313 mono_error_raise_exception (&error);
6315 pklass = mono_ptr_class_get (type->type);
6317 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6318 mono_error_raise_exception (&error);
6323 ICALL_EXPORT MonoObject *
6324 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6325 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6328 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6329 MonoObject *delegate;
6331 MonoMethod *method = info->method;
6333 mono_class_init_checked (delegate_class, &error);
6334 mono_error_raise_exception (&error);
6336 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6337 /* FIXME improve this exception message */
6338 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6340 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6341 mono_error_set_pending_exception (&error);
6345 if (mono_security_core_clr_enabled ()) {
6346 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6347 if (throwOnBindFailure)
6348 mono_error_set_pending_exception (&error);
6350 mono_error_cleanup (&error);
6355 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6356 mono_error_raise_exception (&error);
6358 if (method_is_dynamic (method)) {
6359 /* Creating a trampoline would leak memory */
6360 func = mono_compile_method (method);
6362 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6363 method = mono_object_get_virtual_method (target, method);
6364 func = mono_create_ftnptr (mono_domain_get (),
6365 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6368 mono_delegate_ctor_with_method (delegate, target, func, method);
6373 ICALL_EXPORT MonoMulticastDelegate *
6374 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6377 MonoMulticastDelegate *ret;
6379 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6381 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6382 mono_error_raise_exception (&error);
6383 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6388 ICALL_EXPORT MonoReflectionMethod*
6389 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6391 MonoReflectionMethod *ret = NULL;
6393 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6394 mono_error_raise_exception (&error);
6400 static inline gint32
6401 mono_array_get_byte_length (MonoArray *array)
6407 klass = array->obj.vtable->klass;
6409 if (array->bounds == NULL)
6410 length = array->max_length;
6413 for (i = 0; i < klass->rank; ++ i)
6414 length *= array->bounds [i].length;
6417 switch (klass->element_class->byval_arg.type) {
6420 case MONO_TYPE_BOOLEAN:
6424 case MONO_TYPE_CHAR:
6432 return length * sizeof (gpointer);
6443 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6445 return mono_array_get_byte_length (array);
6449 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6451 return mono_array_get (array, gint8, idx);
6455 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6457 mono_array_set (array, gint8, idx, value);
6460 ICALL_EXPORT MonoBoolean
6461 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6463 guint8 *src_buf, *dest_buf;
6466 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6470 g_assert (count >= 0);
6472 /* This is called directly from the class libraries without going through the managed wrapper */
6473 MONO_CHECK_ARG_NULL (src, FALSE);
6474 MONO_CHECK_ARG_NULL (dest, FALSE);
6476 /* watch out for integer overflow */
6477 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6480 src_buf = (guint8 *)src->vector + src_offset;
6481 dest_buf = (guint8 *)dest->vector + dest_offset;
6484 memcpy (dest_buf, src_buf, count);
6486 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6491 #ifndef DISABLE_REMOTING
6492 ICALL_EXPORT MonoObject *
6493 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6496 MonoDomain *domain = mono_object_domain (this_obj);
6498 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6499 MonoTransparentProxy *tp;
6503 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6504 mono_error_raise_exception (&error);
6505 tp = (MonoTransparentProxy*) res;
6507 MONO_OBJECT_SETREF (tp, rp, rp);
6508 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6509 klass = mono_class_from_mono_type (type);
6511 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6512 mono_class_setup_vtable (klass);
6513 if (mono_class_has_failure (klass)) {
6514 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6518 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6519 if (!is_ok (&error)) {
6520 mono_error_set_pending_exception (&error);
6523 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6524 if (!is_ok (&error)) {
6525 mono_error_set_pending_exception (&error);
6529 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6533 ICALL_EXPORT MonoReflectionType *
6534 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6537 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6538 mono_error_raise_exception (&error);
6544 /* System.Environment */
6547 ves_icall_System_Environment_get_UserName (void)
6549 /* using glib is more portable */
6550 return mono_string_new (mono_domain_get (), g_get_user_name ());
6554 ICALL_EXPORT MonoString *
6555 ves_icall_System_Environment_get_MachineName (void)
6557 #if defined (HOST_WIN32)
6562 len = MAX_COMPUTERNAME_LENGTH + 1;
6563 buf = g_new (gunichar2, len);
6566 if (GetComputerName (buf, (PDWORD) &len)) {
6568 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6569 mono_error_raise_exception (&error);
6574 #elif !defined(DISABLE_SOCKETS)
6578 #if defined _SC_HOST_NAME_MAX
6579 n = sysconf (_SC_HOST_NAME_MAX);
6583 buf = g_malloc (n+1);
6585 if (gethostname (buf, n) == 0){
6587 result = mono_string_new (mono_domain_get (), buf);
6594 return mono_string_new (mono_domain_get (), "mono");
6599 ves_icall_System_Environment_get_Platform (void)
6601 #if defined (TARGET_WIN32)
6604 #elif defined(__MACH__)
6607 // Notice that the value is hidden from user code, and only exposed
6608 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6609 // define and making assumptions based on Unix/128/4 values before there
6610 // was a MacOS define. Lots of code would assume that not-Unix meant
6611 // Windows, but in this case, it would be OSX.
6620 ICALL_EXPORT MonoString *
6621 ves_icall_System_Environment_get_NewLine (void)
6623 #if defined (HOST_WIN32)
6624 return mono_string_new (mono_domain_get (), "\r\n");
6626 return mono_string_new (mono_domain_get (), "\n");
6630 ICALL_EXPORT MonoBoolean
6631 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6633 #if SIZEOF_VOID_P == 8
6637 gboolean isWow64Process = FALSE;
6638 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6639 return (MonoBoolean)isWow64Process;
6641 #elif defined(HAVE_SYS_UTSNAME_H)
6642 struct utsname name;
6644 if (uname (&name) >= 0) {
6645 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6652 ICALL_EXPORT MonoString *
6653 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6661 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6662 value = g_getenv (utf8_name);
6669 return mono_string_new (mono_domain_get (), value);
6673 * There is no standard way to get at environ.
6676 #ifndef __MINGW32_VERSION
6677 #if defined(__APPLE__)
6678 #if defined (TARGET_OSX)
6679 /* Apple defines this in crt_externs.h but doesn't provide that header for
6680 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6681 * in fact exist on all implementations (so far)
6683 gchar ***_NSGetEnviron(void);
6684 #define environ (*_NSGetEnviron())
6686 static char *mono_environ[1] = { NULL };
6687 #define environ mono_environ
6688 #endif /* defined (TARGET_OSX) */
6696 ICALL_EXPORT MonoArray *
6697 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6708 env_strings = GetEnvironmentStrings();
6711 env_string = env_strings;
6712 while (*env_string != '\0') {
6713 /* weird case that MS seems to skip */
6714 if (*env_string != '=')
6716 while (*env_string != '\0')
6722 domain = mono_domain_get ();
6723 names = mono_array_new (domain, mono_defaults.string_class, n);
6727 env_string = env_strings;
6728 while (*env_string != '\0') {
6729 /* weird case that MS seems to skip */
6730 if (*env_string != '=') {
6731 equal_str = wcschr(env_string, '=');
6732 g_assert(equal_str);
6734 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6735 mono_error_raise_exception (&error);
6736 mono_array_setref (names, n, str);
6739 while (*env_string != '\0')
6744 FreeEnvironmentStrings (env_strings);
6757 for (e = environ; *e != 0; ++ e)
6760 domain = mono_domain_get ();
6761 names = mono_array_new (domain, mono_defaults.string_class, n);
6764 for (e = environ; *e != 0; ++ e) {
6765 parts = g_strsplit (*e, "=", 2);
6767 str = mono_string_new (domain, *parts);
6768 mono_array_setref (names, n, str);
6781 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6783 #if !GLIB_CHECK_VERSION(2,4,0)
6784 #define g_setenv(a,b,c) setenv(a,b,c)
6785 #define g_unsetenv(a) unsetenv(a)
6789 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6792 gunichar2 *utf16_name, *utf16_value;
6794 gchar *utf8_name, *utf8_value;
6799 utf16_name = mono_string_to_utf16 (name);
6800 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6801 SetEnvironmentVariable (utf16_name, NULL);
6802 g_free (utf16_name);
6806 utf16_value = mono_string_to_utf16 (value);
6808 SetEnvironmentVariable (utf16_name, utf16_value);
6810 g_free (utf16_name);
6811 g_free (utf16_value);
6813 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6815 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6816 g_unsetenv (utf8_name);
6821 utf8_value = mono_string_to_utf8_checked (value, &error);
6822 if (!mono_error_ok (&error)) {
6824 mono_error_set_pending_exception (&error);
6827 g_setenv (utf8_name, utf8_value, TRUE);
6830 g_free (utf8_value);
6835 ves_icall_System_Environment_Exit (int result)
6837 mono_environment_exitcode_set (result);
6839 /* FIXME: There are some cleanup hangs that should be worked out, but
6840 * if the program is going to exit, everything will be cleaned up when
6841 * NaCl exits anyway.
6843 #ifndef __native_client__
6844 if (!mono_runtime_try_shutdown ())
6845 mono_thread_exit ();
6847 /* Suspend all managed threads since the runtime is going away */
6848 mono_thread_suspend_all_other_threads ();
6850 mono_runtime_quit ();
6853 /* we may need to do some cleanup here... */
6857 ICALL_EXPORT MonoString*
6858 ves_icall_System_Environment_GetGacPath (void)
6860 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6863 ICALL_EXPORT MonoString*
6864 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6866 #if defined (HOST_WIN32)
6867 #ifndef CSIDL_FLAG_CREATE
6868 #define CSIDL_FLAG_CREATE 0x8000
6871 WCHAR path [MAX_PATH];
6872 /* Create directory if no existing */
6873 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6878 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6879 mono_error_raise_exception (&error);
6883 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6885 return mono_string_new (mono_domain_get (), "");
6888 ICALL_EXPORT MonoArray *
6889 ves_icall_System_Environment_GetLogicalDrives (void)
6892 gunichar2 buf [256], *ptr, *dname;
6894 guint initial_size = 127, size = 128;
6897 MonoString *drivestr;
6898 MonoDomain *domain = mono_domain_get ();
6904 while (size > initial_size) {
6905 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6906 if (size > initial_size) {
6909 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6910 initial_size = size;
6924 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6929 while (*u16) { u16++; len ++; }
6930 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6931 mono_error_raise_exception (&error);
6932 mono_array_setref (result, ndrives++, drivestr);
6942 ICALL_EXPORT MonoString *
6943 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6945 gunichar2 volume_name [MAX_PATH + 1];
6947 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6949 return mono_string_from_utf16 (volume_name);
6952 ICALL_EXPORT MonoString *
6953 ves_icall_System_Environment_InternalGetHome (void)
6955 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6958 static const char *encodings [] = {
6960 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6961 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6962 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6964 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6965 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6966 "x_unicode_2_0_utf_7",
6968 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6969 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6971 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6974 "unicodefffe", "utf_16be",
6981 * Returns the internal codepage, if the value of "int_code_page" is
6982 * 1 at entry, and we can not compute a suitable code page number,
6983 * returns the code page as a string
6985 ICALL_EXPORT MonoString*
6986 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6991 char *codepage = NULL;
6993 int want_name = *int_code_page;
6996 *int_code_page = -1;
6998 g_get_charset (&cset);
6999 c = codepage = strdup (cset);
7000 for (c = codepage; *c; c++){
7001 if (isascii (*c) && isalpha (*c))
7006 /* g_print ("charset: %s\n", cset); */
7008 /* handle some common aliases */
7011 for (i = 0; p != 0; ){
7014 p = encodings [++i];
7017 if (strcmp (p, codepage) == 0){
7018 *int_code_page = code;
7021 p = encodings [++i];
7024 if (strstr (codepage, "utf_8") != NULL)
7025 *int_code_page |= 0x10000000;
7028 if (want_name && *int_code_page == -1)
7029 return mono_string_new (mono_domain_get (), cset);
7034 ICALL_EXPORT MonoBoolean
7035 ves_icall_System_Environment_get_HasShutdownStarted (void)
7037 if (mono_runtime_is_shutting_down ())
7040 if (mono_domain_is_unloading (mono_domain_get ()))
7047 ves_icall_System_Environment_BroadcastSettingChange (void)
7050 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7055 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7061 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
7062 MonoReflectionMethod *method,
7063 MonoArray *out_args)
7065 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
7068 #ifndef DISABLE_REMOTING
7069 ICALL_EXPORT MonoBoolean
7070 ves_icall_IsTransparentProxy (MonoObject *proxy)
7075 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7081 ICALL_EXPORT MonoReflectionMethod *
7082 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7083 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7085 MonoReflectionMethod *ret = NULL;
7090 MonoMethod **vtable;
7091 MonoMethod *res = NULL;
7093 MONO_CHECK_ARG_NULL (rtype, NULL);
7094 MONO_CHECK_ARG_NULL (rmethod, NULL);
7096 method = rmethod->method;
7097 klass = mono_class_from_mono_type (rtype->type);
7098 mono_class_init_checked (klass, &error);
7099 mono_error_raise_exception (&error);
7101 if (MONO_CLASS_IS_INTERFACE (klass))
7104 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7107 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7108 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7114 mono_class_setup_vtable (klass);
7115 vtable = klass->vtable;
7117 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7118 gboolean variance_used = FALSE;
7119 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7120 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7122 res = vtable [offs + method->slot];
7124 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7127 if (method->slot != -1)
7128 res = vtable [method->slot];
7134 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7135 mono_error_raise_exception (&error);
7140 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7146 klass = mono_class_from_mono_type (type->type);
7147 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7148 if (!is_ok (&error)) {
7149 mono_error_set_pending_exception (&error);
7153 mono_vtable_set_is_remote (vtable, enable);
7156 #else /* DISABLE_REMOTING */
7159 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7161 g_assert_not_reached ();
7166 ICALL_EXPORT MonoObject *
7167 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7174 domain = mono_object_domain (type);
7175 klass = mono_class_from_mono_type (type->type);
7176 mono_class_init_checked (klass, &error);
7177 mono_error_raise_exception (&error);
7179 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7180 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7184 if (klass->rank >= 1) {
7185 g_assert (klass->rank == 1);
7186 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7188 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7189 if (!is_ok (&error)) {
7190 mono_error_set_pending_exception (&error);
7193 /* Bypass remoting object creation check */
7194 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7195 mono_error_set_pending_exception (&error);
7201 ICALL_EXPORT MonoString *
7202 ves_icall_System_IO_get_temp_path (void)
7204 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7207 #ifndef PLATFORM_NO_DRIVEINFO
7208 ICALL_EXPORT MonoBoolean
7209 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7210 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7214 ULARGE_INTEGER wapi_free_bytes_avail;
7215 ULARGE_INTEGER wapi_total_number_of_bytes;
7216 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7218 *error = ERROR_SUCCESS;
7219 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7220 &wapi_total_number_of_free_bytes);
7223 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7224 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7225 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7227 *free_bytes_avail = 0;
7228 *total_number_of_bytes = 0;
7229 *total_number_of_free_bytes = 0;
7230 *error = GetLastError ();
7236 ICALL_EXPORT guint32
7237 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7239 return GetDriveType (mono_string_chars (root_path_name));
7243 ICALL_EXPORT gpointer
7244 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7246 return mono_compile_method (method);
7249 ICALL_EXPORT MonoString *
7250 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7255 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7257 #if defined (HOST_WIN32)
7258 /* Avoid mixing '/' and '\\' */
7261 for (i = strlen (path) - 1; i >= 0; i--)
7262 if (path [i] == '/')
7266 mcpath = mono_string_new (mono_domain_get (), path);
7273 get_bundled_app_config (void)
7275 const gchar *app_config;
7278 gchar *config_file_name, *config_file_path;
7279 gsize len, config_file_path_length, config_ext_length;
7282 domain = mono_domain_get ();
7283 file = domain->setup->configuration_file;
7284 if (!file || file->length == 0)
7287 // Retrieve config file and remove the extension
7288 config_file_name = mono_string_to_utf8 (file);
7289 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7290 if (!config_file_path)
7291 config_file_path = config_file_name;
7293 config_file_path_length = strlen (config_file_path);
7294 config_ext_length = strlen (".config");
7295 if (config_file_path_length <= config_ext_length)
7298 len = config_file_path_length - config_ext_length;
7299 module = (gchar *)g_malloc0 (len + 1);
7300 memcpy (module, config_file_path, len);
7301 // Get the config file from the module name
7302 app_config = mono_config_string_for_assembly_file (module);
7305 if (config_file_name != config_file_path)
7306 g_free (config_file_name);
7307 g_free (config_file_path);
7312 return mono_string_new (mono_domain_get (), app_config);
7316 get_bundled_machine_config (void)
7318 const gchar *machine_config;
7320 machine_config = mono_get_machine_config ();
7322 if (!machine_config)
7325 return mono_string_new (mono_domain_get (), machine_config);
7328 ICALL_EXPORT MonoString *
7329 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7334 path = g_path_get_dirname (mono_get_config_dir ());
7336 #if defined (HOST_WIN32)
7337 /* Avoid mixing '/' and '\\' */
7340 for (i = strlen (path) - 1; i >= 0; i--)
7341 if (path [i] == '/')
7345 ipath = mono_string_new (mono_domain_get (), path);
7351 ICALL_EXPORT gboolean
7352 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7354 MonoPEResourceDataEntry *entry;
7357 if (!assembly || !result || !size)
7362 image = assembly->assembly->image;
7363 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7367 *result = mono_image_rva_map (image, entry->rde_data_offset);
7372 *size = entry->rde_size;
7377 ICALL_EXPORT MonoBoolean
7378 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7380 return mono_is_debugger_attached ();
7383 ICALL_EXPORT MonoBoolean
7384 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7386 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7387 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7393 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7395 if (mono_get_runtime_callbacks ()->debug_log)
7396 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7400 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7402 #if defined (HOST_WIN32)
7403 OutputDebugString (mono_string_chars (message));
7405 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7409 /* Only used for value types */
7410 ICALL_EXPORT MonoObject *
7411 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7418 domain = mono_object_domain (type);
7419 klass = mono_class_from_mono_type (type->type);
7420 mono_class_init_checked (klass, &error);
7421 mono_error_raise_exception (&error);
7423 if (mono_class_is_nullable (klass))
7424 /* No arguments -> null */
7427 result = mono_object_new_checked (domain, klass, &error);
7428 mono_error_raise_exception (&error);
7432 ICALL_EXPORT MonoReflectionMethod *
7433 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7435 MonoReflectionMethod *ret = NULL;
7438 MonoClass *klass, *parent;
7439 MonoGenericContext *generic_inst = NULL;
7440 MonoMethod *method = m->method;
7441 MonoMethod *result = NULL;
7444 if (method->klass == NULL)
7447 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7448 MONO_CLASS_IS_INTERFACE (method->klass) ||
7449 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7452 slot = mono_method_get_vtable_slot (method);
7456 klass = method->klass;
7457 if (klass->generic_class) {
7458 generic_inst = mono_class_get_context (klass);
7459 klass = klass->generic_class->container_class;
7463 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7464 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7465 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7466 or klass is the generic container class and generic_inst is the instantiation.
7468 when we go to the parent, if the parent is an open constructed type, we need to
7469 replace the type parameters by the definitions from the generic_inst, and then take it
7470 apart again into the klass and the generic_inst.
7472 For cases like this:
7473 class C<T> : B<T, int> {
7474 public override void Foo () { ... }
7476 class B<U,V> : A<HashMap<U,V>> {
7477 public override void Foo () { ... }
7480 public virtual void Foo () { ... }
7483 if at each iteration the parent isn't open, we can skip inflating it. if at some
7484 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7487 MonoGenericContext *parent_inst = NULL;
7488 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7490 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7491 if (!mono_error_ok (&error)) {
7492 mono_error_set_pending_exception (&error);
7496 if (parent->generic_class) {
7497 parent_inst = mono_class_get_context (parent);
7498 parent = parent->generic_class->container_class;
7501 mono_class_setup_vtable (parent);
7502 if (parent->vtable_size <= slot)
7505 generic_inst = parent_inst;
7508 klass = klass->parent;
7511 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7512 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7513 if (!mono_error_ok (&error)) {
7514 mono_error_set_pending_exception (&error);
7518 generic_inst = NULL;
7520 if (klass->generic_class) {
7521 generic_inst = mono_class_get_context (klass);
7522 klass = klass->generic_class->container_class;
7528 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7529 if (!mono_error_ok (&error)) {
7530 mono_error_set_pending_exception (&error);
7535 if (klass == method->klass)
7538 /*This is possible if definition == FALSE.
7539 * Do it here to be really sure we don't read invalid memory.
7541 if (slot >= klass->vtable_size)
7544 mono_class_setup_vtable (klass);
7546 result = klass->vtable [slot];
7547 if (result == NULL) {
7548 /* It is an abstract method */
7549 gpointer iter = NULL;
7550 while ((result = mono_class_get_methods (klass, &iter)))
7551 if (result->slot == slot)
7558 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7559 mono_error_raise_exception (&error);
7563 ICALL_EXPORT MonoString*
7564 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7566 MonoMethod *method = m->method;
7568 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7573 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7575 iter->sig = *(MonoMethodSignature**)argsp;
7577 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7578 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7581 /* FIXME: it's not documented what start is exactly... */
7585 iter->args = argsp + sizeof (gpointer);
7587 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7589 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7592 ICALL_EXPORT MonoTypedRef
7593 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7595 guint32 i, arg_size;
7599 i = iter->sig->sentinelpos + iter->next_arg;
7601 g_assert (i < iter->sig->param_count);
7603 res.type = iter->sig->params [i];
7604 res.klass = mono_class_from_mono_type (res.type);
7605 arg_size = mono_type_stack_size (res.type, &align);
7606 #if defined(__arm__) || defined(__mips__)
7607 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7609 res.value = iter->args;
7610 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7611 /* Values are stored as 8 byte register sized objects, but 'value'
7612 * is dereferenced as a pointer in other routines.
7614 res.value = (char*)res.value + 4;
7616 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7617 if (arg_size <= sizeof (gpointer)) {
7619 int padding = arg_size - mono_type_size (res.type, &dummy);
7620 res.value = (guint8*)res.value + padding;
7623 iter->args = (char*)iter->args + arg_size;
7626 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7631 ICALL_EXPORT MonoTypedRef
7632 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7634 guint32 i, arg_size;
7638 i = iter->sig->sentinelpos + iter->next_arg;
7640 g_assert (i < iter->sig->param_count);
7642 while (i < iter->sig->param_count) {
7643 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7645 res.type = iter->sig->params [i];
7646 res.klass = mono_class_from_mono_type (res.type);
7647 /* FIXME: endianess issue... */
7648 arg_size = mono_type_stack_size (res.type, &align);
7649 #if defined(__arm__) || defined(__mips__)
7650 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7652 res.value = iter->args;
7653 iter->args = (char*)iter->args + arg_size;
7655 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7658 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7666 ICALL_EXPORT MonoType*
7667 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7671 i = iter->sig->sentinelpos + iter->next_arg;
7673 g_assert (i < iter->sig->param_count);
7675 return iter->sig->params [i];
7678 ICALL_EXPORT MonoObject*
7679 mono_TypedReference_ToObject (MonoTypedRef* tref)
7682 MonoObject *result = NULL;
7683 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7684 MonoObject** objp = (MonoObject **)tref->value;
7688 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7689 mono_error_set_pending_exception (&error);
7693 ICALL_EXPORT MonoTypedRef
7694 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7697 MonoReflectionField *f;
7699 MonoType *ftype = NULL;
7703 memset (&res, 0, sizeof (res));
7706 g_assert (mono_array_length (fields) > 0);
7708 klass = target->vtable->klass;
7710 for (i = 0; i < mono_array_length (fields); ++i) {
7711 f = mono_array_get (fields, MonoReflectionField*, i);
7713 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7716 if (f->field->parent != klass) {
7717 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7721 p = (guint8*)target + f->field->offset;
7723 p += f->field->offset - sizeof (MonoObject);
7724 klass = mono_class_from_mono_type (f->field->type);
7725 ftype = f->field->type;
7729 res.klass = mono_class_from_mono_type (ftype);
7736 prelink_method (MonoMethod *method, MonoError *error)
7738 const char *exc_class, *exc_arg;
7740 mono_error_init (error);
7741 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7743 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7745 mono_error_set_exception_instance (error,
7746 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7749 /* create the wrapper, too? */
7753 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7757 prelink_method (method->method, &error);
7758 mono_error_raise_exception (&error);
7762 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7765 MonoClass *klass = mono_class_from_mono_type (type->type);
7767 gpointer iter = NULL;
7769 mono_class_init_checked (klass, &error);
7770 mono_error_raise_exception (&error);
7772 while ((m = mono_class_get_methods (klass, &iter))) {
7773 prelink_method (m, &error);
7774 mono_error_raise_exception (&error);
7778 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7780 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7781 gint32 const **exponents,
7782 gunichar2 const **digitLowerTable,
7783 gunichar2 const **digitUpperTable,
7784 gint64 const **tenPowersList,
7785 gint32 const **decHexDigits)
7787 *mantissas = Formatter_MantissaBitsTable;
7788 *exponents = Formatter_TensExponentTable;
7789 *digitLowerTable = Formatter_DigitLowerTable;
7790 *digitUpperTable = Formatter_DigitUpperTable;
7791 *tenPowersList = Formatter_TenPowersList;
7792 *decHexDigits = Formatter_DecHexDigits;
7796 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7797 * and avoid useless allocations.
7800 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7802 MonoReflectionType *rt;
7806 mono_error_init (error);
7807 for (i = 0; i < type->num_mods; ++i) {
7808 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7813 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7815 for (i = 0; i < type->num_mods; ++i) {
7816 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7817 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7818 return_val_if_nok (error, NULL);
7820 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7821 return_val_if_nok (error, NULL);
7823 mono_array_setref (res, count, rt);
7830 ICALL_EXPORT MonoArray*
7831 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7834 MonoType *type = param->ClassImpl->type;
7835 MonoClass *member_class = mono_object_class (param->MemberImpl);
7836 MonoMethod *method = NULL;
7839 MonoMethodSignature *sig;
7842 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7843 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7844 method = rmethod->method;
7845 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7846 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7847 if (!(method = prop->property->get))
7848 method = prop->property->set;
7851 char *type_name = mono_type_get_full_name (member_class);
7852 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7853 MonoException *ex = mono_get_exception_not_supported (msg);
7856 mono_set_pending_exception (ex);
7860 image = method->klass->image;
7861 pos = param->PositionImpl;
7862 sig = mono_method_signature (method);
7866 type = sig->params [pos];
7868 res = type_array_from_modifiers (image, type, optional, &error);
7869 mono_error_raise_exception (&error);
7874 get_property_type (MonoProperty *prop)
7876 MonoMethodSignature *sig;
7878 sig = mono_method_signature (prop->get);
7880 } else if (prop->set) {
7881 sig = mono_method_signature (prop->set);
7882 return sig->params [sig->param_count - 1];
7887 ICALL_EXPORT MonoArray*
7888 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7891 MonoType *type = get_property_type (property->property);
7892 MonoImage *image = property->klass->image;
7897 res = type_array_from_modifiers (image, type, optional, &error);
7898 mono_error_raise_exception (&error);
7903 *Construct a MonoType suited to be used to decode a constant blob object.
7905 * @type is the target type which will be constructed
7906 * @blob_type is the blob type, for example, that comes from the constant table
7907 * @real_type is the expected constructed type.
7910 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7912 type->type = blob_type;
7913 type->data.klass = NULL;
7914 if (blob_type == MONO_TYPE_CLASS)
7915 type->data.klass = mono_defaults.object_class;
7916 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7917 /* For enums, we need to use the base type */
7918 type->type = MONO_TYPE_VALUETYPE;
7919 type->data.klass = mono_class_from_mono_type (real_type);
7921 type->data.klass = mono_class_from_mono_type (real_type);
7924 ICALL_EXPORT MonoObject*
7925 property_info_get_default_value (MonoReflectionProperty *property)
7929 MonoProperty *prop = property->property;
7930 MonoType *type = get_property_type (prop);
7931 MonoDomain *domain = mono_object_domain (property);
7932 MonoTypeEnum def_type;
7933 const char *def_value;
7936 mono_class_init (prop->parent);
7938 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7939 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7943 def_value = mono_class_get_property_default_value (prop, &def_type);
7945 mono_type_from_blob_type (&blob_type, def_type, type);
7946 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7948 mono_error_set_pending_exception (&error);
7952 ICALL_EXPORT MonoBoolean
7953 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7956 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7957 MonoCustomAttrInfo *cinfo;
7960 mono_class_init_checked (attr_class, &error);
7961 mono_error_raise_exception (&error);
7963 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7964 if (!is_ok (&error)) {
7965 mono_error_set_pending_exception (&error);
7970 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7972 mono_custom_attrs_free (cinfo);
7976 ICALL_EXPORT MonoArray*
7977 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7979 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7984 mono_class_init_checked (attr_class, &error);
7985 mono_error_raise_exception (&error);
7988 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7989 if (!mono_error_ok (&error)) {
7990 mono_error_set_pending_exception (&error);
7997 ICALL_EXPORT MonoArray*
7998 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8002 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8003 mono_error_set_pending_exception (&error);
8008 ICALL_EXPORT MonoString*
8009 ves_icall_Mono_Runtime_GetDisplayName (void)
8012 MonoString *display_name;
8014 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8015 display_name = mono_string_new (mono_domain_get (), info);
8017 return display_name;
8020 ICALL_EXPORT MonoString*
8021 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8024 MonoString *message;
8028 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8029 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8032 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8034 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8035 mono_error_raise_exception (&error);
8041 ICALL_EXPORT gpointer
8042 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8044 return GetCurrentProcess ();
8047 ICALL_EXPORT MonoBoolean
8048 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8050 return GetExitCodeProcess (handle, (guint32*) exitcode);
8053 ICALL_EXPORT MonoBoolean
8054 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8056 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8057 return CloseHandle (handle);
8059 return CloseProcess (handle);
8063 ICALL_EXPORT MonoBoolean
8064 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8066 return TerminateProcess (handle, exitcode);
8070 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8072 return WaitForInputIdle (handle, milliseconds);
8075 ICALL_EXPORT MonoBoolean
8076 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8078 return GetProcessWorkingSetSize (handle, min, max);
8081 ICALL_EXPORT MonoBoolean
8082 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8084 return SetProcessWorkingSetSize (handle, min, max);
8087 ICALL_EXPORT MonoBoolean
8088 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8090 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8094 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8096 return mono_process_current_pid ();
8100 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8102 return GetPriorityClass (handle);
8105 ICALL_EXPORT MonoBoolean
8106 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8108 return SetPriorityClass (handle, priorityClass);
8111 #ifndef DISABLE_ICALL_TABLES
8113 #define ICALL_TYPE(id,name,first)
8114 #define ICALL(id,name,func) Icall_ ## id,
8117 #include "metadata/icall-def.h"
8123 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8124 #define ICALL(id,name,func)
8126 #include "metadata/icall-def.h"
8132 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8133 #define ICALL(id,name,func)
8135 guint16 first_icall;
8138 static const IcallTypeDesc
8139 icall_type_descs [] = {
8140 #include "metadata/icall-def.h"
8144 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8147 #define ICALL_TYPE(id,name,first)
8150 #ifdef HAVE_ARRAY_ELEM_INIT
8151 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8152 #define MSGSTRFIELD1(line) str##line
8154 static const struct msgstrtn_t {
8155 #define ICALL(id,name,func)
8157 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8158 #include "metadata/icall-def.h"
8160 } icall_type_names_str = {
8161 #define ICALL_TYPE(id,name,first) (name),
8162 #include "metadata/icall-def.h"
8165 static const guint16 icall_type_names_idx [] = {
8166 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8167 #include "metadata/icall-def.h"
8170 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8172 static const struct msgstr_t {
8174 #define ICALL_TYPE(id,name,first)
8175 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8176 #include "metadata/icall-def.h"
8178 } icall_names_str = {
8179 #define ICALL(id,name,func) (name),
8180 #include "metadata/icall-def.h"
8183 static const guint16 icall_names_idx [] = {
8184 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8185 #include "metadata/icall-def.h"
8188 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8194 #define ICALL_TYPE(id,name,first) name,
8195 #define ICALL(id,name,func)
8196 static const char* const
8197 icall_type_names [] = {
8198 #include "metadata/icall-def.h"
8202 #define icall_type_name_get(id) (icall_type_names [(id)])
8206 #define ICALL_TYPE(id,name,first)
8207 #define ICALL(id,name,func) name,
8208 static const char* const
8210 #include "metadata/icall-def.h"
8213 #define icall_name_get(id) icall_names [(id)]
8215 #endif /* !HAVE_ARRAY_ELEM_INIT */
8219 #define ICALL_TYPE(id,name,first)
8220 #define ICALL(id,name,func) func,
8221 static const gconstpointer
8222 icall_functions [] = {
8223 #include "metadata/icall-def.h"
8227 #ifdef ENABLE_ICALL_SYMBOL_MAP
8230 #define ICALL_TYPE(id,name,first)
8231 #define ICALL(id,name,func) #func,
8232 static const gconstpointer
8233 icall_symbols [] = {
8234 #include "metadata/icall-def.h"
8239 #endif /* DISABLE_ICALL_TABLES */
8241 static mono_mutex_t icall_mutex;
8242 static GHashTable *icall_hash = NULL;
8243 static GHashTable *jit_icall_hash_name = NULL;
8244 static GHashTable *jit_icall_hash_addr = NULL;
8247 mono_icall_init (void)
8249 #ifndef DISABLE_ICALL_TABLES
8252 /* check that tables are sorted: disable in release */
8255 const char *prev_class = NULL;
8256 const char *prev_method;
8258 for (i = 0; i < Icall_type_num; ++i) {
8259 const IcallTypeDesc *desc;
8262 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8263 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8264 prev_class = icall_type_name_get (i);
8265 desc = &icall_type_descs [i];
8266 num_icalls = icall_desc_num_icalls (desc);
8267 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8268 for (j = 0; j < num_icalls; ++j) {
8269 const char *methodn = icall_name_get (desc->first_icall + j);
8270 if (prev_method && strcmp (prev_method, methodn) >= 0)
8271 g_print ("method %s should come before method %s\n", methodn, prev_method);
8272 prev_method = methodn;
8278 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8279 mono_os_mutex_init (&icall_mutex);
8283 mono_icall_lock (void)
8285 mono_locks_os_acquire (&icall_mutex, IcallLock);
8289 mono_icall_unlock (void)
8291 mono_locks_os_release (&icall_mutex, IcallLock);
8295 mono_icall_cleanup (void)
8297 g_hash_table_destroy (icall_hash);
8298 g_hash_table_destroy (jit_icall_hash_name);
8299 g_hash_table_destroy (jit_icall_hash_addr);
8300 mono_os_mutex_destroy (&icall_mutex);
8304 * mono_add_internal_call:
8305 * @name: method specification to surface to the managed world
8306 * @method: pointer to a C method to invoke when the method is called
8308 * This method surfaces the C function pointed by @method as a method
8309 * that has been surfaced in managed code with the method specified in
8310 * @name as an internal call.
8312 * Internal calls are surfaced to all app domains loaded and they are
8313 * accessibly by a type with the specified name.
8315 * You must provide a fully qualified type name, that is namespaces
8316 * and type name, followed by a colon and the method name, with an
8317 * optional signature to bind.
8319 * For example, the following are all valid declarations:
8321 * "MyApp.Services.ScriptService:Accelerate"
8322 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8324 * You use method parameters in cases where there might be more than
8325 * one surface method to managed code. That way you can register different
8326 * internal calls for different method overloads.
8328 * The internal calls are invoked with no marshalling. This means that .NET
8329 * types like System.String are exposed as `MonoString *` parameters. This is
8330 * different than the way that strings are surfaced in P/Invoke.
8332 * For more information on how the parameters are marshalled, see the
8333 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8336 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8337 * reference for more information on the format of method descriptions.
8340 mono_add_internal_call (const char *name, gconstpointer method)
8344 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8346 mono_icall_unlock ();
8349 #ifndef DISABLE_ICALL_TABLES
8351 #ifdef HAVE_ARRAY_ELEM_INIT
8353 compare_method_imap (const void *key, const void *elem)
8355 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8356 return strcmp (key, method_name);
8360 find_method_icall (const IcallTypeDesc *imap, const char *name)
8362 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);
8365 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8369 compare_class_imap (const void *key, const void *elem)
8371 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8372 return strcmp (key, class_name);
8375 static const IcallTypeDesc*
8376 find_class_icalls (const char *name)
8378 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);
8381 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8384 #else /* HAVE_ARRAY_ELEM_INIT */
8387 compare_method_imap (const void *key, const void *elem)
8389 const char** method_name = (const char**)elem;
8390 return strcmp (key, *method_name);
8394 find_method_icall (const IcallTypeDesc *imap, const char *name)
8396 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8399 return (gpointer)icall_functions [(nameslot - icall_names)];
8403 compare_class_imap (const void *key, const void *elem)
8405 const char** class_name = (const char**)elem;
8406 return strcmp (key, *class_name);
8409 static const IcallTypeDesc*
8410 find_class_icalls (const char *name)
8412 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8415 return &icall_type_descs [nameslot - icall_type_names];
8418 #endif /* HAVE_ARRAY_ELEM_INIT */
8420 #endif /* DISABLE_ICALL_TABLES */
8423 * we should probably export this as an helper (handle nested types).
8424 * Returns the number of chars written in buf.
8427 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8429 int nspacelen, cnamelen;
8430 nspacelen = strlen (klass->name_space);
8431 cnamelen = strlen (klass->name);
8432 if (nspacelen + cnamelen + 2 > bufsize)
8435 memcpy (buf, klass->name_space, nspacelen);
8436 buf [nspacelen ++] = '.';
8438 memcpy (buf + nspacelen, klass->name, cnamelen);
8439 buf [nspacelen + cnamelen] = 0;
8440 return nspacelen + cnamelen;
8443 #ifdef DISABLE_ICALL_TABLES
8445 no_icall_table (void)
8447 g_assert_not_reached ();
8452 mono_lookup_internal_call (MonoMethod *method)
8457 int typelen = 0, mlen, siglen;
8459 #ifndef DISABLE_ICALL_TABLES
8460 const IcallTypeDesc *imap = NULL;
8463 g_assert (method != NULL);
8465 if (method->is_inflated)
8466 method = ((MonoMethodInflated *) method)->declaring;
8468 if (method->klass->nested_in) {
8469 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8473 mname [pos++] = '/';
8476 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8482 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8487 #ifndef DISABLE_ICALL_TABLES
8488 imap = find_class_icalls (mname);
8491 mname [typelen] = ':';
8492 mname [typelen + 1] = ':';
8494 mlen = strlen (method->name);
8495 memcpy (mname + typelen + 2, method->name, mlen);
8496 sigstart = mname + typelen + 2 + mlen;
8499 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8500 siglen = strlen (tmpsig);
8501 if (typelen + mlen + siglen + 6 > sizeof (mname))
8504 memcpy (sigstart + 1, tmpsig, siglen);
8505 sigstart [siglen + 1] = ')';
8506 sigstart [siglen + 2] = 0;
8511 res = g_hash_table_lookup (icall_hash, mname);
8513 mono_icall_unlock ();;
8516 /* try without signature */
8518 res = g_hash_table_lookup (icall_hash, mname);
8520 mono_icall_unlock ();
8524 #ifdef DISABLE_ICALL_TABLES
8525 mono_icall_unlock ();
8526 /* Fail only when the result is actually used */
8527 /* mono_marshal_get_native_wrapper () depends on this */
8528 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8529 return ves_icall_System_String_ctor_RedirectToCreateString;
8531 return no_icall_table;
8533 /* it wasn't found in the static call tables */
8535 mono_icall_unlock ();
8538 res = find_method_icall (imap, sigstart - mlen);
8540 mono_icall_unlock ();
8543 /* try _with_ signature */
8545 res = find_method_icall (imap, sigstart - mlen);
8547 mono_icall_unlock ();
8551 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8552 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8553 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8554 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8555 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");
8556 g_print ("If you see other errors or faults after this message they are probably related\n");
8557 g_print ("and you need to fix your mono install first.\n");
8559 mono_icall_unlock ();
8565 #ifdef ENABLE_ICALL_SYMBOL_MAP
8567 func_cmp (gconstpointer key, gconstpointer p)
8569 return (gsize)key - (gsize)*(gsize*)p;
8574 * mono_lookup_icall_symbol:
8576 * Given the icall METHOD, returns its C symbol.
8579 mono_lookup_icall_symbol (MonoMethod *m)
8581 #ifdef DISABLE_ICALL_TABLES
8582 g_assert_not_reached ();
8585 #ifdef ENABLE_ICALL_SYMBOL_MAP
8589 static gconstpointer *functions_sorted;
8590 static const char**symbols_sorted;
8591 static gboolean inited;
8596 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8597 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8598 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8599 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8600 /* Bubble sort the two arrays */
8604 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8605 if (functions_sorted [i] > functions_sorted [i + 1]) {
8608 tmp = functions_sorted [i];
8609 functions_sorted [i] = functions_sorted [i + 1];
8610 functions_sorted [i + 1] = tmp;
8611 tmp = symbols_sorted [i];
8612 symbols_sorted [i] = symbols_sorted [i + 1];
8613 symbols_sorted [i + 1] = tmp;
8620 func = mono_lookup_internal_call (m);
8623 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8627 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8629 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8630 g_assert_not_reached ();
8637 type_from_typename (char *type_name)
8639 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8641 if (!strcmp (type_name, "int"))
8642 klass = mono_defaults.int_class;
8643 else if (!strcmp (type_name, "ptr"))
8644 klass = mono_defaults.int_class;
8645 else if (!strcmp (type_name, "void"))
8646 klass = mono_defaults.void_class;
8647 else if (!strcmp (type_name, "int32"))
8648 klass = mono_defaults.int32_class;
8649 else if (!strcmp (type_name, "uint32"))
8650 klass = mono_defaults.uint32_class;
8651 else if (!strcmp (type_name, "int8"))
8652 klass = mono_defaults.sbyte_class;
8653 else if (!strcmp (type_name, "uint8"))
8654 klass = mono_defaults.byte_class;
8655 else if (!strcmp (type_name, "int16"))
8656 klass = mono_defaults.int16_class;
8657 else if (!strcmp (type_name, "uint16"))
8658 klass = mono_defaults.uint16_class;
8659 else if (!strcmp (type_name, "long"))
8660 klass = mono_defaults.int64_class;
8661 else if (!strcmp (type_name, "ulong"))
8662 klass = mono_defaults.uint64_class;
8663 else if (!strcmp (type_name, "float"))
8664 klass = mono_defaults.single_class;
8665 else if (!strcmp (type_name, "double"))
8666 klass = mono_defaults.double_class;
8667 else if (!strcmp (type_name, "object"))
8668 klass = mono_defaults.object_class;
8669 else if (!strcmp (type_name, "obj"))
8670 klass = mono_defaults.object_class;
8671 else if (!strcmp (type_name, "string"))
8672 klass = mono_defaults.string_class;
8673 else if (!strcmp (type_name, "bool"))
8674 klass = mono_defaults.boolean_class;
8675 else if (!strcmp (type_name, "boolean"))
8676 klass = mono_defaults.boolean_class;
8678 g_error ("%s", type_name);
8679 g_assert_not_reached ();
8681 return &klass->byval_arg;
8685 * LOCKING: Take the corlib image lock.
8687 MonoMethodSignature*
8688 mono_create_icall_signature (const char *sigstr)
8693 MonoMethodSignature *res, *res2;
8694 MonoImage *corlib = mono_defaults.corlib;
8696 mono_image_lock (corlib);
8697 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8698 mono_image_unlock (corlib);
8703 parts = g_strsplit (sigstr, " ", 256);
8712 res = mono_metadata_signature_alloc (corlib, len - 1);
8717 * Under windows, the default pinvoke calling convention is STDCALL but
8720 res->call_convention = MONO_CALL_C;
8723 res->ret = type_from_typename (parts [0]);
8724 for (i = 1; i < len; ++i) {
8725 res->params [i - 1] = type_from_typename (parts [i]);
8730 mono_image_lock (corlib);
8731 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8733 res = res2; /*Value is allocated in the image pool*/
8735 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8736 mono_image_unlock (corlib);
8742 mono_find_jit_icall_by_name (const char *name)
8744 MonoJitICallInfo *info;
8745 g_assert (jit_icall_hash_name);
8748 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8749 mono_icall_unlock ();
8754 mono_find_jit_icall_by_addr (gconstpointer addr)
8756 MonoJitICallInfo *info;
8757 g_assert (jit_icall_hash_addr);
8760 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8761 mono_icall_unlock ();
8767 * mono_get_jit_icall_info:
8769 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8770 * caller should access it while holding the icall lock.
8773 mono_get_jit_icall_info (void)
8775 return jit_icall_hash_name;
8779 * mono_lookup_jit_icall_symbol:
8781 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8784 mono_lookup_jit_icall_symbol (const char *name)
8786 MonoJitICallInfo *info;
8787 const char *res = NULL;
8790 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8792 res = info->c_symbol;
8793 mono_icall_unlock ();
8798 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8801 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8802 mono_icall_unlock ();
8806 * 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
8807 * icalls without wrappers in some cases.
8810 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8812 MonoJitICallInfo *info;
8819 if (!jit_icall_hash_name) {
8820 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8821 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8824 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8825 g_warning ("jit icall already defined \"%s\"\n", name);
8826 g_assert_not_reached ();
8829 info = g_new0 (MonoJitICallInfo, 1);
8834 info->c_symbol = c_symbol;
8835 info->no_raise = no_raise;
8838 info->wrapper = func;
8840 info->wrapper = NULL;
8843 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8844 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8846 mono_icall_unlock ();
8851 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8853 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);