5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
9 * Aleksey Kliger (aleksey@xamarin.com)
11 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
12 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
14 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
25 #ifdef HAVE_SYS_TIME_H
31 #if defined (HOST_WIN32)
34 #if defined (HAVE_WCHAR_H)
38 #include "mono/utils/mono-membar.h"
39 #include <mono/metadata/object.h>
40 #include <mono/metadata/threads.h>
41 #include <mono/metadata/threads-types.h>
42 #include <mono/metadata/threadpool-ms.h>
43 #include <mono/metadata/threadpool-ms-io.h>
44 #include <mono/metadata/monitor.h>
45 #include <mono/metadata/reflection.h>
46 #include <mono/metadata/assembly.h>
47 #include <mono/metadata/tabledefs.h>
48 #include <mono/metadata/exception.h>
49 #include <mono/metadata/exception-internals.h>
50 #include <mono/metadata/file-io.h>
51 #include <mono/metadata/console-io.h>
52 #include <mono/metadata/mono-route.h>
53 #include <mono/metadata/socket-io.h>
54 #include <mono/metadata/mono-endian.h>
55 #include <mono/metadata/tokentype.h>
56 #include <mono/metadata/domain-internals.h>
57 #include <mono/metadata/metadata-internals.h>
58 #include <mono/metadata/class-internals.h>
59 #include <mono/metadata/reflection-internals.h>
60 #include <mono/metadata/marshal.h>
61 #include <mono/metadata/gc-internals.h>
62 #include <mono/metadata/mono-gc.h>
63 #include <mono/metadata/rand.h>
64 #include <mono/metadata/sysmath.h>
65 #include <mono/metadata/string-icalls.h>
66 #include <mono/metadata/debug-helpers.h>
67 #include <mono/metadata/process.h>
68 #include <mono/metadata/environment.h>
69 #include <mono/metadata/profiler-private.h>
70 #include <mono/metadata/locales.h>
71 #include <mono/metadata/filewatcher.h>
72 #include <mono/metadata/security.h>
73 #include <mono/metadata/mono-config.h>
74 #include <mono/metadata/cil-coff.h>
75 #include <mono/metadata/number-formatter.h>
76 #include <mono/metadata/security-manager.h>
77 #include <mono/metadata/security-core-clr.h>
78 #include <mono/metadata/mono-perfcounters.h>
79 #include <mono/metadata/mono-debug.h>
80 #include <mono/metadata/mono-ptr-array.h>
81 #include <mono/metadata/verify-internals.h>
82 #include <mono/metadata/runtime.h>
83 #include <mono/metadata/file-mmap.h>
84 #include <mono/metadata/seq-points-data.h>
85 #include <mono/io-layer/io-layer.h>
86 #include <mono/utils/monobitset.h>
87 #include <mono/utils/mono-time.h>
88 #include <mono/utils/mono-proclib.h>
89 #include <mono/utils/mono-string.h>
90 #include <mono/utils/mono-error-internals.h>
91 #include <mono/utils/mono-mmap.h>
92 #include <mono/utils/mono-io-portability.h>
93 #include <mono/utils/mono-digest.h>
94 #include <mono/utils/bsearch.h>
95 #include <mono/utils/mono-os-mutex.h>
96 #include <mono/utils/mono-threads.h>
98 #if defined (HOST_WIN32)
102 #include "decimal-ms.h"
103 #include "number-ms.h"
105 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
106 #include <sys/utsname.h>
109 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
111 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
113 /* Lazy class loading functions */
114 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
115 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
116 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
119 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
122 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
124 static inline MonoBoolean
125 is_generic_parameter (MonoType *type)
127 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
131 mono_class_init_checked (MonoClass *klass, MonoError *error)
133 mono_error_init (error);
135 if (!mono_class_init (klass))
136 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
139 ICALL_EXPORT MonoObject *
140 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
146 MonoObject *result = NULL;
148 ac = (MonoClass *)arr->obj.vtable->klass;
150 esize = mono_array_element_size (ac);
151 ea = (gpointer*)((char*)arr->vector + (pos * esize));
153 if (ac->element_class->valuetype) {
154 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
155 mono_error_set_pending_exception (&error);
157 result = (MonoObject *)*ea;
161 ICALL_EXPORT MonoObject *
162 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
168 MONO_CHECK_ARG_NULL (idxs, NULL);
171 ic = (MonoClass *)io->obj.vtable->klass;
173 ac = (MonoClass *)arr->obj.vtable->klass;
175 g_assert (ic->rank == 1);
176 if (io->bounds != NULL || io->max_length != ac->rank) {
177 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
181 ind = (gint32 *)io->vector;
183 if (arr->bounds == NULL) {
184 if (*ind < 0 || *ind >= arr->max_length) {
185 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
189 return ves_icall_System_Array_GetValueImpl (arr, *ind);
192 for (i = 0; i < ac->rank; i++) {
193 if ((ind [i] < arr->bounds [i].lower_bound) ||
194 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
195 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
200 pos = ind [0] - arr->bounds [0].lower_bound;
201 for (i = 1; i < ac->rank; i++)
202 pos = pos * arr->bounds [i].length + ind [i] -
203 arr->bounds [i].lower_bound;
205 return ves_icall_System_Array_GetValueImpl (arr, pos);
209 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
212 MonoClass *ac, *vc, *ec;
221 mono_error_init (&error);
224 vc = value->vtable->klass;
228 ac = arr->obj.vtable->klass;
229 ec = ac->element_class;
231 esize = mono_array_element_size (ac);
232 ea = (gpointer*)((char*)arr->vector + (pos * esize));
233 va = (gpointer*)((char*)value + sizeof (MonoObject));
235 if (mono_class_is_nullable (ec)) {
236 mono_nullable_init ((guint8*)ea, value, ec);
241 mono_gc_bzero_atomic (ea, esize);
245 #define NO_WIDENING_CONVERSION G_STMT_START{\
246 mono_set_pending_exception (mono_get_exception_argument ( \
247 "value", "not a widening conversion")); \
251 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
252 if (esize < vsize + (extra)) { \
253 mono_set_pending_exception (mono_get_exception_argument ( \
254 "value", "not a widening conversion")); \
259 #define INVALID_CAST G_STMT_START{ \
260 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
261 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
265 /* Check element (destination) type. */
266 switch (ec->byval_arg.type) {
267 case MONO_TYPE_STRING:
268 switch (vc->byval_arg.type) {
269 case MONO_TYPE_STRING:
275 case MONO_TYPE_BOOLEAN:
276 switch (vc->byval_arg.type) {
277 case MONO_TYPE_BOOLEAN:
290 NO_WIDENING_CONVERSION;
299 if (!ec->valuetype) {
300 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
301 if (mono_error_set_pending_exception (&error))
305 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
309 if (mono_object_isinst_checked (value, ec, &error)) {
310 if (ec->has_references)
311 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
313 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
316 if (mono_error_set_pending_exception (&error))
322 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
324 et = ec->byval_arg.type;
325 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
326 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
328 vt = vc->byval_arg.type;
329 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
330 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
332 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
338 case MONO_TYPE_CHAR: \
339 CHECK_WIDENING_CONVERSION(0); \
340 *(etype *) ea = (etype) u64; \
342 /* You can't assign a signed value to an unsigned array. */ \
347 /* You can't assign a floating point number to an integer array. */ \
350 NO_WIDENING_CONVERSION; \
354 #define ASSIGN_SIGNED(etype) G_STMT_START{\
360 CHECK_WIDENING_CONVERSION(0); \
361 *(etype *) ea = (etype) i64; \
363 /* You can assign an unsigned value to a signed array if the array's */ \
364 /* element size is larger than the value size. */ \
369 case MONO_TYPE_CHAR: \
370 CHECK_WIDENING_CONVERSION(1); \
371 *(etype *) ea = (etype) u64; \
373 /* You can't assign a floating point number to an integer array. */ \
376 NO_WIDENING_CONVERSION; \
380 #define ASSIGN_REAL(etype) G_STMT_START{\
384 CHECK_WIDENING_CONVERSION(0); \
385 *(etype *) ea = (etype) r64; \
387 /* All integer values fit into a floating point array, so we don't */ \
388 /* need to CHECK_WIDENING_CONVERSION here. */ \
393 *(etype *) ea = (etype) i64; \
399 case MONO_TYPE_CHAR: \
400 *(etype *) ea = (etype) u64; \
407 u64 = *(guint8 *) va;
410 u64 = *(guint16 *) va;
413 u64 = *(guint32 *) va;
416 u64 = *(guint64 *) va;
422 i64 = *(gint16 *) va;
425 i64 = *(gint32 *) va;
428 i64 = *(gint64 *) va;
431 r64 = *(gfloat *) va;
434 r64 = *(gdouble *) va;
437 u64 = *(guint16 *) va;
439 case MONO_TYPE_BOOLEAN:
440 /* Boolean is only compatible with itself. */
453 NO_WIDENING_CONVERSION;
460 /* If we can't do a direct copy, let's try a widening conversion. */
463 ASSIGN_UNSIGNED (guint16);
465 ASSIGN_UNSIGNED (guint8);
467 ASSIGN_UNSIGNED (guint16);
469 ASSIGN_UNSIGNED (guint32);
471 ASSIGN_UNSIGNED (guint64);
473 ASSIGN_SIGNED (gint8);
475 ASSIGN_SIGNED (gint16);
477 ASSIGN_SIGNED (gint32);
479 ASSIGN_SIGNED (gint64);
481 ASSIGN_REAL (gfloat);
483 ASSIGN_REAL (gdouble);
487 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
491 #undef NO_WIDENING_CONVERSION
492 #undef CHECK_WIDENING_CONVERSION
493 #undef ASSIGN_UNSIGNED
499 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
505 MONO_CHECK_ARG_NULL (idxs,);
507 ic = idxs->obj.vtable->klass;
508 ac = arr->obj.vtable->klass;
510 g_assert (ic->rank == 1);
511 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
512 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
516 ind = (gint32 *)idxs->vector;
518 if (arr->bounds == NULL) {
519 if (*ind < 0 || *ind >= arr->max_length) {
520 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
524 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
528 for (i = 0; i < ac->rank; i++)
529 if ((ind [i] < arr->bounds [i].lower_bound) ||
530 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
531 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
535 pos = ind [0] - arr->bounds [0].lower_bound;
536 for (i = 1; i < ac->rank; i++)
537 pos = pos * arr->bounds [i].length + ind [i] -
538 arr->bounds [i].lower_bound;
540 ves_icall_System_Array_SetValueImpl (arr, value, pos);
543 ICALL_EXPORT MonoArray *
544 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
547 MonoClass *aklass, *klass;
550 gboolean bounded = FALSE;
552 MONO_CHECK_ARG_NULL (type, NULL);
553 MONO_CHECK_ARG_NULL (lengths, NULL);
555 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
557 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
559 for (i = 0; i < mono_array_length (lengths); i++) {
560 if (mono_array_get (lengths, gint32, i) < 0) {
561 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
566 klass = mono_class_from_mono_type (type->type);
567 mono_class_init_checked (klass, &error);
568 mono_error_raise_exception (&error);
570 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
571 /* vectors are not the same as one dimensional arrays with no-zero bounds */
576 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
578 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
579 for (i = 0; i < aklass->rank; ++i) {
580 sizes [i] = mono_array_get (lengths, guint32, i);
582 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
584 sizes [i + aklass->rank] = 0;
587 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
588 mono_error_set_pending_exception (&error);
593 ICALL_EXPORT MonoArray *
594 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
597 MonoClass *aklass, *klass;
600 gboolean bounded = FALSE;
602 MONO_CHECK_ARG_NULL (type, NULL);
603 MONO_CHECK_ARG_NULL (lengths, NULL);
605 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
607 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
609 for (i = 0; i < mono_array_length (lengths); i++) {
610 if ((mono_array_get (lengths, gint64, i) < 0) ||
611 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
612 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
617 klass = mono_class_from_mono_type (type->type);
618 mono_class_init_checked (klass, &error);
619 mono_error_raise_exception (&error);
621 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
622 /* vectors are not the same as one dimensional arrays with no-zero bounds */
627 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
629 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
630 for (i = 0; i < aklass->rank; ++i) {
631 sizes [i] = mono_array_get (lengths, guint64, i);
633 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
635 sizes [i + aklass->rank] = 0;
638 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
639 mono_error_set_pending_exception (&error);
645 ves_icall_System_Array_GetRank (MonoObject *arr)
647 return arr->vtable->klass->rank;
651 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
653 gint32 rank = arr->obj.vtable->klass->rank;
656 if ((dimension < 0) || (dimension >= rank)) {
657 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
661 if (arr->bounds == NULL)
662 length = arr->max_length;
664 length = arr->bounds [dimension].length;
666 #ifdef MONO_BIG_ARRAYS
667 if (length > G_MAXINT32) {
668 mono_set_pending_exception (mono_get_exception_overflow ());
676 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
678 gint32 rank = arr->obj.vtable->klass->rank;
680 if ((dimension < 0) || (dimension >= rank)) {
681 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
685 if (arr->bounds == NULL)
686 return arr->max_length;
688 return arr->bounds [dimension].length;
692 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
694 gint32 rank = arr->obj.vtable->klass->rank;
696 if ((dimension < 0) || (dimension >= rank)) {
697 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
701 if (arr->bounds == NULL)
704 return arr->bounds [dimension].lower_bound;
708 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
710 int sz = mono_array_element_size (mono_object_class (arr));
711 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
714 ICALL_EXPORT gboolean
715 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
720 MonoVTable *src_vtable;
721 MonoVTable *dest_vtable;
722 MonoClass *src_class;
723 MonoClass *dest_class;
725 src_vtable = source->obj.vtable;
726 dest_vtable = dest->obj.vtable;
728 if (src_vtable->rank != dest_vtable->rank)
731 if (source->bounds || dest->bounds)
734 /* there's no integer overflow since mono_array_length returns an unsigned integer */
735 if ((dest_idx + length > mono_array_length_fast (dest)) ||
736 (source_idx + length > mono_array_length_fast (source)))
739 src_class = src_vtable->klass->element_class;
740 dest_class = dest_vtable->klass->element_class;
743 * Handle common cases.
746 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
747 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
749 if (src_class == mono_defaults.object_class && dest_class->valuetype)
752 /* Check if we're copying a char[] <==> (u)short[] */
753 if (src_class != dest_class) {
754 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
757 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
758 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
762 if (dest_class->valuetype) {
763 element_size = mono_array_element_size (source->obj.vtable->klass);
764 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
765 if (dest_class->has_references) {
766 mono_value_copy_array (dest, dest_idx, source_addr, length);
768 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
769 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
772 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
779 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
785 ac = (MonoClass *)arr->obj.vtable->klass;
787 esize = mono_array_element_size (ac);
788 ea = (gpointer*)((char*)arr->vector + (pos * esize));
790 mono_gc_memmove_atomic (value, ea, esize);
794 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
800 ac = (MonoClass *)arr->obj.vtable->klass;
801 ec = ac->element_class;
803 esize = mono_array_element_size (ac);
804 ea = (gpointer*)((char*)arr->vector + (pos * esize));
806 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
807 g_assert (esize == sizeof (gpointer));
808 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
810 g_assert (ec->inited);
811 g_assert (esize == mono_class_value_size (ec, NULL));
812 if (ec->has_references)
813 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
815 mono_gc_memmove_atomic (ea, value, esize);
820 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
822 MonoClass *klass = array->obj.vtable->klass;
823 guint32 size = mono_array_element_size (klass);
824 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
826 const char *field_data;
828 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
829 MonoException *exc = mono_get_exception_argument("array",
830 "Cannot initialize array of non-primitive type.");
831 mono_set_pending_exception (exc);
835 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
836 MonoException *exc = mono_get_exception_argument("field_handle",
837 "Field doesn't have an RVA");
838 mono_set_pending_exception (exc);
842 size *= array->max_length;
843 field_data = mono_field_get_data (field_handle);
845 if (size > mono_type_size (field_handle->type, &align)) {
846 MonoException *exc = mono_get_exception_argument("field_handle",
847 "Field not large enough to fill array");
848 mono_set_pending_exception (exc);
852 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
854 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
855 guint ## n *src = (guint ## n *) field_data; \
857 nEnt = (size / sizeof(guint ## n)); \
859 for (i = 0; i < nEnt; i++) { \
860 data[i] = read ## n (&src[i]); \
864 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
866 switch (type->type) {
883 memcpy (mono_array_addr (array, char, 0), field_data, size);
887 memcpy (mono_array_addr (array, char, 0), field_data, size);
892 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
894 return offsetof (MonoString, chars);
897 ICALL_EXPORT MonoObject *
898 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
900 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
904 MonoObject *ret = mono_object_clone_checked (obj, &error);
905 mono_error_set_pending_exception (&error);
912 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
918 MONO_CHECK_ARG_NULL (handle,);
920 klass = mono_class_from_mono_type (handle);
921 MONO_CHECK_ARG (handle, klass,);
923 if (klass->generic_container)
926 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
927 if (!is_ok (&error)) {
928 mono_error_set_pending_exception (&error);
932 /* This will call the type constructor */
933 if (!mono_runtime_class_init_full (vtable, &error))
934 mono_error_set_pending_exception (&error);
938 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
942 mono_image_check_for_module_cctor (image);
943 if (image->has_module_cctor) {
944 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
945 if (!mono_error_ok (&error)) {
946 mono_error_set_pending_exception (&error);
949 /*It's fine to raise the exception here*/
950 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
951 if (!is_ok (&error)) {
952 mono_error_set_pending_exception (&error);
955 if (!mono_runtime_class_init_full (vtable, &error))
956 mono_error_set_pending_exception (&error);
960 ICALL_EXPORT MonoBoolean
961 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
966 /* later make this configurable and per-arch */
967 int min_size = 4096 * 4 * sizeof (void*);
968 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
969 /* if we have no info we are optimistic and assume there is enough room */
973 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
977 current = (guint8 *)&stack_addr;
978 if (current > stack_addr) {
979 if ((current - stack_addr) < min_size)
982 if (current - (stack_addr - stack_size) < min_size)
988 ICALL_EXPORT MonoObject *
989 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
992 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
993 mono_error_set_pending_exception (&error);
999 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1003 MonoObject **values = NULL;
1006 gint32 result = (int)(gsize)mono_defaults.int32_class;
1007 MonoClassField* field;
1010 klass = mono_object_class (this_obj);
1012 if (mono_class_num_fields (klass) == 0)
1016 * Compute the starting value of the hashcode for fields of primitive
1017 * types, and return the remaining fields in an array to the managed side.
1018 * This way, we can avoid costly reflection operations in managed code.
1021 while ((field = mono_class_get_fields (klass, &iter))) {
1022 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1024 if (mono_field_is_deleted (field))
1026 /* FIXME: Add more types */
1027 switch (field->type->type) {
1029 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1031 case MONO_TYPE_STRING: {
1033 s = *(MonoString**)((guint8*)this_obj + field->offset);
1035 result ^= mono_string_hash (s);
1040 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1041 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1042 if (!is_ok (&error)) {
1043 mono_error_set_pending_exception (&error);
1046 values [count++] = o;
1052 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1053 for (i = 0; i < count; ++i)
1054 mono_array_setref (*fields, i, values [i]);
1061 ICALL_EXPORT MonoBoolean
1062 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1066 MonoObject **values = NULL;
1068 MonoClassField* field;
1072 MONO_CHECK_ARG_NULL (that, FALSE);
1074 if (this_obj->vtable != that->vtable)
1077 klass = mono_object_class (this_obj);
1079 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1080 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1083 * Do the comparison for fields of primitive type and return a result if
1084 * possible. Otherwise, return the remaining fields in an array to the
1085 * managed side. This way, we can avoid costly reflection operations in
1090 while ((field = mono_class_get_fields (klass, &iter))) {
1091 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1093 if (mono_field_is_deleted (field))
1095 /* FIXME: Add more types */
1096 switch (field->type->type) {
1099 case MONO_TYPE_BOOLEAN:
1100 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1105 case MONO_TYPE_CHAR:
1106 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1111 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1116 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1120 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1124 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1129 case MONO_TYPE_STRING: {
1130 MonoString *s1, *s2;
1131 guint32 s1len, s2len;
1132 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1133 s2 = *(MonoString**)((guint8*)that + field->offset);
1136 if ((s1 == NULL) || (s2 == NULL))
1138 s1len = mono_string_length (s1);
1139 s2len = mono_string_length (s2);
1143 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1149 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1150 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1151 if (!is_ok (&error)) {
1152 mono_error_set_pending_exception (&error);
1155 values [count++] = o;
1156 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1157 if (!is_ok (&error)) {
1158 mono_error_set_pending_exception (&error);
1161 values [count++] = o;
1164 if (klass->enumtype)
1165 /* enums only have one non-static field */
1171 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1172 for (i = 0; i < count; ++i)
1173 mono_array_setref_fast (*fields, i, values [i]);
1180 ICALL_EXPORT MonoReflectionType *
1181 ves_icall_System_Object_GetType (MonoObject *obj)
1184 MonoReflectionType *ret;
1185 #ifndef DISABLE_REMOTING
1186 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1187 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1190 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1192 mono_error_raise_exception (&error);
1198 ves_icall_MonoType_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1200 mtype->type = &obj->vtable->klass->byval_arg;
1201 g_assert (mtype->type->type);
1205 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1207 MONO_CHECK_ARG_NULL (obj, 0);
1210 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1211 mono_error_raise_exception (&error);
1216 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1217 MonoReflectionMethod *method,
1218 MonoArray *opt_param_types)
1220 MONO_CHECK_ARG_NULL (method, 0);
1223 gint32 result = mono_image_create_method_token (
1224 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1225 mono_error_raise_exception (&error);
1230 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1233 mono_image_create_pefile (mb, file, &error);
1234 mono_error_raise_exception (&error);
1238 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1241 if (!mono_image_build_metadata (mb, &error))
1242 mono_error_raise_exception (&error);
1246 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1248 mono_image_register_token (mb->dynamic_image, token, obj);
1251 ICALL_EXPORT MonoObject*
1252 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1256 mono_loader_lock ();
1257 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1258 mono_loader_unlock ();
1263 ICALL_EXPORT MonoReflectionModule*
1264 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1267 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1268 mono_error_set_pending_exception (&error);
1272 ICALL_EXPORT MonoArray*
1273 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
1276 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
1277 mono_error_set_pending_exception (&error);
1282 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1284 MonoMethod **dest = (MonoMethod **)data;
1286 /* skip unmanaged frames */
1302 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1304 MonoMethod **dest = (MonoMethod **)data;
1306 /* skip unmanaged frames */
1311 if (!strcmp (m->klass->name_space, "System.Reflection"))
1320 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1322 MonoMethod **dest = (MonoMethod **)data;
1324 /* skip unmanaged frames */
1328 if (m->wrapper_type != MONO_WRAPPER_NONE)
1331 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1345 static MonoReflectionType *
1346 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1348 MonoMethod *m, *dest;
1350 MonoType *type = NULL;
1351 MonoAssembly *assembly = NULL;
1352 gboolean type_resolve = FALSE;
1354 mono_error_init (error);
1357 * We must compute the calling assembly as type loading must happen under a metadata context.
1358 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1359 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1361 m = mono_method_get_last_managed ();
1364 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1369 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1370 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1371 * to crash. This only seems to happen in some strange remoting
1372 * scenarios and I was unable to figure out what's happening there.
1373 * Dec 10, 2005 - Martin.
1377 assembly = dest->klass->image->assembly;
1378 type_resolve = TRUE;
1380 g_warning (G_STRLOC);
1383 if (info->assembly.name)
1384 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1388 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1389 type = mono_reflection_get_type_checked (assembly->image, info, ignoreCase, &type_resolve, error);
1390 return_val_if_nok (error, NULL);
1393 if (!info->assembly.name && !type) {
1395 type = mono_reflection_get_type_checked (NULL, info, ignoreCase, &type_resolve, error);
1396 return_val_if_nok (error, NULL);
1398 if (assembly && !type && type_resolve) {
1399 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1400 type = mono_reflection_get_type_checked (assembly->image, info, ignoreCase, &type_resolve, error);
1401 return_val_if_nok (error, NULL);
1407 return mono_type_get_object_checked (mono_domain_get (), type, error);
1410 ICALL_EXPORT MonoReflectionType*
1411 ves_icall_System_Type_internal_from_name (MonoString *name,
1412 MonoBoolean throwOnError,
1413 MonoBoolean ignoreCase)
1416 char *str = mono_string_to_utf8 (name);
1417 MonoTypeNameParse info;
1418 MonoReflectionType *type;
1421 parsedOk = mono_reflection_parse_type (str, &info);
1423 /* mono_reflection_parse_type() mangles the string */
1425 mono_reflection_free_type_info (&info);
1428 mono_set_pending_exception (mono_get_exception_argument("typeName", "failed parse"));
1433 type = type_from_parsed_name (&info, ignoreCase, &error);
1435 mono_reflection_free_type_info (&info);
1438 if (!mono_error_ok (&error)) {
1440 mono_error_set_pending_exception (&error);
1442 mono_error_cleanup (&error);
1447 MonoException *e = NULL;
1450 e = mono_get_exception_type_load (name, NULL);
1452 mono_loader_clear_error ();
1454 mono_set_pending_exception (e);
1463 ICALL_EXPORT MonoReflectionType*
1464 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1467 MonoReflectionType *ret;
1468 MonoDomain *domain = mono_domain_get ();
1470 ret = mono_type_get_object_checked (domain, handle, &error);
1471 mono_error_raise_exception (&error);
1476 /* System.TypeCode */
1495 TYPECODE_STRING = 18
1498 ICALL_EXPORT guint32
1499 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1501 int t = type->type->type;
1503 if (type->type->byref)
1504 return TYPECODE_OBJECT;
1508 case MONO_TYPE_VOID:
1509 return TYPECODE_OBJECT;
1510 case MONO_TYPE_BOOLEAN:
1511 return TYPECODE_BOOLEAN;
1513 return TYPECODE_BYTE;
1515 return TYPECODE_SBYTE;
1517 return TYPECODE_UINT16;
1519 return TYPECODE_INT16;
1520 case MONO_TYPE_CHAR:
1521 return TYPECODE_CHAR;
1525 return TYPECODE_OBJECT;
1527 return TYPECODE_UINT32;
1529 return TYPECODE_INT32;
1531 return TYPECODE_UINT64;
1533 return TYPECODE_INT64;
1535 return TYPECODE_SINGLE;
1537 return TYPECODE_DOUBLE;
1538 case MONO_TYPE_VALUETYPE: {
1539 MonoClass *klass = type->type->data.klass;
1541 if (klass->enumtype) {
1542 t = mono_class_enum_basetype (klass)->type;
1544 } else if (mono_is_corlib_image (klass->image)) {
1545 if (strcmp (klass->name_space, "System") == 0) {
1546 if (strcmp (klass->name, "Decimal") == 0)
1547 return TYPECODE_DECIMAL;
1548 else if (strcmp (klass->name, "DateTime") == 0)
1549 return TYPECODE_DATETIME;
1552 return TYPECODE_OBJECT;
1554 case MONO_TYPE_STRING:
1555 return TYPECODE_STRING;
1556 case MONO_TYPE_SZARRAY:
1557 case MONO_TYPE_ARRAY:
1558 case MONO_TYPE_OBJECT:
1560 case MONO_TYPE_MVAR:
1561 case MONO_TYPE_TYPEDBYREF:
1562 return TYPECODE_OBJECT;
1563 case MONO_TYPE_CLASS:
1565 MonoClass *klass = type->type->data.klass;
1566 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1567 if (strcmp (klass->name, "DBNull") == 0)
1568 return TYPECODE_DBNULL;
1571 return TYPECODE_OBJECT;
1572 case MONO_TYPE_GENERICINST:
1573 return TYPECODE_OBJECT;
1575 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1581 mono_type_is_primitive (MonoType *type)
1583 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1584 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1588 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1590 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1591 return mono_class_enum_basetype (type->data.klass);
1592 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1593 return mono_class_enum_basetype (type->data.generic_class->container_class);
1597 ICALL_EXPORT guint32
1598 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1603 g_assert (type != NULL);
1605 klass = mono_class_from_mono_type (type->type);
1606 klassc = mono_class_from_mono_type (c->type);
1608 if (type->type->byref ^ c->type->byref)
1611 if (type->type->byref) {
1612 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1613 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1615 klass = mono_class_from_mono_type (t);
1616 klassc = mono_class_from_mono_type (ot);
1618 if (mono_type_is_primitive (t)) {
1619 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1620 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1621 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1622 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1623 return t->type == ot->type;
1625 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1628 if (klass->valuetype)
1629 return klass == klassc;
1630 return klass->valuetype == klassc->valuetype;
1633 return mono_class_is_assignable_from (klass, klassc);
1636 ICALL_EXPORT guint32
1637 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1640 MonoClass *klass = mono_class_from_mono_type (type->type);
1641 mono_class_init_checked (klass, &error);
1642 if (!is_ok (&error)) {
1643 mono_error_set_pending_exception (&error);
1646 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1647 mono_error_set_pending_exception (&error);
1651 ICALL_EXPORT guint32
1652 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1654 MonoClass *klass = mono_class_from_mono_type (type->type);
1655 return klass->flags;
1658 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1659 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1662 MonoClass *klass = field->field->parent;
1663 MonoMarshalType *info;
1667 if (klass->generic_container ||
1668 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1671 ftype = mono_field_get_type (field->field);
1672 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1675 info = mono_marshal_load_type_info (klass);
1677 for (i = 0; i < info->num_fields; ++i) {
1678 if (info->fields [i].field == field->field) {
1679 if (!info->fields [i].mspec)
1682 MonoReflectionMarshalAsAttribute* obj;
1683 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1684 if (!mono_error_ok (&error))
1685 mono_error_set_pending_exception (&error);
1694 ICALL_EXPORT MonoReflectionField*
1695 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1698 gboolean found = FALSE;
1705 klass = handle->parent;
1707 klass = mono_class_from_mono_type (type);
1709 /* Check that the field belongs to the class */
1710 for (k = klass; k; k = k->parent) {
1711 if (k == handle->parent) {
1718 /* The managed code will throw the exception */
1722 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1723 mono_error_raise_exception (&error);
1727 ICALL_EXPORT MonoArray*
1728 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1731 MonoType *type = mono_field_get_type_checked (field->field, &error);
1734 if (!mono_error_ok (&error)) {
1735 mono_error_set_pending_exception (&error);
1739 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1740 mono_error_raise_exception (&error);
1745 vell_icall_get_method_attributes (MonoMethod *method)
1747 return method->flags;
1751 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1754 MonoReflectionType *rt;
1755 MonoDomain *domain = mono_domain_get ();
1756 MonoMethodSignature* sig;
1758 sig = mono_method_signature_checked (method, &error);
1759 if (!mono_error_ok (&error)) {
1760 mono_error_set_pending_exception (&error);
1764 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1765 if (!mono_error_ok (&error)) {
1766 mono_error_set_pending_exception (&error);
1770 MONO_STRUCT_SETREF (info, parent, rt);
1772 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1773 if (!mono_error_ok (&error)) {
1774 mono_error_set_pending_exception (&error);
1778 MONO_STRUCT_SETREF (info, ret, rt);
1780 info->attrs = method->flags;
1781 info->implattrs = method->iflags;
1782 if (sig->call_convention == MONO_CALL_DEFAULT)
1783 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1785 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1790 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1793 ICALL_EXPORT MonoArray*
1794 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1797 MonoDomain *domain = mono_domain_get ();
1799 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1800 mono_error_set_pending_exception (&error);
1804 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1805 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1808 MonoDomain *domain = mono_domain_get ();
1809 MonoReflectionMarshalAsAttribute* res = NULL;
1810 MonoMarshalSpec **mspecs;
1813 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1814 mono_method_get_marshal_info (method, mspecs);
1817 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1818 if (!mono_error_ok (&error)) {
1819 mono_error_set_pending_exception (&error);
1824 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1826 mono_metadata_free_marshal_spec (mspecs [i]);
1833 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1835 MonoClass *parent = field->field->parent;
1836 if (!parent->size_inited)
1837 mono_class_init (parent);
1838 mono_class_setup_fields_locking (parent);
1840 return field->field->offset - sizeof (MonoObject);
1843 ICALL_EXPORT MonoReflectionType*
1844 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1847 MonoReflectionType *ret;
1850 parent = declaring? field->field->parent: field->klass;
1852 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1853 mono_error_raise_exception (&error);
1859 ICALL_EXPORT MonoObject *
1860 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1863 MonoClass *fklass = field->klass;
1864 MonoClassField *cf = field->field;
1865 MonoDomain *domain = mono_object_domain (field);
1867 if (fklass->image->assembly->ref_only) {
1868 mono_set_pending_exception (mono_get_exception_invalid_operation (
1869 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1873 if (mono_security_core_clr_enabled ())
1874 mono_security_core_clr_ensure_reflection_access_field (cf);
1876 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1877 mono_error_set_pending_exception (&error);
1882 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1885 MonoClassField *cf = field->field;
1889 if (field->klass->image->assembly->ref_only) {
1890 mono_set_pending_exception (mono_get_exception_invalid_operation (
1891 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1895 if (mono_security_core_clr_enabled ())
1896 mono_security_core_clr_ensure_reflection_access_field (cf);
1898 type = mono_field_get_type_checked (cf, &error);
1899 if (!mono_error_ok (&error)) {
1900 mono_error_set_pending_exception (&error);
1904 v = (gchar *) value;
1906 switch (type->type) {
1909 case MONO_TYPE_BOOLEAN:
1912 case MONO_TYPE_CHAR:
1921 case MONO_TYPE_VALUETYPE:
1924 v += sizeof (MonoObject);
1926 case MONO_TYPE_STRING:
1927 case MONO_TYPE_OBJECT:
1928 case MONO_TYPE_CLASS:
1929 case MONO_TYPE_ARRAY:
1930 case MONO_TYPE_SZARRAY:
1933 case MONO_TYPE_GENERICINST: {
1934 MonoGenericClass *gclass = type->data.generic_class;
1935 g_assert (!gclass->context.class_inst->is_open);
1937 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1938 MonoClass *nklass = mono_class_from_mono_type (type);
1939 MonoObject *nullable;
1942 * Convert the boxed vtype into a Nullable structure.
1943 * This is complicated by the fact that Nullables have
1944 * a variable structure.
1946 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1947 if (!mono_error_ok (&error)) {
1948 mono_error_set_pending_exception (&error);
1952 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1954 v = (gchar *)mono_object_unbox (nullable);
1957 if (gclass->container_class->valuetype && (v != NULL))
1958 v += sizeof (MonoObject);
1962 g_error ("type 0x%x not handled in "
1963 "ves_icall_FieldInfo_SetValueInternal", type->type);
1968 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1969 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
1970 if (!is_ok (&error)) {
1971 mono_error_set_pending_exception (&error);
1974 if (!vtable->initialized) {
1975 if (!mono_runtime_class_init_full (vtable, &error)) {
1976 mono_error_set_pending_exception (&error);
1980 mono_field_static_set_value (vtable, cf, v);
1982 mono_field_set_value (obj, cf, v);
1987 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1996 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1997 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2001 if (MONO_TYPE_IS_REFERENCE (f->type))
2002 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2004 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2007 ICALL_EXPORT MonoObject *
2008 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2010 MonoObject *o = NULL;
2011 MonoClassField *field = rfield->field;
2013 MonoDomain *domain = mono_object_domain (rfield);
2015 MonoTypeEnum def_type;
2016 const char *def_value;
2020 mono_class_init (field->parent);
2022 t = mono_field_get_type_checked (field, &error);
2023 if (!mono_error_ok (&error)) {
2024 mono_error_set_pending_exception (&error);
2028 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2029 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2033 if (image_is_dynamic (field->parent->image)) {
2034 MonoClass *klass = field->parent;
2035 int fidx = field - klass->fields;
2037 g_assert (fidx >= 0 && fidx < klass->field.count);
2038 g_assert (klass->ext);
2039 g_assert (klass->ext->field_def_values);
2040 def_type = klass->ext->field_def_values [fidx].def_type;
2041 def_value = klass->ext->field_def_values [fidx].data;
2042 if (def_type == MONO_TYPE_END) {
2043 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2047 def_value = mono_class_get_field_default_value (field, &def_type);
2048 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2050 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2055 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2059 case MONO_TYPE_BOOLEAN:
2062 case MONO_TYPE_CHAR:
2070 case MONO_TYPE_R8: {
2073 /* boxed value type */
2074 t = g_new0 (MonoType, 1);
2076 klass = mono_class_from_mono_type (t);
2078 o = mono_object_new_checked (domain, klass, &error);
2079 if (!mono_error_ok (&error)) {
2080 mono_error_set_pending_exception (&error);
2083 v = ((gchar *) o) + sizeof (MonoObject);
2084 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2087 case MONO_TYPE_STRING:
2088 case MONO_TYPE_CLASS:
2089 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2092 g_assert_not_reached ();
2098 ICALL_EXPORT MonoReflectionType*
2099 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2102 MonoReflectionType *ret;
2105 type = mono_field_get_type_checked (ref_field->field, &error);
2106 if (!mono_error_ok (&error)) {
2107 mono_error_set_pending_exception (&error);
2111 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2112 if (!mono_error_ok (&error)) {
2113 mono_error_set_pending_exception (&error);
2120 /* From MonoProperty.cs */
2122 PInfo_Attributes = 1,
2123 PInfo_GetMethod = 1 << 1,
2124 PInfo_SetMethod = 1 << 2,
2125 PInfo_ReflectedType = 1 << 3,
2126 PInfo_DeclaringType = 1 << 4,
2131 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2134 MonoReflectionType *rt;
2135 MonoReflectionMethod *rm;
2136 MonoDomain *domain = mono_object_domain (property);
2137 const MonoProperty *pproperty = property->property;
2139 if ((req_info & PInfo_ReflectedType) != 0) {
2140 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2141 mono_error_raise_exception (&error);
2143 MONO_STRUCT_SETREF (info, parent, rt);
2145 if ((req_info & PInfo_DeclaringType) != 0) {
2146 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2147 mono_error_raise_exception (&error);
2149 MONO_STRUCT_SETREF (info, declaring_type, rt);
2152 if ((req_info & PInfo_Name) != 0)
2153 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2155 if ((req_info & PInfo_Attributes) != 0)
2156 info->attrs = pproperty->attrs;
2158 if ((req_info & PInfo_GetMethod) != 0) {
2159 if (pproperty->get &&
2160 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2161 pproperty->get->klass == property->klass)) {
2162 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2163 mono_error_raise_exception (&error);
2168 MONO_STRUCT_SETREF (info, get, rm);
2170 if ((req_info & PInfo_SetMethod) != 0) {
2171 if (pproperty->set &&
2172 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2173 pproperty->set->klass == property->klass)) {
2174 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2175 mono_error_raise_exception (&error);
2180 MONO_STRUCT_SETREF (info, set, rm);
2183 * There may be other methods defined for properties, though, it seems they are not exposed
2184 * in the reflection API
2189 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2192 MonoReflectionType *rt;
2193 MonoReflectionMethod *rm;
2194 MonoDomain *domain = mono_object_domain (event);
2196 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2197 mono_error_raise_exception (&error);
2199 MONO_STRUCT_SETREF (info, reflected_type, rt);
2201 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2202 mono_error_raise_exception (&error);
2204 MONO_STRUCT_SETREF (info, declaring_type, rt);
2206 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2207 info->attrs = event->event->attrs;
2209 if (event->event->add) {
2210 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2211 mono_error_raise_exception (&error);
2216 MONO_STRUCT_SETREF (info, add_method, rm);
2218 if (event->event->remove) {
2219 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2220 mono_error_raise_exception (&error);
2225 MONO_STRUCT_SETREF (info, remove_method, rm);
2227 if (event->event->raise) {
2228 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2229 mono_error_raise_exception (&error);
2234 MONO_STRUCT_SETREF (info, raise_method, rm);
2236 #ifndef MONO_SMALL_CONFIG
2237 if (event->event->other) {
2239 while (event->event->other [n])
2241 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2243 for (i = 0; i < n; i++) {
2244 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2245 mono_error_raise_exception (&error);
2246 mono_array_setref (info->other_methods, i, rm);
2253 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2258 mono_class_setup_interfaces (klass, error);
2259 if (!mono_error_ok (error))
2262 for (i = 0; i < klass->interface_count; i++) {
2263 ic = klass->interfaces [i];
2264 g_hash_table_insert (ifaces, ic, ic);
2266 collect_interfaces (ic, ifaces, error);
2267 if (!mono_error_ok (error))
2273 MonoArray *iface_array;
2274 MonoGenericContext *context;
2278 } FillIfaceArrayData;
2281 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2283 MonoReflectionType *rt;
2284 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2285 MonoClass *ic = (MonoClass *)key;
2286 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2288 if (!mono_error_ok (data->error))
2291 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2292 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2293 if (!mono_error_ok (data->error))
2297 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2298 if (!mono_error_ok (data->error))
2301 mono_array_setref (data->iface_array, data->next_idx++, rt);
2304 mono_metadata_free_type (inflated);
2308 get_interfaces_hash (gconstpointer v1)
2310 MonoClass *k = (MonoClass*)v1;
2312 return k->type_token;
2315 ICALL_EXPORT MonoArray*
2316 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2319 MonoClass *klass = mono_class_from_mono_type (type->type);
2321 FillIfaceArrayData data = { 0 };
2324 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2326 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2327 data.context = mono_class_get_context (klass);
2328 klass = klass->generic_class->container_class;
2331 for (parent = klass; parent; parent = parent->parent) {
2332 mono_class_setup_interfaces (parent, &error);
2333 if (!mono_error_ok (&error))
2335 collect_interfaces (parent, iface_hash, &error);
2336 if (!mono_error_ok (&error))
2340 data.error = &error;
2341 data.domain = mono_object_domain (type);
2343 len = g_hash_table_size (iface_hash);
2345 g_hash_table_destroy (iface_hash);
2346 if (!data.domain->empty_types)
2347 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2348 return data.domain->empty_types;
2351 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2352 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2353 if (!mono_error_ok (&error))
2356 g_hash_table_destroy (iface_hash);
2357 return data.iface_array;
2360 g_hash_table_destroy (iface_hash);
2361 mono_error_set_pending_exception (&error);
2366 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2368 gboolean variance_used;
2369 MonoClass *klass = mono_class_from_mono_type (type->type);
2370 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2371 MonoReflectionMethod *member;
2374 int i = 0, len, ioffset;
2378 mono_class_init_checked (klass, &error);
2379 mono_error_raise_exception (&error);
2380 mono_class_init_checked (iclass, &error);
2381 mono_error_raise_exception (&error);
2383 mono_class_setup_vtable (klass);
2385 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2389 len = mono_class_num_methods (iclass);
2390 domain = mono_object_domain (type);
2391 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2392 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2394 while ((method = mono_class_get_methods (iclass, &iter))) {
2395 member = mono_method_get_object_checked (domain, method, iclass, &error);
2396 mono_error_raise_exception (&error);
2397 mono_array_setref (*methods, i, member);
2398 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2399 mono_error_raise_exception (&error);
2400 mono_array_setref (*targets, i, member);
2407 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2410 MonoClass *klass = mono_class_from_mono_type (type->type);
2412 mono_class_init_checked (klass, &error);
2413 mono_error_raise_exception (&error);
2415 if (image_is_dynamic (klass->image)) {
2416 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2417 *packing = tb->packing_size;
2418 *size = tb->class_size;
2420 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2424 ICALL_EXPORT MonoReflectionType*
2425 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2428 MonoReflectionType *ret;
2431 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2432 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2433 mono_error_raise_exception (&error);
2438 klass = mono_class_from_mono_type (type->type);
2439 mono_class_init_checked (klass, &error);
2440 mono_error_raise_exception (&error);
2442 // GetElementType should only return a type for:
2443 // Array Pointer PassedByRef
2444 if (type->type->byref)
2445 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2446 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2447 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2448 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2449 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2453 mono_error_raise_exception (&error);
2458 ICALL_EXPORT MonoReflectionType*
2459 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2462 MonoReflectionType *ret;
2464 if (type->type->byref)
2467 MonoClass *klass = mono_class_from_mono_type (type->type);
2471 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2472 mono_error_raise_exception (&error);
2477 ICALL_EXPORT MonoBoolean
2478 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2480 return type->type->type == MONO_TYPE_PTR;
2483 ICALL_EXPORT MonoBoolean
2484 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2486 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)));
2489 ICALL_EXPORT MonoBoolean
2490 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2492 return type->type->byref;
2495 ICALL_EXPORT MonoBoolean
2496 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2499 MonoClass *klass = mono_class_from_mono_type (type->type);
2500 mono_class_init_checked (klass, &error);
2501 mono_error_raise_exception (&error);
2503 return mono_class_is_com_object (klass);
2506 ICALL_EXPORT guint32
2507 ves_icall_reflection_get_token (MonoObject* obj)
2510 guint32 result = mono_reflection_get_token_checked (obj, &error);
2511 mono_error_set_pending_exception (&error);
2515 ICALL_EXPORT MonoReflectionModule*
2516 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2519 MonoReflectionModule *result = NULL;
2520 MonoClass *klass = mono_class_from_mono_type (type->type);
2521 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2522 if (!mono_error_ok (&error))
2523 mono_error_set_pending_exception (&error);
2527 ICALL_EXPORT MonoReflectionAssembly*
2528 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2531 MonoDomain *domain = mono_domain_get ();
2532 MonoClass *klass = mono_class_from_mono_type (type->type);
2533 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2535 mono_error_set_pending_exception (&error);
2539 ICALL_EXPORT MonoReflectionType*
2540 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2543 MonoReflectionType *ret;
2544 MonoDomain *domain = mono_domain_get ();
2547 if (type->type->byref)
2549 if (type->type->type == MONO_TYPE_VAR) {
2550 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2551 klass = param ? param->owner.klass : NULL;
2552 } else if (type->type->type == MONO_TYPE_MVAR) {
2553 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2554 klass = param ? param->owner.method->klass : NULL;
2556 klass = mono_class_from_mono_type (type->type)->nested_in;
2562 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2563 mono_error_raise_exception (&error);
2568 ICALL_EXPORT MonoString*
2569 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2571 MonoDomain *domain = mono_domain_get ();
2572 MonoClass *klass = mono_class_from_mono_type (type->type);
2574 if (type->type->byref) {
2575 char *n = g_strdup_printf ("%s&", klass->name);
2576 MonoString *res = mono_string_new (domain, n);
2582 return mono_string_new (domain, klass->name);
2586 ICALL_EXPORT MonoString*
2587 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2589 MonoDomain *domain = mono_domain_get ();
2590 MonoClass *klass = mono_class_from_mono_type (type->type);
2592 while (klass->nested_in)
2593 klass = klass->nested_in;
2595 if (klass->name_space [0] == '\0')
2598 return mono_string_new (domain, klass->name_space);
2602 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2606 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2607 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2611 klass = mono_class_from_mono_type (type->type);
2617 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2620 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2624 ICALL_EXPORT MonoArray*
2625 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2628 MonoReflectionType *rt;
2630 MonoClass *klass, *pklass;
2631 MonoDomain *domain = mono_object_domain (type);
2634 klass = mono_class_from_mono_type (type->type);
2636 if (klass->generic_container) {
2637 MonoGenericContainer *container = klass->generic_container;
2638 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2639 for (i = 0; i < container->type_argc; ++i) {
2640 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2642 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2643 mono_error_raise_exception (&error);
2645 mono_array_setref (res, i, rt);
2647 } else if (klass->generic_class) {
2648 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2649 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2650 for (i = 0; i < inst->type_argc; ++i) {
2651 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2652 mono_error_raise_exception (&error);
2654 mono_array_setref (res, i, rt);
2662 ICALL_EXPORT gboolean
2663 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2667 if (!IS_MONOTYPE (type))
2670 if (type->type->byref)
2673 klass = mono_class_from_mono_type (type->type);
2674 return klass->generic_container != NULL;
2677 ICALL_EXPORT MonoReflectionType*
2678 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2681 MonoReflectionType *ret;
2684 if (type->type->byref)
2687 klass = mono_class_from_mono_type (type->type);
2689 if (klass->generic_container) {
2690 return type; /* check this one */
2692 if (klass->generic_class) {
2693 MonoClass *generic_class = klass->generic_class->container_class;
2696 tb = mono_class_get_ref_info (generic_class);
2698 if (generic_class->wastypebuilder && tb)
2699 return (MonoReflectionType *)tb;
2701 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2702 mono_error_raise_exception (&error);
2710 ICALL_EXPORT MonoReflectionType*
2711 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2714 MonoReflectionType *ret;
2716 MonoType *geninst, **types;
2719 g_assert (IS_MONOTYPE (type));
2720 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2721 mono_error_raise_exception (&error);
2723 count = mono_array_length (type_array);
2724 types = g_new0 (MonoType *, count);
2726 for (i = 0; i < count; i++) {
2727 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2728 types [i] = t->type;
2731 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2734 mono_error_set_pending_exception (&error);
2738 klass = mono_class_from_mono_type (geninst);
2740 /*we might inflate to the GTD*/
2741 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2742 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2746 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2747 mono_error_raise_exception (&error);
2752 ICALL_EXPORT gboolean
2753 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2757 if (!IS_MONOTYPE (type))
2760 if (type->type->byref)
2763 klass = mono_class_from_mono_type (type->type);
2764 return klass->generic_class != NULL || klass->generic_container != NULL;
2768 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2770 if (!IS_MONOTYPE (type))
2773 if (is_generic_parameter (type->type))
2774 return mono_type_get_generic_param_num (type->type);
2778 ICALL_EXPORT GenericParameterAttributes
2779 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2781 g_assert (IS_MONOTYPE (type));
2782 g_assert (is_generic_parameter (type->type));
2783 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2786 ICALL_EXPORT MonoArray *
2787 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2790 MonoReflectionType *rt;
2791 MonoGenericParamInfo *param_info;
2797 g_assert (IS_MONOTYPE (type));
2799 domain = mono_object_domain (type);
2800 param_info = mono_generic_param_info (type->type->data.generic_param);
2801 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2804 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2805 for (i = 0; i < count; i++) {
2806 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2807 mono_error_raise_exception (&error);
2809 mono_array_setref (res, i, rt);
2816 ICALL_EXPORT MonoBoolean
2817 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2819 return is_generic_parameter (type->type);
2822 ICALL_EXPORT MonoBoolean
2823 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2825 return is_generic_parameter (tb->type.type);
2829 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2830 MonoReflectionType *t)
2832 enumtype->type = t->type;
2835 ICALL_EXPORT MonoReflectionMethod*
2836 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2837 MonoReflectionMethod* generic)
2844 MonoReflectionMethod *ret = NULL;
2846 domain = ((MonoObject *)type)->vtable->domain;
2848 klass = mono_class_from_mono_type (type->type);
2849 mono_class_init_checked (klass, &error);
2850 mono_error_raise_exception (&error);
2853 while ((method = mono_class_get_methods (klass, &iter))) {
2854 if (method->token == generic->method->token) {
2855 ret = mono_method_get_object_checked (domain, method, klass, &error);
2856 mono_error_raise_exception (&error);
2863 ICALL_EXPORT MonoReflectionMethod *
2864 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2867 MonoType *type = ref_type->type;
2869 MonoReflectionMethod *ret = NULL;
2871 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2872 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2875 if (type->type == MONO_TYPE_VAR)
2878 method = mono_type_get_generic_param_owner (type)->owner.method;
2881 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2882 if (!mono_error_ok (&error))
2883 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2887 ICALL_EXPORT MonoBoolean
2888 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2890 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2894 ICALL_EXPORT MonoBoolean
2895 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2897 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2902 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2904 MonoDomain *domain = mono_domain_get ();
2905 MonoImage *image = method->method->klass->image;
2906 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2907 MonoTableInfo *tables = image->tables;
2908 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2909 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2910 guint32 im_cols [MONO_IMPLMAP_SIZE];
2911 guint32 scope_token;
2912 const char *import = NULL;
2913 const char *scope = NULL;
2915 if (image_is_dynamic (image)) {
2916 MonoReflectionMethodAux *method_aux =
2917 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2919 import = method_aux->dllentry;
2920 scope = method_aux->dll;
2923 if (!import || !scope) {
2924 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2929 if (piinfo->implmap_idx) {
2930 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2932 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2933 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2934 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2935 scope = mono_metadata_string_heap (image, scope_token);
2939 *flags = piinfo->piflags;
2940 *entry_point = mono_string_new (domain, import);
2941 *dll_name = mono_string_new (domain, scope);
2944 ICALL_EXPORT MonoReflectionMethod *
2945 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2947 MonoMethodInflated *imethod;
2949 MonoReflectionMethod *ret = NULL;
2952 if (method->method->is_generic)
2955 if (!method->method->is_inflated)
2958 imethod = (MonoMethodInflated *) method->method;
2960 result = imethod->declaring;
2961 /* Not a generic method. */
2962 if (!result->is_generic)
2965 if (image_is_dynamic (method->method->klass->image)) {
2966 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2967 MonoReflectionMethod *res;
2970 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2971 * the dynamic case as well ?
2973 mono_image_lock ((MonoImage*)image);
2974 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2975 mono_image_unlock ((MonoImage*)image);
2981 if (imethod->context.class_inst) {
2982 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2983 /*Generic methods gets the context of the GTD.*/
2984 if (mono_class_get_context (klass)) {
2985 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2986 if (!mono_error_ok (&error))
2991 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2993 if (!mono_error_ok (&error))
2994 mono_error_set_pending_exception (&error);
2998 ICALL_EXPORT gboolean
2999 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3001 return mono_method_signature (method->method)->generic_param_count != 0;
3004 ICALL_EXPORT gboolean
3005 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3007 return method->method->is_generic;
3010 ICALL_EXPORT MonoArray*
3011 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3014 MonoReflectionType *rt;
3019 domain = mono_object_domain (method);
3021 if (method->method->is_inflated) {
3022 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3025 count = inst->type_argc;
3026 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3028 for (i = 0; i < count; i++) {
3029 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3030 mono_error_raise_exception (&error);
3032 mono_array_setref (res, i, rt);
3039 count = mono_method_signature (method->method)->generic_param_count;
3040 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3042 for (i = 0; i < count; i++) {
3043 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3044 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3045 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3047 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3048 mono_error_raise_exception (&error);
3050 mono_array_setref (res, i, rt);
3056 ICALL_EXPORT MonoObject *
3057 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3061 * Invoke from reflection is supposed to always be a virtual call (the API
3062 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3063 * greater flexibility.
3065 MonoMethod *m = method->method;
3066 MonoMethodSignature *sig = mono_method_signature (m);
3069 void *obj = this_arg;
3073 if (mono_security_core_clr_enabled ())
3074 mono_security_core_clr_ensure_reflection_access_method (m);
3076 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3077 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3078 mono_error_cleanup (&error); /* FIXME does this make sense? */
3079 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3084 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3085 if (!is_ok (&error)) {
3086 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3089 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3090 char *target_name = mono_type_get_full_name (m->klass);
3091 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3092 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3094 g_free (target_name);
3098 m = mono_object_get_virtual_method (this_arg, m);
3099 /* must pass the pointer to the value for valuetype methods */
3100 if (m->klass->valuetype)
3101 obj = mono_object_unbox (this_arg);
3102 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3103 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3108 if (sig->ret->byref) {
3109 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"));
3113 pcount = params? mono_array_length (params): 0;
3114 if (pcount != sig->param_count) {
3115 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3119 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3120 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."));
3124 image = m->klass->image;
3125 if (image->assembly->ref_only) {
3126 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."));
3130 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3131 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3135 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3139 intptr_t *lower_bounds;
3140 pcount = mono_array_length (params);
3141 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3142 /* Note: the synthetized array .ctors have int32 as argument type */
3143 for (i = 0; i < pcount; ++i)
3144 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3146 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3147 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3148 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3149 if (!mono_error_ok (&error)) {
3150 mono_error_set_pending_exception (&error);
3154 for (i = 0; i < mono_array_length (arr); ++i) {
3155 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3156 if (!mono_error_ok (&error)) {
3157 mono_error_set_pending_exception (&error);
3160 mono_array_setref_fast (arr, i, subarray);
3162 return (MonoObject*)arr;
3165 if (m->klass->rank == pcount) {
3166 /* Only lengths provided. */
3167 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3168 if (!mono_error_ok (&error)) {
3169 mono_error_set_pending_exception (&error);
3173 return (MonoObject*)arr;
3175 g_assert (pcount == (m->klass->rank * 2));
3176 /* The arguments are lower-bound-length pairs */
3177 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3179 for (i = 0; i < pcount / 2; ++i) {
3180 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3181 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3184 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3185 if (!mono_error_ok (&error)) {
3186 mono_error_set_pending_exception (&error);
3190 return (MonoObject*)arr;
3193 return mono_runtime_invoke_array (m, obj, params, NULL);
3196 #ifndef DISABLE_REMOTING
3197 ICALL_EXPORT MonoObject *
3198 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3201 MonoDomain *domain = mono_object_domain (method);
3202 MonoMethod *m = method->method;
3203 MonoMethodSignature *sig = mono_method_signature (m);
3204 MonoArray *out_args;
3206 int i, j, outarg_count = 0;
3208 if (m->klass == mono_defaults.object_class) {
3209 if (!strcmp (m->name, "FieldGetter")) {
3210 MonoClass *k = this_arg->vtable->klass;
3214 /* If this is a proxy, then it must be a CBO */
3215 if (k == mono_defaults.transparent_proxy_class) {
3216 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3217 this_arg = tp->rp->unwrapped_server;
3218 g_assert (this_arg);
3219 k = this_arg->vtable->klass;
3222 name = mono_array_get (params, MonoString *, 1);
3223 str = mono_string_to_utf8 (name);
3226 MonoClassField* field = mono_class_get_field_from_name (k, str);
3228 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3229 if (field_klass->valuetype) {
3230 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3231 mono_error_set_pending_exception (&error);
3232 /* fallthru to cleanup */
3234 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3236 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3237 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3238 mono_array_setref (out_args, 0, result);
3246 g_assert_not_reached ();
3248 } else if (!strcmp (m->name, "FieldSetter")) {
3249 MonoClass *k = this_arg->vtable->klass;
3255 /* If this is a proxy, then it must be a CBO */
3256 if (k == mono_defaults.transparent_proxy_class) {
3257 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3258 this_arg = tp->rp->unwrapped_server;
3259 g_assert (this_arg);
3260 k = this_arg->vtable->klass;
3263 name = mono_array_get (params, MonoString *, 1);
3264 str = mono_string_to_utf8 (name);
3267 MonoClassField* field = mono_class_get_field_from_name (k, str);
3269 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3270 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3272 if (field_klass->valuetype) {
3273 size = mono_type_size (field->type, &align);
3274 g_assert (size == mono_class_value_size (field_klass, NULL));
3275 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3277 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3280 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3281 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3291 g_assert_not_reached ();
3296 for (i = 0; i < mono_array_length (params); i++) {
3297 if (sig->params [i]->byref)
3301 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3303 /* handle constructors only for objects already allocated */
3304 if (!strcmp (method->method->name, ".ctor"))
3305 g_assert (this_arg);
3307 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3308 g_assert (!method->method->klass->valuetype);
3309 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3311 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3312 if (sig->params [i]->byref) {
3314 arg = mono_array_get (params, gpointer, i);
3315 mono_array_setref (out_args, j, arg);
3320 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3327 read_enum_value (const char *mem, int type)
3330 case MONO_TYPE_BOOLEAN:
3332 return *(guint8*)mem;
3334 return *(gint8*)mem;
3335 case MONO_TYPE_CHAR:
3337 return read16 (mem);
3339 return (gint16) read16 (mem);
3341 return read32 (mem);
3343 return (gint32) read32 (mem);
3346 return read64 (mem);
3348 g_assert_not_reached ();
3354 write_enum_value (char *mem, int type, guint64 value)
3358 case MONO_TYPE_I1: {
3359 guint8 *p = (guint8*)mem;
3364 case MONO_TYPE_I2: {
3365 guint16 *p = (guint16 *)mem;
3370 case MONO_TYPE_I4: {
3371 guint32 *p = (guint32 *)mem;
3376 case MONO_TYPE_I8: {
3377 guint64 *p = (guint64 *)mem;
3382 g_assert_not_reached ();
3387 ICALL_EXPORT MonoObject *
3388 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3396 domain = mono_object_domain (enumType);
3397 enumc = mono_class_from_mono_type (enumType->type);
3399 mono_class_init_checked (enumc, &error);
3400 mono_error_raise_exception (&error);
3402 etype = mono_class_enum_basetype (enumc);
3404 res = mono_object_new_checked (domain, enumc, &error);
3405 mono_error_raise_exception (&error);
3406 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3411 ICALL_EXPORT MonoBoolean
3412 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3414 int size = mono_class_value_size (a->vtable->klass, NULL);
3415 guint64 a_val = 0, b_val = 0;
3417 memcpy (&a_val, mono_object_unbox (a), size);
3418 memcpy (&b_val, mono_object_unbox (b), size);
3420 return (a_val & b_val) == b_val;
3423 ICALL_EXPORT MonoObject *
3424 ves_icall_System_Enum_get_value (MonoObject *eobj)
3436 g_assert (eobj->vtable->klass->enumtype);
3438 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3439 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3440 mono_error_raise_exception (&error);
3441 dst = (char *)res + sizeof (MonoObject);
3442 src = (char *)eobj + sizeof (MonoObject);
3443 size = mono_class_value_size (enumc, NULL);
3445 memcpy (dst, src, size);
3450 ICALL_EXPORT MonoReflectionType *
3451 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3454 MonoReflectionType *ret;
3458 klass = mono_class_from_mono_type (type->type);
3459 mono_class_init_checked (klass, &error);
3460 mono_error_raise_exception (&error);
3462 etype = mono_class_enum_basetype (klass);
3464 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3468 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3469 mono_error_raise_exception (&error);
3475 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3477 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3478 gpointer odata = (char *)other + sizeof (MonoObject);
3479 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3480 g_assert (basetype);
3485 if (eobj->vtable->klass != other->vtable->klass)
3488 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3489 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3490 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3493 return me > other ? 1 : -1; \
3496 switch (basetype->type) {
3498 COMPARE_ENUM_VALUES (guint8);
3500 COMPARE_ENUM_VALUES (gint8);
3501 case MONO_TYPE_CHAR:
3503 COMPARE_ENUM_VALUES (guint16);
3505 COMPARE_ENUM_VALUES (gint16);
3507 COMPARE_ENUM_VALUES (guint32);
3509 COMPARE_ENUM_VALUES (gint32);
3511 COMPARE_ENUM_VALUES (guint64);
3513 COMPARE_ENUM_VALUES (gint64);
3517 #undef COMPARE_ENUM_VALUES
3518 /* indicates that the enum was of an unsupported unerlying type */
3523 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3525 gpointer data = (char *)eobj + sizeof (MonoObject);
3526 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3527 g_assert (basetype);
3529 switch (basetype->type) {
3530 case MONO_TYPE_I1: {
3531 gint8 value = *((gint8*)data);
3532 return ((int)value ^ (int)value << 8);
3535 return *((guint8*)data);
3536 case MONO_TYPE_CHAR:
3538 return *((guint16*)data);
3540 case MONO_TYPE_I2: {
3541 gint16 value = *((gint16*)data);
3542 return ((int)(guint16)value | (((int)value) << 16));
3545 return *((guint32*)data);
3547 return *((gint32*)data);
3549 case MONO_TYPE_I8: {
3550 gint64 value = *((gint64*)data);
3551 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3554 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3559 ICALL_EXPORT MonoBoolean
3560 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3563 MonoDomain *domain = mono_object_domain (type);
3564 MonoClass *enumc = mono_class_from_mono_type (type->type);
3565 guint j = 0, nvalues;
3567 MonoClassField *field;
3569 guint64 field_value, previous_value = 0;
3570 gboolean sorted = TRUE;
3572 mono_class_init_checked (enumc, &error);
3573 mono_error_raise_exception (&error);
3575 if (!enumc->enumtype) {
3576 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3580 base_type = mono_class_enum_basetype (enumc)->type;
3582 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3583 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3584 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3587 while ((field = mono_class_get_fields (enumc, &iter))) {
3589 MonoTypeEnum def_type;
3591 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3593 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3595 if (mono_field_is_deleted (field))
3597 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3599 p = mono_class_get_field_default_value (field, &def_type);
3600 /* len = */ mono_metadata_decode_blob_size (p, &p);
3602 field_value = read_enum_value (p, base_type);
3603 mono_array_set (*values, guint64, j, field_value);
3605 if (previous_value > field_value)
3608 previous_value = field_value;
3616 BFLAGS_IgnoreCase = 1,
3617 BFLAGS_DeclaredOnly = 2,
3618 BFLAGS_Instance = 4,
3620 BFLAGS_Public = 0x10,
3621 BFLAGS_NonPublic = 0x20,
3622 BFLAGS_FlattenHierarchy = 0x40,
3623 BFLAGS_InvokeMethod = 0x100,
3624 BFLAGS_CreateInstance = 0x200,
3625 BFLAGS_GetField = 0x400,
3626 BFLAGS_SetField = 0x800,
3627 BFLAGS_GetProperty = 0x1000,
3628 BFLAGS_SetProperty = 0x2000,
3629 BFLAGS_ExactBinding = 0x10000,
3630 BFLAGS_SuppressChangeType = 0x20000,
3631 BFLAGS_OptionalParamBinding = 0x40000
3634 ICALL_EXPORT MonoArray*
3635 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3639 MonoClass *startklass, *klass, *refklass;
3644 char *utf8_name = NULL;
3645 int (*compare_func) (const char *s1, const char *s2) = NULL;
3646 MonoClassField *field;
3647 MonoPtrArray tmp_array;
3649 domain = ((MonoObject *)type)->vtable->domain;
3650 if (type->type->byref)
3651 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3653 klass = startklass = mono_class_from_mono_type (type->type);
3654 refklass = mono_class_from_mono_type (reftype->type);
3656 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3659 if (mono_class_has_failure (klass)) {
3660 mono_ptr_array_destroy (tmp_array);
3661 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3666 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3667 guint32 flags = mono_field_get_flags (field);
3669 if (mono_field_is_deleted_with_flags (field, flags))
3671 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3672 if (bflags & BFLAGS_Public)
3674 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3675 if (bflags & BFLAGS_NonPublic) {
3682 if (flags & FIELD_ATTRIBUTE_STATIC) {
3683 if (bflags & BFLAGS_Static)
3684 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3687 if (bflags & BFLAGS_Instance)
3695 if (utf8_name == NULL) {
3696 utf8_name = mono_string_to_utf8 (name);
3697 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3700 if (compare_func (mono_field_get_name (field), utf8_name))
3704 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3705 if (!mono_error_ok (&error))
3707 mono_ptr_array_append (tmp_array, member);
3709 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3712 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3714 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3715 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3717 mono_ptr_array_destroy (tmp_array);
3719 if (utf8_name != NULL)
3724 mono_ptr_array_destroy (tmp_array);
3725 mono_error_raise_exception (&error);
3726 g_assert_not_reached ();
3730 method_nonpublic (MonoMethod* method, gboolean start_klass)
3732 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3733 case METHOD_ATTRIBUTE_ASSEM:
3734 return (start_klass || mono_defaults.generic_ilist_class);
3735 case METHOD_ATTRIBUTE_PRIVATE:
3737 case METHOD_ATTRIBUTE_PUBLIC:
3745 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3748 MonoClass *startklass;
3752 /*FIXME, use MonoBitSet*/
3753 guint32 method_slots_default [8];
3754 guint32 *method_slots = NULL;
3755 int (*compare_func) (const char *s1, const char *s2) = NULL;
3757 array = g_ptr_array_new ();
3762 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3764 /* An optimization for calls made from Delegate:CreateDelegate () */
3765 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3766 method = mono_get_delegate_invoke (klass);
3767 if (mono_loader_get_last_error ())
3770 g_ptr_array_add (array, method);
3774 mono_class_setup_methods (klass);
3775 mono_class_setup_vtable (klass);
3776 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3779 if (is_generic_parameter (&klass->byval_arg))
3780 nslots = mono_class_get_vtable_size (klass->parent);
3782 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3783 if (nslots >= sizeof (method_slots_default) * 8) {
3784 method_slots = g_new0 (guint32, nslots / 32 + 1);
3786 method_slots = method_slots_default;
3787 memset (method_slots, 0, sizeof (method_slots_default));
3790 mono_class_setup_methods (klass);
3791 mono_class_setup_vtable (klass);
3792 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3796 while ((method = mono_class_get_methods (klass, &iter))) {
3798 if (method->slot != -1) {
3799 g_assert (method->slot < nslots);
3800 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3802 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3803 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3806 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3808 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3809 if (bflags & BFLAGS_Public)
3811 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3817 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3818 if (bflags & BFLAGS_Static)
3819 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3822 if (bflags & BFLAGS_Instance)
3830 if (compare_func (name, method->name))
3835 g_ptr_array_add (array, method);
3837 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3839 if (method_slots != method_slots_default)
3840 g_free (method_slots);
3845 if (method_slots != method_slots_default)
3846 g_free (method_slots);
3847 g_ptr_array_free (array, TRUE);
3849 if (mono_class_has_failure (klass)) {
3850 *ex = mono_class_get_exception_for_failure (klass);
3852 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3853 mono_loader_clear_error ();
3858 ICALL_EXPORT MonoArray*
3859 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3861 static MonoClass *MethodInfo_array;
3865 MonoVTable *array_vtable;
3866 MonoException *ex = NULL;
3867 const char *mname = NULL;
3868 GPtrArray *method_array;
3869 MonoClass *klass, *refklass;
3872 mono_error_init (&error);
3874 if (!MethodInfo_array) {
3875 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3876 mono_memory_barrier ();
3877 MethodInfo_array = klass;
3880 klass = mono_class_from_mono_type (type->type);
3881 refklass = mono_class_from_mono_type (reftype->type);
3882 domain = ((MonoObject *)type)->vtable->domain;
3883 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3884 if (!is_ok (&error)) {
3885 mono_error_set_pending_exception (&error);
3888 if (type->type->byref) {
3889 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3890 mono_error_set_pending_exception (&error);
3896 mname = mono_string_to_utf8 (name);
3898 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3899 g_free ((char*)mname);
3901 mono_set_pending_exception (ex);
3905 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3906 if (!mono_error_ok (&error)) {
3907 mono_error_set_pending_exception (&error);
3911 for (i = 0; i < method_array->len; ++i) {
3912 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3913 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3914 if (!mono_error_ok (&error))
3916 mono_array_setref (res, i, rm);
3920 g_ptr_array_free (method_array, TRUE);
3921 if (!mono_error_ok (&error))
3922 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3926 ICALL_EXPORT MonoArray*
3927 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3930 MonoClass *startklass, *klass, *refklass;
3935 gpointer iter = NULL;
3936 MonoPtrArray tmp_array;
3939 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3941 domain = ((MonoObject *)type)->vtable->domain;
3942 if (type->type->byref)
3943 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3944 klass = startklass = mono_class_from_mono_type (type->type);
3945 refklass = mono_class_from_mono_type (reftype->type);
3947 mono_class_setup_methods (klass);
3948 if (mono_class_has_failure (klass)) {
3949 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3954 while ((method = mono_class_get_methods (klass, &iter))) {
3956 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3958 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3959 if (bflags & BFLAGS_Public)
3962 if (bflags & BFLAGS_NonPublic)
3968 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3969 if (bflags & BFLAGS_Static)
3970 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3973 if (bflags & BFLAGS_Instance)
3979 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3980 if (!mono_error_ok (&error)) {
3981 mono_error_set_pending_exception (&error);
3985 mono_ptr_array_append (tmp_array, member);
3988 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
3990 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3991 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3993 mono_ptr_array_destroy (tmp_array);
3999 property_hash (gconstpointer data)
4001 MonoProperty *prop = (MonoProperty*)data;
4003 return g_str_hash (prop->name);
4007 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
4009 if (method1->is_inflated)
4010 method1 = ((MonoMethodInflated*) method1)->declaring;
4011 if (method2->is_inflated)
4012 method2 = ((MonoMethodInflated*) method2)->declaring;
4014 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4018 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4020 // Properties are hide-by-name-and-signature
4021 if (!g_str_equal (prop1->name, prop2->name))
4024 /* If we see a property in a generic method, we want to
4025 compare the generic signatures, not the inflated signatures
4026 because we might conflate two properties that were
4030 public T this[T t] { getter { return t; } } // method 1
4031 public U this[U u] { getter { return u; } } // method 2
4034 If we see int Foo<int,int>::Item[int] we need to know if
4035 the indexer came from method 1 or from method 2, and we
4036 shouldn't conflate them. (Bugzilla 36283)
4038 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
4041 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4048 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4053 return method_nonpublic (accessor, start_klass);
4056 ICALL_EXPORT MonoArray*
4057 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4061 MonoClass *startklass, *klass;
4067 gchar *propname = NULL;
4068 int (*compare_func) (const char *s1, const char *s2) = NULL;
4070 GHashTable *properties = NULL;
4071 MonoPtrArray tmp_array;
4073 mono_error_init (&error);
4075 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4077 domain = ((MonoObject *)type)->vtable->domain;
4078 if (type->type->byref)
4079 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
4080 klass = startklass = mono_class_from_mono_type (type->type);
4083 propname = mono_string_to_utf8 (name);
4084 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4087 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4089 mono_class_setup_methods (klass);
4090 mono_class_setup_vtable (klass);
4091 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4095 while ((prop = mono_class_get_properties (klass, &iter))) {
4101 flags = method->flags;
4104 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4105 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4106 if (bflags & BFLAGS_Public)
4108 } else if (bflags & BFLAGS_NonPublic) {
4109 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4110 property_accessor_nonpublic(prop->set, startklass == klass)) {
4117 if (flags & METHOD_ATTRIBUTE_STATIC) {
4118 if (bflags & BFLAGS_Static)
4119 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4122 if (bflags & BFLAGS_Instance)
4131 if (compare_func (propname, prop->name))
4135 if (g_hash_table_lookup (properties, prop))
4138 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4141 mono_ptr_array_append (tmp_array, pr);
4143 g_hash_table_insert (properties, prop, prop);
4145 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4148 g_hash_table_destroy (properties);
4151 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4152 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4153 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4155 mono_ptr_array_destroy (tmp_array);
4162 if (mono_class_has_failure (klass)) {
4163 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4165 mono_error_set_from_loader_error (&error);
4166 mono_loader_clear_error ();
4171 g_hash_table_destroy (properties);
4174 mono_ptr_array_destroy (tmp_array);
4176 mono_error_set_pending_exception (&error);
4182 event_hash (gconstpointer data)
4184 MonoEvent *event = (MonoEvent*)data;
4186 return g_str_hash (event->name);
4190 event_equal (MonoEvent *event1, MonoEvent *event2)
4192 // Events are hide-by-name
4193 return g_str_equal (event1->name, event2->name);
4196 ICALL_EXPORT MonoArray*
4197 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4201 MonoClass *startklass, *klass;
4207 char *utf8_name = NULL;
4208 int (*compare_func) (const char *s1, const char *s2) = NULL;
4209 GHashTable *events = NULL;
4210 MonoPtrArray tmp_array;
4212 mono_error_init (&error);
4214 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4216 domain = mono_object_domain (type);
4217 if (type->type->byref)
4218 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4219 klass = startklass = mono_class_from_mono_type (type->type);
4221 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4223 mono_class_setup_methods (klass);
4224 mono_class_setup_vtable (klass);
4225 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4229 while ((event = mono_class_get_events (klass, &iter))) {
4231 method = event->add;
4233 method = event->remove;
4235 method = event->raise;
4237 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4238 if (bflags & BFLAGS_Public)
4240 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4241 if (bflags & BFLAGS_NonPublic)
4246 if (bflags & BFLAGS_NonPublic)
4252 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4253 if (bflags & BFLAGS_Static)
4254 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4257 if (bflags & BFLAGS_Instance)
4262 if (bflags & BFLAGS_Instance)
4268 if (utf8_name == NULL) {
4269 utf8_name = mono_string_to_utf8 (name);
4270 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4273 if (compare_func (event->name, utf8_name))
4277 if (g_hash_table_lookup (events, event))
4280 MonoReflectionEvent *ev_obj;
4281 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4284 mono_ptr_array_append (tmp_array, ev_obj);
4286 g_hash_table_insert (events, event, event);
4288 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4291 g_hash_table_destroy (events);
4293 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4295 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4296 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4298 mono_ptr_array_destroy (tmp_array);
4300 if (utf8_name != NULL)
4306 if (mono_class_has_failure (klass)) {
4307 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4309 mono_error_set_from_loader_error (&error);
4310 mono_loader_clear_error ();
4316 g_hash_table_destroy (events);
4317 if (utf8_name != NULL)
4320 mono_ptr_array_destroy (tmp_array);
4322 mono_error_set_pending_exception (&error);
4326 ICALL_EXPORT MonoArray*
4327 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4330 MonoReflectionType *rt;
4338 MonoPtrArray tmp_array;
4340 domain = ((MonoObject *)type)->vtable->domain;
4341 if (type->type->byref)
4342 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4343 klass = mono_class_from_mono_type (type->type);
4346 * If a nested type is generic, return its generic type definition.
4347 * Note that this means that the return value is essentially the set
4348 * of nested types of the generic type definition of @klass.
4350 * A note in MSDN claims that a generic type definition can have
4351 * nested types that aren't generic. In any case, the container of that
4352 * nested type would be the generic type definition.
4354 if (klass->generic_class)
4355 klass = klass->generic_class->container_class;
4357 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4359 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4361 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4362 if (bflags & BFLAGS_Public)
4365 if (bflags & BFLAGS_NonPublic)
4373 str = mono_string_to_utf8 (name);
4374 mono_identifier_unescape_type_name_chars (str);
4377 if (strcmp (nested->name, str))
4381 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4382 mono_error_raise_exception (&error);
4384 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4387 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4389 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4390 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4392 mono_ptr_array_destroy (tmp_array);
4399 ICALL_EXPORT MonoReflectionType*
4400 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4403 MonoReflectionType *ret;
4405 MonoType *type = NULL;
4406 MonoTypeNameParse info;
4407 gboolean type_resolve;
4409 /* On MS.NET, this does not fire a TypeResolve event */
4410 type_resolve = TRUE;
4411 str = mono_string_to_utf8 (name);
4412 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4413 if (!mono_reflection_parse_type (str, &info)) {
4415 mono_reflection_free_type_info (&info);
4417 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4420 /*g_print ("failed parse\n");*/
4424 if (info.assembly.name) {
4426 mono_reflection_free_type_info (&info);
4428 /* 1.0 and 2.0 throw different exceptions */
4429 if (mono_defaults.generic_ilist_class)
4430 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4432 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4438 if (module != NULL) {
4439 if (module->image) {
4440 type = mono_reflection_get_type_checked (module->image, &info, ignoreCase, &type_resolve, &error);
4441 if (!is_ok (&error)) {
4443 mono_reflection_free_type_info (&info);
4444 mono_error_set_pending_exception (&error);
4451 if (assembly_is_dynamic (assembly->assembly)) {
4452 /* Enumerate all modules */
4453 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4457 if (abuilder->modules) {
4458 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4459 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4460 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4461 if (!is_ok (&error)) {
4463 mono_reflection_free_type_info (&info);
4464 mono_error_set_pending_exception (&error);
4472 if (!type && abuilder->loaded_modules) {
4473 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4474 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4475 type = mono_reflection_get_type_checked (mod->image, &info, ignoreCase, &type_resolve, &error);
4476 if (!is_ok (&error)) {
4478 mono_reflection_free_type_info (&info);
4479 mono_error_set_pending_exception (&error);
4488 type = mono_reflection_get_type_checked (assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4489 if (!is_ok (&error)) {
4491 mono_reflection_free_type_info (&info);
4492 mono_error_set_pending_exception (&error);
4497 mono_reflection_free_type_info (&info);
4499 MonoException *e = NULL;
4502 e = mono_get_exception_type_load (name, NULL);
4504 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4505 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4507 mono_loader_clear_error ();
4510 mono_set_pending_exception (e);
4512 } else if (mono_loader_get_last_error ()) {
4514 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4517 mono_loader_clear_error ();
4520 if (type->type == MONO_TYPE_CLASS) {
4521 MonoClass *klass = mono_type_get_class (type);
4523 /* need to report exceptions ? */
4524 if (throwOnError && mono_class_has_failure (klass)) {
4525 /* report SecurityException (or others) that occured when loading the assembly */
4526 MonoException *exc = mono_class_get_exception_for_failure (klass);
4527 mono_loader_clear_error ();
4528 mono_set_pending_exception (exc);
4533 /* g_print ("got it\n"); */
4534 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4535 mono_error_set_pending_exception (&error);
4541 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4544 gchar *shadow_ini_file;
4547 /* Check for shadow-copied assembly */
4548 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4549 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4551 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4552 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4558 g_free (shadow_ini_file);
4559 if (content != NULL) {
4562 *filename = content;
4569 ICALL_EXPORT MonoString *
4570 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4572 MonoDomain *domain = mono_object_domain (assembly);
4573 MonoAssembly *mass = assembly->assembly;
4574 MonoString *res = NULL;
4579 if (g_path_is_absolute (mass->image->name)) {
4580 absolute = g_strdup (mass->image->name);
4581 dirname = g_path_get_dirname (absolute);
4583 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4584 dirname = g_strdup (mass->basedir);
4587 replace_shadow_path (domain, dirname, &absolute);
4592 for (i = strlen (absolute) - 1; i >= 0; i--)
4593 if (absolute [i] == '\\')
4598 uri = g_filename_to_uri (absolute, NULL, NULL);
4600 const char *prepend = "file://";
4602 if (*absolute == '/' && *(absolute + 1) == '/') {
4605 prepend = "file:///";
4608 uri = g_strconcat (prepend, absolute, NULL);
4612 res = mono_string_new (domain, uri);
4619 ICALL_EXPORT MonoBoolean
4620 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4622 MonoAssembly *mass = assembly->assembly;
4624 return mass->in_gac;
4627 ICALL_EXPORT MonoReflectionAssembly*
4628 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4633 MonoImageOpenStatus status;
4634 MonoReflectionAssembly* result = NULL;
4636 name = mono_string_to_utf8 (mname);
4637 res = mono_assembly_load_with_partial_name (name, &status);
4643 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4645 mono_error_set_pending_exception (&error);
4649 ICALL_EXPORT MonoString *
4650 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4652 MonoDomain *domain = mono_object_domain (assembly);
4655 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4660 ICALL_EXPORT MonoBoolean
4661 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4663 return assembly->assembly->ref_only;
4666 ICALL_EXPORT MonoString *
4667 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4669 MonoDomain *domain = mono_object_domain (assembly);
4671 return mono_string_new (domain, assembly->assembly->image->version);
4674 ICALL_EXPORT MonoReflectionMethod*
4675 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4678 MonoReflectionMethod *res = NULL;
4681 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4685 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4686 if (!mono_error_ok (&error))
4689 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4692 if (!mono_error_ok (&error))
4693 mono_error_set_pending_exception (&error);
4697 ICALL_EXPORT MonoReflectionModule*
4698 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4701 MonoReflectionModule *result = NULL;
4702 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4703 if (!mono_error_ok (&error))
4704 mono_error_set_pending_exception (&error);
4708 ICALL_EXPORT MonoArray*
4709 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4711 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4712 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4716 for (i = 0; i < table->rows; ++i) {
4717 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4718 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4724 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4726 static MonoMethod *create_version = NULL;
4730 mono_error_init (error);
4733 if (!create_version) {
4734 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4735 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4736 g_assert (create_version);
4737 mono_method_desc_free (desc);
4743 args [3] = &revision;
4744 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4745 return_val_if_nok (error, NULL);
4747 mono_runtime_invoke_checked (create_version, result, args, error);
4748 return_val_if_nok (error, NULL);
4753 ICALL_EXPORT MonoArray*
4754 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4758 MonoDomain *domain = mono_object_domain (assembly);
4760 static MonoMethod *create_culture = NULL;
4761 MonoImage *image = assembly->assembly->image;
4765 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4768 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4770 if (count > 0 && !create_culture) {
4771 MonoMethodDesc *desc = mono_method_desc_new (
4772 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4773 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4774 g_assert (create_culture);
4775 mono_method_desc_free (desc);
4778 for (i = 0; i < count; i++) {
4779 MonoObject *version;
4780 MonoReflectionAssemblyName *aname;
4781 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4783 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4785 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4786 domain, mono_class_get_assembly_name_class (), &error);
4787 mono_error_raise_exception (&error);
4789 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4791 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4792 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4793 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4794 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4795 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4796 aname->versioncompat = 1; /* SameMachine (default) */
4797 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4799 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4800 mono_error_raise_exception (&error);
4802 MONO_OBJECT_SETREF (aname, version, version);
4804 if (create_culture) {
4806 MonoBoolean assembly_ref = 1;
4807 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4808 args [1] = &assembly_ref;
4810 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4811 mono_error_raise_exception (&error);
4813 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4816 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4817 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4818 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4820 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4821 /* public key token isn't copied - the class library will
4822 automatically generate it from the public key if required */
4823 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4824 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4826 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4827 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4830 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4833 /* note: this function doesn't return the codebase on purpose (i.e. it can
4834 be used under partial trust as path information isn't present). */
4836 mono_array_setref (result, i, aname);
4841 /* move this in some file in mono/util/ */
4843 g_concat_dir_and_file (const char *dir, const char *file)
4845 g_return_val_if_fail (dir != NULL, NULL);
4846 g_return_val_if_fail (file != NULL, NULL);
4849 * If the directory name doesn't have a / on the end, we need
4850 * to add one so we get a proper path to the file
4852 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4853 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4855 return g_strconcat (dir, file, NULL);
4859 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4862 char *n = mono_string_to_utf8 (name);
4863 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4865 guint32 cols [MONO_MANIFEST_SIZE];
4866 guint32 impl, file_idx;
4870 for (i = 0; i < table->rows; ++i) {
4871 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4872 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4873 if (strcmp (val, n) == 0)
4877 if (i == table->rows)
4880 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4883 * this code should only be called after obtaining the
4884 * ResourceInfo and handling the other cases.
4886 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4887 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4889 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4894 module = assembly->assembly->image;
4897 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4898 mono_error_raise_exception (&error);
4899 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4901 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4904 ICALL_EXPORT gboolean
4905 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4908 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4910 guint32 cols [MONO_MANIFEST_SIZE];
4911 guint32 file_cols [MONO_FILE_SIZE];
4915 n = mono_string_to_utf8 (name);
4916 for (i = 0; i < table->rows; ++i) {
4917 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4918 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4919 if (strcmp (val, n) == 0)
4923 if (i == table->rows)
4926 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4927 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4930 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4931 case MONO_IMPLEMENTATION_FILE:
4932 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4933 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4934 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4935 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4936 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4937 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4940 info->location = RESOURCE_LOCATION_EMBEDDED;
4943 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4944 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4945 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4946 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4947 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4948 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4950 mono_set_pending_exception (ex);
4953 MonoReflectionAssembly *assm_obj;
4954 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4956 mono_error_set_pending_exception (&error);
4959 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4961 /* Obtain info recursively */
4962 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4963 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4966 case MONO_IMPLEMENTATION_EXP_TYPE:
4967 g_assert_not_reached ();
4975 ICALL_EXPORT MonoObject*
4976 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4978 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4979 MonoArray *result = NULL;
4984 /* check hash if needed */
4986 n = mono_string_to_utf8 (name);
4987 for (i = 0; i < table->rows; ++i) {
4988 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4989 if (strcmp (val, n) == 0) {
4992 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4993 fn = mono_string_new (mono_object_domain (assembly), n);
4995 return (MonoObject*)fn;
5003 for (i = 0; i < table->rows; ++i) {
5004 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5008 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
5011 for (i = 0; i < table->rows; ++i) {
5012 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5013 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5014 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5015 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5020 return (MonoObject*)result;
5023 ICALL_EXPORT MonoArray*
5024 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5027 MonoDomain *domain = mono_domain_get();
5030 int i, j, file_count = 0;
5031 MonoImage **modules;
5032 guint32 module_count, real_module_count;
5033 MonoTableInfo *table;
5034 guint32 cols [MONO_FILE_SIZE];
5035 MonoImage *image = assembly->assembly->image;
5037 g_assert (image != NULL);
5038 g_assert (!assembly_is_dynamic (assembly->assembly));
5040 table = &image->tables [MONO_TABLE_FILE];
5041 file_count = table->rows;
5043 modules = image->modules;
5044 module_count = image->module_count;
5046 real_module_count = 0;
5047 for (i = 0; i < module_count; ++i)
5049 real_module_count ++;
5051 klass = mono_class_get_module_class ();
5052 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
5054 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5055 mono_error_raise_exception (&error);
5056 mono_array_setref (res, 0, image_obj);
5058 for (i = 0; i < module_count; ++i)
5060 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5061 mono_error_raise_exception (&error);
5062 mono_array_setref (res, j, rm);
5066 for (i = 0; i < file_count; ++i, ++j) {
5067 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5068 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5069 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5070 mono_error_raise_exception (&error);
5071 mono_array_setref (res, j, rm);
5074 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5076 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5077 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5080 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5081 mono_error_raise_exception (&error);
5082 mono_array_setref (res, j, rm);
5089 ICALL_EXPORT MonoReflectionMethod*
5090 ves_icall_GetCurrentMethod (void)
5092 MonoReflectionMethod *res = NULL;
5095 MonoMethod *m = mono_method_get_last_managed ();
5098 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5102 while (m->is_inflated)
5103 m = ((MonoMethodInflated*)m)->declaring;
5105 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5106 mono_error_raise_exception (&error);
5112 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5115 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5118 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5119 //method is inflated, we should inflate it on the other class
5120 MonoGenericContext ctx;
5121 ctx.method_inst = inflated->context.method_inst;
5122 ctx.class_inst = inflated->context.class_inst;
5123 if (klass->generic_class)
5124 ctx.class_inst = klass->generic_class->context.class_inst;
5125 else if (klass->generic_container)
5126 ctx.class_inst = klass->generic_container->context.class_inst;
5127 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5128 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5132 mono_class_setup_methods (method->klass);
5133 if (mono_class_has_failure (method->klass))
5135 for (i = 0; i < method->klass->method.count; ++i) {
5136 if (method->klass->methods [i] == method) {
5141 mono_class_setup_methods (klass);
5142 if (mono_class_has_failure (klass))
5144 g_assert (offset >= 0 && offset < klass->method.count);
5145 return klass->methods [offset];
5148 ICALL_EXPORT MonoReflectionMethod*
5149 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5151 MonoReflectionMethod *res = NULL;
5155 klass = mono_class_from_mono_type (type);
5156 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5158 if (method->klass != klass) {
5159 method = mono_method_get_equivalent_method (method, klass);
5164 klass = method->klass;
5165 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5166 mono_error_raise_exception (&error);
5170 ICALL_EXPORT MonoReflectionMethodBody*
5171 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5174 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5175 mono_error_set_pending_exception (&error);
5179 ICALL_EXPORT MonoReflectionAssembly*
5180 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5183 MonoReflectionAssembly *result;
5184 MonoMethod *dest = NULL;
5186 mono_stack_walk_no_il (get_executing, &dest);
5188 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5190 mono_error_set_pending_exception (&error);
5195 ICALL_EXPORT MonoReflectionAssembly*
5196 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5199 MonoReflectionAssembly *result;
5200 MonoDomain* domain = mono_domain_get ();
5202 if (!domain->entry_assembly)
5205 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5207 mono_error_set_pending_exception (&error);
5211 ICALL_EXPORT MonoReflectionAssembly*
5212 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5217 MonoReflectionAssembly *result;
5220 mono_stack_walk_no_il (get_executing, &dest);
5222 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5226 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5229 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5231 mono_error_set_pending_exception (&error);
5235 ICALL_EXPORT MonoString *
5236 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5237 gboolean assembly_qualified)
5239 MonoDomain *domain = mono_object_domain (object);
5240 MonoTypeNameFormat format;
5245 format = assembly_qualified ?
5246 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5247 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5249 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5251 name = mono_type_get_name_full (object->type, format);
5255 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5260 res = mono_string_new (domain, name);
5267 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5270 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5272 mono_class_init_checked (klass, &error);
5273 mono_error_raise_exception (&error);
5274 return mono_security_core_clr_class_level (klass);
5278 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5280 MonoClassField *field = rfield->field;
5281 return mono_security_core_clr_field_level (field, TRUE);
5285 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5287 MonoMethod *method = rfield->method;
5288 return mono_security_core_clr_method_level (method, TRUE);
5292 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)
5294 static MonoMethod *create_culture = NULL;
5298 const char *pkey_ptr;
5300 MonoBoolean assembly_ref = 0;
5302 mono_error_init (error);
5304 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5305 aname->major = name->major;
5306 aname->minor = name->minor;
5307 aname->build = name->build;
5308 aname->flags = name->flags;
5309 aname->revision = name->revision;
5310 aname->hashalg = name->hash_alg;
5311 aname->versioncompat = 1; /* SameMachine (default) */
5312 aname->processor_architecture = name->arch;
5314 if (by_default_version) {
5315 MonoObject *version;
5317 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5318 return_if_nok (error);
5320 MONO_OBJECT_SETREF (aname, version, version);
5324 if (absolute != NULL && *absolute != '\0') {
5325 const gchar *prepend = "file://";
5328 codebase = g_strdup (absolute);
5333 for (i = strlen (codebase) - 1; i >= 0; i--)
5334 if (codebase [i] == '\\')
5337 if (*codebase == '/' && *(codebase + 1) == '/') {
5340 prepend = "file:///";
5344 result = g_strconcat (prepend, codebase, NULL);
5350 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5354 if (!create_culture) {
5355 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5356 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5357 g_assert (create_culture);
5358 mono_method_desc_free (desc);
5361 if (name->culture) {
5362 args [0] = mono_string_new (domain, name->culture);
5363 args [1] = &assembly_ref;
5365 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5366 return_if_nok (error);
5368 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5371 if (name->public_key) {
5372 pkey_ptr = (char*)name->public_key;
5373 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5375 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5376 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5377 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5378 } else if (default_publickey) {
5379 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5380 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5383 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5384 if (name->public_key_token [0]) {
5388 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5389 p = mono_array_addr (aname->keyToken, char, 0);
5391 for (i = 0, j = 0; i < 8; i++) {
5392 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5393 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5396 } else if (default_token) {
5397 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5401 ICALL_EXPORT MonoString *
5402 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5404 MonoDomain *domain = mono_object_domain (assembly);
5405 MonoAssembly *mass = assembly->assembly;
5409 name = mono_stringify_assembly_name (&mass->aname);
5410 res = mono_string_new (domain, name);
5417 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5421 MonoAssembly *mass = assembly->assembly;
5423 if (g_path_is_absolute (mass->image->name)) {
5424 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5425 mono_error_set_pending_exception (&error);
5428 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5430 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5431 mono_error_set_pending_exception (&error);
5437 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5441 MonoImageOpenStatus status = MONO_IMAGE_OK;
5444 MonoAssemblyName name;
5447 filename = mono_string_to_utf8 (fname);
5449 dirname = g_path_get_dirname (filename);
5450 replace_shadow_path (mono_domain_get (), dirname, &filename);
5453 image = mono_image_open (filename, &status);
5459 if (status == MONO_IMAGE_IMAGE_INVALID)
5460 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5462 exc = mono_get_exception_file_not_found2 (NULL, fname);
5463 mono_set_pending_exception (exc);
5467 res = mono_assembly_fill_assembly_name (image, &name);
5469 mono_image_close (image);
5471 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5475 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5476 mono_error_set_pending_exception (&error);
5478 mono_image_close (image);
5482 ICALL_EXPORT MonoBoolean
5483 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5484 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5486 MonoBoolean result = FALSE;
5487 MonoDeclSecurityEntry entry;
5489 /* SecurityAction.RequestMinimum */
5490 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5491 *minimum = entry.blob;
5492 *minLength = entry.size;
5495 /* SecurityAction.RequestOptional */
5496 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5497 *optional = entry.blob;
5498 *optLength = entry.size;
5501 /* SecurityAction.RequestRefuse */
5502 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5503 *refused = entry.blob;
5504 *refLength = entry.size;
5512 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5514 guint32 attrs, visibility;
5516 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5517 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5518 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5521 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5527 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5529 MonoReflectionType *rt;
5532 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5535 mono_error_init (error);
5537 /* we start the count from 1 because we skip the special type <Module> */
5540 for (i = 1; i < tdef->rows; ++i) {
5541 if (mono_module_type_is_visible (tdef, image, i + 1))
5545 count = tdef->rows - 1;
5547 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5548 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5550 for (i = 1; i < tdef->rows; ++i) {
5551 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5552 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5553 mono_loader_assert_no_error (); /* Plug any leaks */
5556 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5557 return_val_if_nok (error, NULL);
5559 mono_array_setref (res, count, rt);
5561 MonoException *ex = mono_error_convert_to_exception (error);
5562 mono_array_setref (*exceptions, count, ex);
5571 ICALL_EXPORT MonoArray*
5572 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5575 MonoArray *res = NULL;
5576 MonoArray *exceptions = NULL;
5577 MonoImage *image = NULL;
5578 MonoTableInfo *table = NULL;
5581 int i, len, ex_count;
5583 domain = mono_object_domain (assembly);
5585 g_assert (!assembly_is_dynamic (assembly->assembly));
5586 image = assembly->assembly->image;
5587 table = &image->tables [MONO_TABLE_FILE];
5588 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5589 mono_error_raise_exception (&error);
5591 /* Append data from all modules in the assembly */
5592 for (i = 0; i < table->rows; ++i) {
5593 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5594 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5599 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5600 mono_error_raise_exception (&error);
5602 /* Append the new types to the end of the array */
5603 if (mono_array_length (res2) > 0) {
5605 MonoArray *res3, *ex3;
5607 len1 = mono_array_length (res);
5608 len2 = mono_array_length (res2);
5610 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5611 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5612 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5615 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5616 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5617 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5624 /* the ReflectionTypeLoadException must have all the types (Types property),
5625 * NULL replacing types which throws an exception. The LoaderException must
5626 * contain all exceptions for NULL items.
5629 len = mono_array_length (res);
5632 for (i = 0; i < len; i++) {
5633 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5637 klass = mono_type_get_class (t->type);
5638 if ((klass != NULL) && mono_class_has_failure (klass)) {
5639 /* keep the class in the list */
5640 list = g_list_append (list, klass);
5641 /* and replace Type with NULL */
5642 mono_array_setref (res, i, NULL);
5649 if (list || ex_count) {
5651 MonoException *exc = NULL;
5652 MonoArray *exl = NULL;
5653 int j, length = g_list_length (list) + ex_count;
5655 mono_loader_clear_error ();
5657 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5658 /* Types for which mono_class_get_checked () succeeded */
5659 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5660 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5661 mono_array_setref (exl, i, exc);
5663 /* Types for which it don't */
5664 for (j = 0; j < mono_array_length (exceptions); ++j) {
5665 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5667 g_assert (i < length);
5668 mono_array_setref (exl, i, exc);
5675 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5676 if (!is_ok (&error)) {
5677 mono_error_set_pending_exception (&error);
5680 mono_loader_clear_error ();
5681 mono_set_pending_exception (exc);
5688 ICALL_EXPORT gboolean
5689 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5692 MonoAssemblyName aname;
5693 MonoDomain *domain = mono_object_domain (name);
5695 gboolean is_version_defined;
5696 gboolean is_token_defined;
5698 aname.public_key = NULL;
5699 val = mono_string_to_utf8 (assname);
5700 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5701 g_free ((guint8*) aname.public_key);
5706 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5707 mono_error_set_pending_exception (&error);
5709 mono_assembly_name_free (&aname);
5710 g_free ((guint8*) aname.public_key);
5716 ICALL_EXPORT MonoReflectionType*
5717 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5720 MonoReflectionType *ret;
5721 MonoDomain *domain = mono_object_domain (module);
5724 g_assert (module->image);
5726 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5727 /* These images do not have a global type */
5730 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5731 if (!mono_error_ok (&error)) {
5732 mono_error_set_pending_exception (&error);
5736 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5737 if (!mono_error_ok (&error)) {
5738 mono_error_set_pending_exception (&error);
5746 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5748 /*if (module->image)
5749 mono_image_close (module->image);*/
5752 ICALL_EXPORT MonoString*
5753 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5755 MonoDomain *domain = mono_object_domain (module);
5757 g_assert (module->image);
5758 return mono_string_new (domain, module->image->guid);
5761 ICALL_EXPORT gpointer
5762 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5765 if (module->image && module->image->is_module_handle)
5766 return module->image->raw_data;
5769 return (gpointer) (-1);
5773 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5775 if (image_is_dynamic (image)) {
5776 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5777 *pe_kind = dyn->pe_kind;
5778 *machine = dyn->machine;
5781 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5782 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5787 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5789 return (image->md_version_major << 16) | (image->md_version_minor);
5792 ICALL_EXPORT MonoArray*
5793 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5796 MonoArray *exceptions;
5800 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5804 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5805 mono_error_raise_exception (&error);
5807 for (i = 0; i < mono_array_length (exceptions); ++i) {
5808 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5810 mono_set_pending_exception (ex);
5819 mono_memberref_is_method (MonoImage *image, guint32 token)
5821 if (!image_is_dynamic (image)) {
5822 guint32 cols [MONO_MEMBERREF_SIZE];
5824 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5825 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5826 mono_metadata_decode_blob_size (sig, &sig);
5827 return (*sig != 0x6);
5829 MonoClass *handle_class;
5831 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5834 return mono_defaults.methodhandle_class == handle_class;
5839 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5842 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5843 mono_array_addr (type_args, MonoType*, 0));
5845 context->class_inst = NULL;
5847 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5848 mono_array_addr (method_args, MonoType*, 0));
5850 context->method_inst = NULL;
5853 ICALL_EXPORT MonoType*
5854 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5857 int table = mono_metadata_token_table (token);
5858 int index = mono_metadata_token_index (token);
5859 MonoGenericContext context;
5862 *resolve_error = ResolveTokenError_Other;
5864 /* Validate token */
5865 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5866 (table != MONO_TABLE_TYPESPEC)) {
5867 *resolve_error = ResolveTokenError_BadTable;
5871 if (image_is_dynamic (image)) {
5872 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5873 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5874 return klass ? &klass->byval_arg : NULL;
5877 init_generic_context_from_args (&context, type_args, method_args);
5878 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5879 return klass ? &klass->byval_arg : NULL;
5882 if ((index <= 0) || (index > image->tables [table].rows)) {
5883 *resolve_error = ResolveTokenError_OutOfRange;
5887 init_generic_context_from_args (&context, type_args, method_args);
5888 klass = mono_class_get_checked (image, token, &error);
5890 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5891 if (!mono_error_ok (&error)) {
5892 mono_error_set_pending_exception (&error);
5897 return &klass->byval_arg;
5902 ICALL_EXPORT MonoMethod*
5903 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5906 int table = mono_metadata_token_table (token);
5907 int index = mono_metadata_token_index (token);
5908 MonoGenericContext context;
5911 *resolve_error = ResolveTokenError_Other;
5913 /* Validate token */
5914 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5915 (table != MONO_TABLE_MEMBERREF)) {
5916 *resolve_error = ResolveTokenError_BadTable;
5920 if (image_is_dynamic (image)) {
5921 if (table == MONO_TABLE_METHOD)
5922 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5924 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5925 *resolve_error = ResolveTokenError_BadTable;
5929 init_generic_context_from_args (&context, type_args, method_args);
5930 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5933 if ((index <= 0) || (index > image->tables [table].rows)) {
5934 *resolve_error = ResolveTokenError_OutOfRange;
5937 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5938 *resolve_error = ResolveTokenError_BadTable;
5942 init_generic_context_from_args (&context, type_args, method_args);
5943 method = mono_get_method_checked (image, token, NULL, &context, &error);
5944 mono_error_set_pending_exception (&error);
5949 ICALL_EXPORT MonoString*
5950 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5952 int index = mono_metadata_token_index (token);
5954 *error = ResolveTokenError_Other;
5956 /* Validate token */
5957 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5958 *error = ResolveTokenError_BadTable;
5962 if (image_is_dynamic (image))
5963 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5965 if ((index <= 0) || (index >= image->heap_us.size)) {
5966 *error = ResolveTokenError_OutOfRange;
5970 /* FIXME: What to do if the index points into the middle of a string ? */
5972 return mono_ldstr (mono_domain_get (), image, index);
5975 ICALL_EXPORT MonoClassField*
5976 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5980 int table = mono_metadata_token_table (token);
5981 int index = mono_metadata_token_index (token);
5982 MonoGenericContext context;
5983 MonoClassField *field;
5985 *resolve_error = ResolveTokenError_Other;
5987 /* Validate token */
5988 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5989 *resolve_error = ResolveTokenError_BadTable;
5993 if (image_is_dynamic (image)) {
5994 if (table == MONO_TABLE_FIELD)
5995 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5997 if (mono_memberref_is_method (image, token)) {
5998 *resolve_error = ResolveTokenError_BadTable;
6002 init_generic_context_from_args (&context, type_args, method_args);
6003 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
6006 if ((index <= 0) || (index > image->tables [table].rows)) {
6007 *resolve_error = ResolveTokenError_OutOfRange;
6010 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6011 *resolve_error = ResolveTokenError_BadTable;
6015 init_generic_context_from_args (&context, type_args, method_args);
6016 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6017 mono_error_set_pending_exception (&error);
6023 ICALL_EXPORT MonoObject*
6024 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6028 int table = mono_metadata_token_table (token);
6030 *error = ResolveTokenError_Other;
6033 case MONO_TABLE_TYPEDEF:
6034 case MONO_TABLE_TYPEREF:
6035 case MONO_TABLE_TYPESPEC: {
6036 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6038 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6039 mono_error_raise_exception (&merror);
6046 case MONO_TABLE_METHOD:
6047 case MONO_TABLE_METHODSPEC: {
6048 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6050 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6051 mono_error_raise_exception (&merror);
6057 case MONO_TABLE_FIELD: {
6058 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6060 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6061 mono_error_raise_exception (&merror);
6067 case MONO_TABLE_MEMBERREF:
6068 if (mono_memberref_is_method (image, token)) {
6069 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6071 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6072 mono_error_raise_exception (&merror);
6079 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6081 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6082 mono_error_raise_exception (&merror);
6091 *error = ResolveTokenError_BadTable;
6097 ICALL_EXPORT MonoArray*
6098 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
6100 int table = mono_metadata_token_table (token);
6101 int idx = mono_metadata_token_index (token);
6102 MonoTableInfo *tables = image->tables;
6107 *error = ResolveTokenError_OutOfRange;
6109 /* FIXME: Support other tables ? */
6110 if (table != MONO_TABLE_STANDALONESIG)
6113 if (image_is_dynamic (image))
6116 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6119 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6121 ptr = mono_metadata_blob_heap (image, sig);
6122 len = mono_metadata_decode_blob_size (ptr, &ptr);
6124 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
6125 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6129 ICALL_EXPORT MonoReflectionType*
6130 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6133 MonoReflectionType *ret;
6135 int isbyref = 0, rank;
6136 char *str = mono_string_to_utf8 (smodifiers);
6139 klass = mono_class_from_mono_type (tb->type.type);
6141 /* logic taken from mono_reflection_parse_type(): keep in sync */
6145 if (isbyref) { /* only one level allowed by the spec */
6154 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6155 mono_error_raise_exception (&error);
6159 klass = mono_ptr_class_get (&klass->byval_arg);
6160 mono_class_init (klass);
6171 else if (*p != '*') { /* '*' means unknown lower bound */
6182 klass = mono_array_class_get (klass, rank);
6183 mono_class_init (klass);
6192 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6193 mono_error_raise_exception (&error);
6198 ICALL_EXPORT MonoBoolean
6199 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6205 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6211 check_for_invalid_type (MonoClass *klass, MonoError *error)
6216 mono_error_init (error);
6218 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6221 name = mono_type_get_full_name (klass);
6222 str = mono_string_new (mono_domain_get (), name);
6224 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6227 ICALL_EXPORT MonoReflectionType *
6228 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6231 MonoReflectionType *ret;
6232 MonoClass *klass, *aklass;
6234 klass = mono_class_from_mono_type (type->type);
6235 check_for_invalid_type (klass, &error);
6236 mono_error_raise_exception (&error);
6238 if (rank == 0) //single dimentional array
6239 aklass = mono_array_class_get (klass, 1);
6241 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6243 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6244 mono_error_raise_exception (&error);
6249 ICALL_EXPORT MonoReflectionType *
6250 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6253 MonoReflectionType *ret;
6256 klass = mono_class_from_mono_type (type->type);
6257 mono_class_init_checked (klass, &error);
6258 mono_error_raise_exception (&error);
6259 check_for_invalid_type (klass, &error);
6260 mono_error_raise_exception (&error);
6262 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6263 mono_error_raise_exception (&error);
6268 ICALL_EXPORT MonoReflectionType *
6269 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6272 MonoReflectionType *ret;
6273 MonoClass *klass, *pklass;
6275 klass = mono_class_from_mono_type (type->type);
6276 mono_class_init_checked (klass, &error);
6277 mono_error_raise_exception (&error);
6278 check_for_invalid_type (klass, &error);
6279 mono_error_raise_exception (&error);
6281 pklass = mono_ptr_class_get (type->type);
6283 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6284 mono_error_raise_exception (&error);
6289 ICALL_EXPORT MonoObject *
6290 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6291 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6294 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6295 MonoObject *delegate;
6297 MonoMethod *method = info->method;
6299 mono_class_init_checked (delegate_class, &error);
6300 mono_error_raise_exception (&error);
6302 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6303 /* FIXME improve this exception message */
6304 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6306 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6307 mono_error_set_pending_exception (&error);
6311 if (mono_security_core_clr_enabled ()) {
6312 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6316 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6317 mono_error_raise_exception (&error);
6319 if (method_is_dynamic (method)) {
6320 /* Creating a trampoline would leak memory */
6321 func = mono_compile_method (method);
6323 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6324 method = mono_object_get_virtual_method (target, method);
6325 func = mono_create_ftnptr (mono_domain_get (),
6326 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6329 mono_delegate_ctor_with_method (delegate, target, func, method);
6334 ICALL_EXPORT MonoMulticastDelegate *
6335 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6338 MonoMulticastDelegate *ret;
6340 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6342 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6343 mono_error_raise_exception (&error);
6344 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6349 ICALL_EXPORT MonoReflectionMethod*
6350 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6352 MonoReflectionMethod *ret = NULL;
6354 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6355 mono_error_raise_exception (&error);
6361 static inline gint32
6362 mono_array_get_byte_length (MonoArray *array)
6368 klass = array->obj.vtable->klass;
6370 if (array->bounds == NULL)
6371 length = array->max_length;
6374 for (i = 0; i < klass->rank; ++ i)
6375 length *= array->bounds [i].length;
6378 switch (klass->element_class->byval_arg.type) {
6381 case MONO_TYPE_BOOLEAN:
6385 case MONO_TYPE_CHAR:
6393 return length * sizeof (gpointer);
6404 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6406 return mono_array_get_byte_length (array);
6410 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6412 return mono_array_get (array, gint8, idx);
6416 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6418 mono_array_set (array, gint8, idx, value);
6421 ICALL_EXPORT MonoBoolean
6422 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6424 guint8 *src_buf, *dest_buf;
6427 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6431 g_assert (count >= 0);
6433 /* This is called directly from the class libraries without going through the managed wrapper */
6434 MONO_CHECK_ARG_NULL (src, FALSE);
6435 MONO_CHECK_ARG_NULL (dest, FALSE);
6437 /* watch out for integer overflow */
6438 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6441 src_buf = (guint8 *)src->vector + src_offset;
6442 dest_buf = (guint8 *)dest->vector + dest_offset;
6445 memcpy (dest_buf, src_buf, count);
6447 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6452 #ifndef DISABLE_REMOTING
6453 ICALL_EXPORT MonoObject *
6454 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6457 MonoDomain *domain = mono_object_domain (this_obj);
6459 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6460 MonoTransparentProxy *tp;
6464 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6465 mono_error_raise_exception (&error);
6466 tp = (MonoTransparentProxy*) res;
6468 MONO_OBJECT_SETREF (tp, rp, rp);
6469 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6470 klass = mono_class_from_mono_type (type);
6472 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6473 mono_class_setup_vtable (klass);
6474 if (mono_class_has_failure (klass)) {
6475 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6479 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6480 if (!is_ok (&error)) {
6481 mono_error_set_pending_exception (&error);
6484 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6485 if (!is_ok (&error)) {
6486 mono_error_set_pending_exception (&error);
6490 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6494 ICALL_EXPORT MonoReflectionType *
6495 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6498 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6499 mono_error_raise_exception (&error);
6505 /* System.Environment */
6508 ves_icall_System_Environment_get_UserName (void)
6510 /* using glib is more portable */
6511 return mono_string_new (mono_domain_get (), g_get_user_name ());
6515 ICALL_EXPORT MonoString *
6516 ves_icall_System_Environment_get_MachineName (void)
6518 #if defined (HOST_WIN32)
6523 len = MAX_COMPUTERNAME_LENGTH + 1;
6524 buf = g_new (gunichar2, len);
6527 if (GetComputerName (buf, (PDWORD) &len)) {
6529 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6530 mono_error_raise_exception (&error);
6535 #elif !defined(DISABLE_SOCKETS)
6539 #if defined _SC_HOST_NAME_MAX
6540 n = sysconf (_SC_HOST_NAME_MAX);
6544 buf = g_malloc (n+1);
6546 if (gethostname (buf, n) == 0){
6548 result = mono_string_new (mono_domain_get (), buf);
6555 return mono_string_new (mono_domain_get (), "mono");
6560 ves_icall_System_Environment_get_Platform (void)
6562 #if defined (TARGET_WIN32)
6565 #elif defined(__MACH__)
6568 // Notice that the value is hidden from user code, and only exposed
6569 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6570 // define and making assumptions based on Unix/128/4 values before there
6571 // was a MacOS define. Lots of code would assume that not-Unix meant
6572 // Windows, but in this case, it would be OSX.
6581 ICALL_EXPORT MonoString *
6582 ves_icall_System_Environment_get_NewLine (void)
6584 #if defined (HOST_WIN32)
6585 return mono_string_new (mono_domain_get (), "\r\n");
6587 return mono_string_new (mono_domain_get (), "\n");
6591 ICALL_EXPORT MonoBoolean
6592 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6594 #if SIZEOF_VOID_P == 8
6598 gboolean isWow64Process = FALSE;
6599 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6600 return (MonoBoolean)isWow64Process;
6602 #elif defined(HAVE_SYS_UTSNAME_H)
6603 struct utsname name;
6605 if (uname (&name) >= 0) {
6606 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6613 ICALL_EXPORT MonoString *
6614 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6622 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6623 value = g_getenv (utf8_name);
6630 return mono_string_new (mono_domain_get (), value);
6634 * There is no standard way to get at environ.
6637 #ifndef __MINGW32_VERSION
6638 #if defined(__APPLE__)
6639 #if defined (TARGET_OSX)
6640 /* Apple defines this in crt_externs.h but doesn't provide that header for
6641 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6642 * in fact exist on all implementations (so far)
6644 gchar ***_NSGetEnviron(void);
6645 #define environ (*_NSGetEnviron())
6647 static char *mono_environ[1] = { NULL };
6648 #define environ mono_environ
6649 #endif /* defined (TARGET_OSX) */
6657 ICALL_EXPORT MonoArray *
6658 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6669 env_strings = GetEnvironmentStrings();
6672 env_string = env_strings;
6673 while (*env_string != '\0') {
6674 /* weird case that MS seems to skip */
6675 if (*env_string != '=')
6677 while (*env_string != '\0')
6683 domain = mono_domain_get ();
6684 names = mono_array_new (domain, mono_defaults.string_class, n);
6688 env_string = env_strings;
6689 while (*env_string != '\0') {
6690 /* weird case that MS seems to skip */
6691 if (*env_string != '=') {
6692 equal_str = wcschr(env_string, '=');
6693 g_assert(equal_str);
6695 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6696 mono_error_raise_exception (&error);
6697 mono_array_setref (names, n, str);
6700 while (*env_string != '\0')
6705 FreeEnvironmentStrings (env_strings);
6718 for (e = environ; *e != 0; ++ e)
6721 domain = mono_domain_get ();
6722 names = mono_array_new (domain, mono_defaults.string_class, n);
6725 for (e = environ; *e != 0; ++ e) {
6726 parts = g_strsplit (*e, "=", 2);
6728 str = mono_string_new (domain, *parts);
6729 mono_array_setref (names, n, str);
6742 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6744 #if !GLIB_CHECK_VERSION(2,4,0)
6745 #define g_setenv(a,b,c) setenv(a,b,c)
6746 #define g_unsetenv(a) unsetenv(a)
6750 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6753 gunichar2 *utf16_name, *utf16_value;
6755 gchar *utf8_name, *utf8_value;
6760 utf16_name = mono_string_to_utf16 (name);
6761 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6762 SetEnvironmentVariable (utf16_name, NULL);
6763 g_free (utf16_name);
6767 utf16_value = mono_string_to_utf16 (value);
6769 SetEnvironmentVariable (utf16_name, utf16_value);
6771 g_free (utf16_name);
6772 g_free (utf16_value);
6774 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6776 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6777 g_unsetenv (utf8_name);
6782 utf8_value = mono_string_to_utf8_checked (value, &error);
6783 if (!mono_error_ok (&error)) {
6785 mono_error_set_pending_exception (&error);
6788 g_setenv (utf8_name, utf8_value, TRUE);
6791 g_free (utf8_value);
6796 ves_icall_System_Environment_Exit (int result)
6798 mono_environment_exitcode_set (result);
6800 /* FIXME: There are some cleanup hangs that should be worked out, but
6801 * if the program is going to exit, everything will be cleaned up when
6802 * NaCl exits anyway.
6804 #ifndef __native_client__
6805 if (!mono_runtime_try_shutdown ())
6806 mono_thread_exit ();
6808 /* Suspend all managed threads since the runtime is going away */
6809 mono_thread_suspend_all_other_threads ();
6811 mono_runtime_quit ();
6814 /* we may need to do some cleanup here... */
6818 ICALL_EXPORT MonoString*
6819 ves_icall_System_Environment_GetGacPath (void)
6821 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6824 ICALL_EXPORT MonoString*
6825 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6827 #if defined (HOST_WIN32)
6828 #ifndef CSIDL_FLAG_CREATE
6829 #define CSIDL_FLAG_CREATE 0x8000
6832 WCHAR path [MAX_PATH];
6833 /* Create directory if no existing */
6834 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6839 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6840 mono_error_raise_exception (&error);
6844 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6846 return mono_string_new (mono_domain_get (), "");
6849 ICALL_EXPORT MonoArray *
6850 ves_icall_System_Environment_GetLogicalDrives (void)
6853 gunichar2 buf [256], *ptr, *dname;
6855 guint initial_size = 127, size = 128;
6858 MonoString *drivestr;
6859 MonoDomain *domain = mono_domain_get ();
6865 while (size > initial_size) {
6866 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6867 if (size > initial_size) {
6870 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6871 initial_size = size;
6885 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6890 while (*u16) { u16++; len ++; }
6891 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6892 mono_error_raise_exception (&error);
6893 mono_array_setref (result, ndrives++, drivestr);
6903 ICALL_EXPORT MonoString *
6904 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6906 gunichar2 volume_name [MAX_PATH + 1];
6908 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6910 return mono_string_from_utf16 (volume_name);
6913 ICALL_EXPORT MonoString *
6914 ves_icall_System_Environment_InternalGetHome (void)
6916 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6919 static const char *encodings [] = {
6921 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6922 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6923 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6925 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6926 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6927 "x_unicode_2_0_utf_7",
6929 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6930 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6932 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6935 "unicodefffe", "utf_16be",
6942 * Returns the internal codepage, if the value of "int_code_page" is
6943 * 1 at entry, and we can not compute a suitable code page number,
6944 * returns the code page as a string
6946 ICALL_EXPORT MonoString*
6947 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6952 char *codepage = NULL;
6954 int want_name = *int_code_page;
6957 *int_code_page = -1;
6959 g_get_charset (&cset);
6960 c = codepage = strdup (cset);
6961 for (c = codepage; *c; c++){
6962 if (isascii (*c) && isalpha (*c))
6967 /* g_print ("charset: %s\n", cset); */
6969 /* handle some common aliases */
6972 for (i = 0; p != 0; ){
6975 p = encodings [++i];
6978 if (strcmp (p, codepage) == 0){
6979 *int_code_page = code;
6982 p = encodings [++i];
6985 if (strstr (codepage, "utf_8") != NULL)
6986 *int_code_page |= 0x10000000;
6989 if (want_name && *int_code_page == -1)
6990 return mono_string_new (mono_domain_get (), cset);
6995 ICALL_EXPORT MonoBoolean
6996 ves_icall_System_Environment_get_HasShutdownStarted (void)
6998 if (mono_runtime_is_shutting_down ())
7001 if (mono_domain_is_unloading (mono_domain_get ()))
7008 ves_icall_System_Environment_BroadcastSettingChange (void)
7011 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7016 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7022 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
7023 MonoReflectionMethod *method,
7024 MonoArray *out_args)
7026 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
7029 #ifndef DISABLE_REMOTING
7030 ICALL_EXPORT MonoBoolean
7031 ves_icall_IsTransparentProxy (MonoObject *proxy)
7036 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7042 ICALL_EXPORT MonoReflectionMethod *
7043 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7044 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7046 MonoReflectionMethod *ret = NULL;
7051 MonoMethod **vtable;
7052 MonoMethod *res = NULL;
7054 MONO_CHECK_ARG_NULL (rtype, NULL);
7055 MONO_CHECK_ARG_NULL (rmethod, NULL);
7057 method = rmethod->method;
7058 klass = mono_class_from_mono_type (rtype->type);
7059 mono_class_init_checked (klass, &error);
7060 mono_error_raise_exception (&error);
7062 if (MONO_CLASS_IS_INTERFACE (klass))
7065 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7068 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7069 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7075 mono_class_setup_vtable (klass);
7076 vtable = klass->vtable;
7078 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7079 gboolean variance_used = FALSE;
7080 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7081 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7083 res = vtable [offs + method->slot];
7085 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7088 if (method->slot != -1)
7089 res = vtable [method->slot];
7095 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7096 mono_error_raise_exception (&error);
7101 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7107 klass = mono_class_from_mono_type (type->type);
7108 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7109 if (!is_ok (&error)) {
7110 mono_error_set_pending_exception (&error);
7114 mono_vtable_set_is_remote (vtable, enable);
7117 #else /* DISABLE_REMOTING */
7120 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7122 g_assert_not_reached ();
7127 ICALL_EXPORT MonoObject *
7128 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7135 domain = mono_object_domain (type);
7136 klass = mono_class_from_mono_type (type->type);
7137 mono_class_init_checked (klass, &error);
7138 mono_error_raise_exception (&error);
7140 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7141 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7145 if (klass->rank >= 1) {
7146 g_assert (klass->rank == 1);
7147 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7149 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7150 if (!is_ok (&error)) {
7151 mono_error_set_pending_exception (&error);
7154 /* Bypass remoting object creation check */
7155 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7156 mono_error_set_pending_exception (&error);
7162 ICALL_EXPORT MonoString *
7163 ves_icall_System_IO_get_temp_path (void)
7165 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7168 #ifndef PLATFORM_NO_DRIVEINFO
7169 ICALL_EXPORT MonoBoolean
7170 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7171 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7175 ULARGE_INTEGER wapi_free_bytes_avail;
7176 ULARGE_INTEGER wapi_total_number_of_bytes;
7177 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7179 *error = ERROR_SUCCESS;
7180 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7181 &wapi_total_number_of_free_bytes);
7184 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7185 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7186 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7188 *free_bytes_avail = 0;
7189 *total_number_of_bytes = 0;
7190 *total_number_of_free_bytes = 0;
7191 *error = GetLastError ();
7197 ICALL_EXPORT guint32
7198 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7200 return GetDriveType (mono_string_chars (root_path_name));
7204 ICALL_EXPORT gpointer
7205 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7207 return mono_compile_method (method);
7210 ICALL_EXPORT MonoString *
7211 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7216 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7218 #if defined (HOST_WIN32)
7219 /* Avoid mixing '/' and '\\' */
7222 for (i = strlen (path) - 1; i >= 0; i--)
7223 if (path [i] == '/')
7227 mcpath = mono_string_new (mono_domain_get (), path);
7234 get_bundled_app_config (void)
7236 const gchar *app_config;
7239 gchar *config_file_name, *config_file_path;
7240 gsize len, config_file_path_length, config_ext_length;
7243 domain = mono_domain_get ();
7244 file = domain->setup->configuration_file;
7245 if (!file || file->length == 0)
7248 // Retrieve config file and remove the extension
7249 config_file_name = mono_string_to_utf8 (file);
7250 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7251 if (!config_file_path)
7252 config_file_path = config_file_name;
7254 config_file_path_length = strlen (config_file_path);
7255 config_ext_length = strlen (".config");
7256 if (config_file_path_length <= config_ext_length)
7259 len = config_file_path_length - config_ext_length;
7260 module = (gchar *)g_malloc0 (len + 1);
7261 memcpy (module, config_file_path, len);
7262 // Get the config file from the module name
7263 app_config = mono_config_string_for_assembly_file (module);
7266 if (config_file_name != config_file_path)
7267 g_free (config_file_name);
7268 g_free (config_file_path);
7273 return mono_string_new (mono_domain_get (), app_config);
7277 get_bundled_machine_config (void)
7279 const gchar *machine_config;
7281 machine_config = mono_get_machine_config ();
7283 if (!machine_config)
7286 return mono_string_new (mono_domain_get (), machine_config);
7289 ICALL_EXPORT MonoString *
7290 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7295 path = g_path_get_dirname (mono_get_config_dir ());
7297 #if defined (HOST_WIN32)
7298 /* Avoid mixing '/' and '\\' */
7301 for (i = strlen (path) - 1; i >= 0; i--)
7302 if (path [i] == '/')
7306 ipath = mono_string_new (mono_domain_get (), path);
7312 ICALL_EXPORT gboolean
7313 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7315 MonoPEResourceDataEntry *entry;
7318 if (!assembly || !result || !size)
7323 image = assembly->assembly->image;
7324 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7328 *result = mono_image_rva_map (image, entry->rde_data_offset);
7333 *size = entry->rde_size;
7338 ICALL_EXPORT MonoBoolean
7339 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7341 return mono_is_debugger_attached ();
7344 ICALL_EXPORT MonoBoolean
7345 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7347 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7348 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7354 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7356 if (mono_get_runtime_callbacks ()->debug_log)
7357 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7361 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7363 #if defined (HOST_WIN32)
7364 OutputDebugString (mono_string_chars (message));
7366 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7370 /* Only used for value types */
7371 ICALL_EXPORT MonoObject *
7372 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7379 domain = mono_object_domain (type);
7380 klass = mono_class_from_mono_type (type->type);
7381 mono_class_init_checked (klass, &error);
7382 mono_error_raise_exception (&error);
7384 if (mono_class_is_nullable (klass))
7385 /* No arguments -> null */
7388 result = mono_object_new_checked (domain, klass, &error);
7389 mono_error_raise_exception (&error);
7393 ICALL_EXPORT MonoReflectionMethod *
7394 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7396 MonoReflectionMethod *ret = NULL;
7399 MonoClass *klass, *parent;
7400 MonoGenericContext *generic_inst = NULL;
7401 MonoMethod *method = m->method;
7402 MonoMethod *result = NULL;
7405 if (method->klass == NULL)
7408 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7409 MONO_CLASS_IS_INTERFACE (method->klass) ||
7410 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7413 slot = mono_method_get_vtable_slot (method);
7417 klass = method->klass;
7418 if (klass->generic_class) {
7419 generic_inst = mono_class_get_context (klass);
7420 klass = klass->generic_class->container_class;
7424 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7425 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7426 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7427 or klass is the generic container class and generic_inst is the instantiation.
7429 when we go to the parent, if the parent is an open constructed type, we need to
7430 replace the type parameters by the definitions from the generic_inst, and then take it
7431 apart again into the klass and the generic_inst.
7433 For cases like this:
7434 class C<T> : B<T, int> {
7435 public override void Foo () { ... }
7437 class B<U,V> : A<HashMap<U,V>> {
7438 public override void Foo () { ... }
7441 public virtual void Foo () { ... }
7444 if at each iteration the parent isn't open, we can skip inflating it. if at some
7445 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7448 MonoGenericContext *parent_inst = NULL;
7449 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7451 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7452 if (!mono_error_ok (&error)) {
7453 mono_error_set_pending_exception (&error);
7457 if (parent->generic_class) {
7458 parent_inst = mono_class_get_context (parent);
7459 parent = parent->generic_class->container_class;
7462 mono_class_setup_vtable (parent);
7463 if (parent->vtable_size <= slot)
7466 generic_inst = parent_inst;
7469 klass = klass->parent;
7472 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7473 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7474 if (!mono_error_ok (&error)) {
7475 mono_error_set_pending_exception (&error);
7479 generic_inst = NULL;
7481 if (klass->generic_class) {
7482 generic_inst = mono_class_get_context (klass);
7483 klass = klass->generic_class->container_class;
7489 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7490 if (!mono_error_ok (&error)) {
7491 mono_error_set_pending_exception (&error);
7496 if (klass == method->klass)
7499 /*This is possible if definition == FALSE.
7500 * Do it here to be really sure we don't read invalid memory.
7502 if (slot >= klass->vtable_size)
7505 mono_class_setup_vtable (klass);
7507 result = klass->vtable [slot];
7508 if (result == NULL) {
7509 /* It is an abstract method */
7510 gpointer iter = NULL;
7511 while ((result = mono_class_get_methods (klass, &iter)))
7512 if (result->slot == slot)
7519 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7520 mono_error_raise_exception (&error);
7524 ICALL_EXPORT MonoString*
7525 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7527 MonoMethod *method = m->method;
7529 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7534 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7536 iter->sig = *(MonoMethodSignature**)argsp;
7538 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7539 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7542 /* FIXME: it's not documented what start is exactly... */
7546 iter->args = argsp + sizeof (gpointer);
7548 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7550 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7553 ICALL_EXPORT MonoTypedRef
7554 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7556 guint32 i, arg_size;
7560 i = iter->sig->sentinelpos + iter->next_arg;
7562 g_assert (i < iter->sig->param_count);
7564 res.type = iter->sig->params [i];
7565 res.klass = mono_class_from_mono_type (res.type);
7566 arg_size = mono_type_stack_size (res.type, &align);
7567 #if defined(__arm__) || defined(__mips__)
7568 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7570 res.value = iter->args;
7571 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7572 /* Values are stored as 8 byte register sized objects, but 'value'
7573 * is dereferenced as a pointer in other routines.
7575 res.value = (char*)res.value + 4;
7577 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7578 if (arg_size <= sizeof (gpointer)) {
7580 int padding = arg_size - mono_type_size (res.type, &dummy);
7581 res.value = (guint8*)res.value + padding;
7584 iter->args = (char*)iter->args + arg_size;
7587 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7592 ICALL_EXPORT MonoTypedRef
7593 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7595 guint32 i, arg_size;
7599 i = iter->sig->sentinelpos + iter->next_arg;
7601 g_assert (i < iter->sig->param_count);
7603 while (i < iter->sig->param_count) {
7604 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7606 res.type = iter->sig->params [i];
7607 res.klass = mono_class_from_mono_type (res.type);
7608 /* FIXME: endianess issue... */
7609 arg_size = mono_type_stack_size (res.type, &align);
7610 #if defined(__arm__) || defined(__mips__)
7611 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7613 res.value = iter->args;
7614 iter->args = (char*)iter->args + arg_size;
7616 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7619 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7627 ICALL_EXPORT MonoType*
7628 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7632 i = iter->sig->sentinelpos + iter->next_arg;
7634 g_assert (i < iter->sig->param_count);
7636 return iter->sig->params [i];
7639 ICALL_EXPORT MonoObject*
7640 mono_TypedReference_ToObject (MonoTypedRef* tref)
7643 MonoObject *result = NULL;
7644 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7645 MonoObject** objp = (MonoObject **)tref->value;
7649 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7650 mono_error_set_pending_exception (&error);
7654 ICALL_EXPORT MonoTypedRef
7655 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7658 MonoReflectionField *f;
7660 MonoType *ftype = NULL;
7664 memset (&res, 0, sizeof (res));
7667 g_assert (mono_array_length (fields) > 0);
7669 klass = target->vtable->klass;
7671 for (i = 0; i < mono_array_length (fields); ++i) {
7672 f = mono_array_get (fields, MonoReflectionField*, i);
7674 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7677 if (f->field->parent != klass) {
7678 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7682 p = (guint8*)target + f->field->offset;
7684 p += f->field->offset - sizeof (MonoObject);
7685 klass = mono_class_from_mono_type (f->field->type);
7686 ftype = f->field->type;
7690 res.klass = mono_class_from_mono_type (ftype);
7697 prelink_method (MonoMethod *method, MonoError *error)
7699 const char *exc_class, *exc_arg;
7701 mono_error_init (error);
7702 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7704 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7706 mono_error_set_exception_instance (error,
7707 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7710 /* create the wrapper, too? */
7714 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7718 prelink_method (method->method, &error);
7719 mono_error_raise_exception (&error);
7723 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7726 MonoClass *klass = mono_class_from_mono_type (type->type);
7728 gpointer iter = NULL;
7730 mono_class_init_checked (klass, &error);
7731 mono_error_raise_exception (&error);
7733 while ((m = mono_class_get_methods (klass, &iter))) {
7734 prelink_method (m, &error);
7735 mono_error_raise_exception (&error);
7739 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7741 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7742 gint32 const **exponents,
7743 gunichar2 const **digitLowerTable,
7744 gunichar2 const **digitUpperTable,
7745 gint64 const **tenPowersList,
7746 gint32 const **decHexDigits)
7748 *mantissas = Formatter_MantissaBitsTable;
7749 *exponents = Formatter_TensExponentTable;
7750 *digitLowerTable = Formatter_DigitLowerTable;
7751 *digitUpperTable = Formatter_DigitUpperTable;
7752 *tenPowersList = Formatter_TenPowersList;
7753 *decHexDigits = Formatter_DecHexDigits;
7757 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7758 * and avoid useless allocations.
7761 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7763 MonoReflectionType *rt;
7767 mono_error_init (error);
7768 for (i = 0; i < type->num_mods; ++i) {
7769 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7774 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7776 for (i = 0; i < type->num_mods; ++i) {
7777 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7778 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7779 return_val_if_nok (error, NULL);
7781 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7782 return_val_if_nok (error, NULL);
7784 mono_array_setref (res, count, rt);
7791 ICALL_EXPORT MonoArray*
7792 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7795 MonoType *type = param->ClassImpl->type;
7796 MonoClass *member_class = mono_object_class (param->MemberImpl);
7797 MonoMethod *method = NULL;
7800 MonoMethodSignature *sig;
7803 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7804 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7805 method = rmethod->method;
7806 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7807 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7808 if (!(method = prop->property->get))
7809 method = prop->property->set;
7812 char *type_name = mono_type_get_full_name (member_class);
7813 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7814 MonoException *ex = mono_get_exception_not_supported (msg);
7817 mono_set_pending_exception (ex);
7821 image = method->klass->image;
7822 pos = param->PositionImpl;
7823 sig = mono_method_signature (method);
7827 type = sig->params [pos];
7829 res = type_array_from_modifiers (image, type, optional, &error);
7830 mono_error_raise_exception (&error);
7835 get_property_type (MonoProperty *prop)
7837 MonoMethodSignature *sig;
7839 sig = mono_method_signature (prop->get);
7841 } else if (prop->set) {
7842 sig = mono_method_signature (prop->set);
7843 return sig->params [sig->param_count - 1];
7848 ICALL_EXPORT MonoArray*
7849 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7852 MonoType *type = get_property_type (property->property);
7853 MonoImage *image = property->klass->image;
7858 res = type_array_from_modifiers (image, type, optional, &error);
7859 mono_error_raise_exception (&error);
7864 *Construct a MonoType suited to be used to decode a constant blob object.
7866 * @type is the target type which will be constructed
7867 * @blob_type is the blob type, for example, that comes from the constant table
7868 * @real_type is the expected constructed type.
7871 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7873 type->type = blob_type;
7874 type->data.klass = NULL;
7875 if (blob_type == MONO_TYPE_CLASS)
7876 type->data.klass = mono_defaults.object_class;
7877 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7878 /* For enums, we need to use the base type */
7879 type->type = MONO_TYPE_VALUETYPE;
7880 type->data.klass = mono_class_from_mono_type (real_type);
7882 type->data.klass = mono_class_from_mono_type (real_type);
7885 ICALL_EXPORT MonoObject*
7886 property_info_get_default_value (MonoReflectionProperty *property)
7890 MonoProperty *prop = property->property;
7891 MonoType *type = get_property_type (prop);
7892 MonoDomain *domain = mono_object_domain (property);
7893 MonoTypeEnum def_type;
7894 const char *def_value;
7897 mono_class_init (prop->parent);
7899 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7900 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7904 def_value = mono_class_get_property_default_value (prop, &def_type);
7906 mono_type_from_blob_type (&blob_type, def_type, type);
7907 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7909 mono_error_set_pending_exception (&error);
7913 ICALL_EXPORT MonoBoolean
7914 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7917 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7918 MonoCustomAttrInfo *cinfo;
7921 mono_class_init_checked (attr_class, &error);
7922 mono_error_raise_exception (&error);
7924 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7925 if (!is_ok (&error)) {
7926 mono_error_set_pending_exception (&error);
7931 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7933 mono_custom_attrs_free (cinfo);
7937 ICALL_EXPORT MonoArray*
7938 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7940 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7945 mono_class_init_checked (attr_class, &error);
7946 mono_error_raise_exception (&error);
7949 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7950 if (!mono_error_ok (&error)) {
7951 mono_error_set_pending_exception (&error);
7955 if (mono_loader_get_last_error ()) {
7956 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7963 ICALL_EXPORT MonoArray*
7964 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7968 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7969 mono_error_set_pending_exception (&error);
7974 ICALL_EXPORT MonoString*
7975 ves_icall_Mono_Runtime_GetDisplayName (void)
7978 MonoString *display_name;
7980 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7981 display_name = mono_string_new (mono_domain_get (), info);
7983 return display_name;
7986 ICALL_EXPORT MonoString*
7987 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7990 MonoString *message;
7994 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7995 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7998 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8000 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8001 mono_error_raise_exception (&error);
8008 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
8011 char *path_str = mono_string_to_utf8 (path);
8013 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
8021 ICALL_EXPORT gpointer
8022 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8024 return GetCurrentProcess ();
8027 ICALL_EXPORT MonoBoolean
8028 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8030 return GetExitCodeProcess (handle, (guint32*) exitcode);
8033 ICALL_EXPORT MonoBoolean
8034 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8036 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8037 return CloseHandle (handle);
8039 return CloseProcess (handle);
8043 ICALL_EXPORT MonoBoolean
8044 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8046 return TerminateProcess (handle, exitcode);
8050 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8052 return WaitForInputIdle (handle, milliseconds);
8055 ICALL_EXPORT MonoBoolean
8056 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8058 return GetProcessWorkingSetSize (handle, min, max);
8061 ICALL_EXPORT MonoBoolean
8062 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8064 return SetProcessWorkingSetSize (handle, min, max);
8067 ICALL_EXPORT MonoBoolean
8068 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8070 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8074 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8076 return mono_process_current_pid ();
8080 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8082 return GetPriorityClass (handle);
8085 ICALL_EXPORT MonoBoolean
8086 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8088 return SetPriorityClass (handle, priorityClass);
8091 #ifndef DISABLE_ICALL_TABLES
8093 #define ICALL_TYPE(id,name,first)
8094 #define ICALL(id,name,func) Icall_ ## id,
8097 #include "metadata/icall-def.h"
8103 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8104 #define ICALL(id,name,func)
8106 #include "metadata/icall-def.h"
8112 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8113 #define ICALL(id,name,func)
8115 guint16 first_icall;
8118 static const IcallTypeDesc
8119 icall_type_descs [] = {
8120 #include "metadata/icall-def.h"
8124 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8127 #define ICALL_TYPE(id,name,first)
8130 #ifdef HAVE_ARRAY_ELEM_INIT
8131 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8132 #define MSGSTRFIELD1(line) str##line
8134 static const struct msgstrtn_t {
8135 #define ICALL(id,name,func)
8137 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8138 #include "metadata/icall-def.h"
8140 } icall_type_names_str = {
8141 #define ICALL_TYPE(id,name,first) (name),
8142 #include "metadata/icall-def.h"
8145 static const guint16 icall_type_names_idx [] = {
8146 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8147 #include "metadata/icall-def.h"
8150 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8152 static const struct msgstr_t {
8154 #define ICALL_TYPE(id,name,first)
8155 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8156 #include "metadata/icall-def.h"
8158 } icall_names_str = {
8159 #define ICALL(id,name,func) (name),
8160 #include "metadata/icall-def.h"
8163 static const guint16 icall_names_idx [] = {
8164 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8165 #include "metadata/icall-def.h"
8168 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8174 #define ICALL_TYPE(id,name,first) name,
8175 #define ICALL(id,name,func)
8176 static const char* const
8177 icall_type_names [] = {
8178 #include "metadata/icall-def.h"
8182 #define icall_type_name_get(id) (icall_type_names [(id)])
8186 #define ICALL_TYPE(id,name,first)
8187 #define ICALL(id,name,func) name,
8188 static const char* const
8190 #include "metadata/icall-def.h"
8193 #define icall_name_get(id) icall_names [(id)]
8195 #endif /* !HAVE_ARRAY_ELEM_INIT */
8199 #define ICALL_TYPE(id,name,first)
8200 #define ICALL(id,name,func) func,
8201 static const gconstpointer
8202 icall_functions [] = {
8203 #include "metadata/icall-def.h"
8207 #ifdef ENABLE_ICALL_SYMBOL_MAP
8210 #define ICALL_TYPE(id,name,first)
8211 #define ICALL(id,name,func) #func,
8212 static const gconstpointer
8213 icall_symbols [] = {
8214 #include "metadata/icall-def.h"
8219 #endif /* DISABLE_ICALL_TABLES */
8221 static mono_mutex_t icall_mutex;
8222 static GHashTable *icall_hash = NULL;
8223 static GHashTable *jit_icall_hash_name = NULL;
8224 static GHashTable *jit_icall_hash_addr = NULL;
8227 mono_icall_init (void)
8229 #ifndef DISABLE_ICALL_TABLES
8232 /* check that tables are sorted: disable in release */
8235 const char *prev_class = NULL;
8236 const char *prev_method;
8238 for (i = 0; i < Icall_type_num; ++i) {
8239 const IcallTypeDesc *desc;
8242 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8243 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8244 prev_class = icall_type_name_get (i);
8245 desc = &icall_type_descs [i];
8246 num_icalls = icall_desc_num_icalls (desc);
8247 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8248 for (j = 0; j < num_icalls; ++j) {
8249 const char *methodn = icall_name_get (desc->first_icall + j);
8250 if (prev_method && strcmp (prev_method, methodn) >= 0)
8251 g_print ("method %s should come before method %s\n", methodn, prev_method);
8252 prev_method = methodn;
8258 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8259 mono_os_mutex_init (&icall_mutex);
8263 mono_icall_lock (void)
8265 mono_locks_os_acquire (&icall_mutex, IcallLock);
8269 mono_icall_unlock (void)
8271 mono_locks_os_release (&icall_mutex, IcallLock);
8275 mono_icall_cleanup (void)
8277 g_hash_table_destroy (icall_hash);
8278 g_hash_table_destroy (jit_icall_hash_name);
8279 g_hash_table_destroy (jit_icall_hash_addr);
8280 mono_os_mutex_destroy (&icall_mutex);
8284 * mono_add_internal_call:
8285 * @name: method specification to surface to the managed world
8286 * @method: pointer to a C method to invoke when the method is called
8288 * This method surfaces the C function pointed by @method as a method
8289 * that has been surfaced in managed code with the method specified in
8290 * @name as an internal call.
8292 * Internal calls are surfaced to all app domains loaded and they are
8293 * accessibly by a type with the specified name.
8295 * You must provide a fully qualified type name, that is namespaces
8296 * and type name, followed by a colon and the method name, with an
8297 * optional signature to bind.
8299 * For example, the following are all valid declarations:
8301 * "MyApp.Services.ScriptService:Accelerate"
8302 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8304 * You use method parameters in cases where there might be more than
8305 * one surface method to managed code. That way you can register different
8306 * internal calls for different method overloads.
8308 * The internal calls are invoked with no marshalling. This means that .NET
8309 * types like System.String are exposed as `MonoString *` parameters. This is
8310 * different than the way that strings are surfaced in P/Invoke.
8312 * For more information on how the parameters are marshalled, see the
8313 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8316 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8317 * reference for more information on the format of method descriptions.
8320 mono_add_internal_call (const char *name, gconstpointer method)
8324 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8326 mono_icall_unlock ();
8329 #ifndef DISABLE_ICALL_TABLES
8331 #ifdef HAVE_ARRAY_ELEM_INIT
8333 compare_method_imap (const void *key, const void *elem)
8335 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8336 return strcmp (key, method_name);
8340 find_method_icall (const IcallTypeDesc *imap, const char *name)
8342 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);
8345 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8349 compare_class_imap (const void *key, const void *elem)
8351 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8352 return strcmp (key, class_name);
8355 static const IcallTypeDesc*
8356 find_class_icalls (const char *name)
8358 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);
8361 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8364 #else /* HAVE_ARRAY_ELEM_INIT */
8367 compare_method_imap (const void *key, const void *elem)
8369 const char** method_name = (const char**)elem;
8370 return strcmp (key, *method_name);
8374 find_method_icall (const IcallTypeDesc *imap, const char *name)
8376 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8379 return (gpointer)icall_functions [(nameslot - icall_names)];
8383 compare_class_imap (const void *key, const void *elem)
8385 const char** class_name = (const char**)elem;
8386 return strcmp (key, *class_name);
8389 static const IcallTypeDesc*
8390 find_class_icalls (const char *name)
8392 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8395 return &icall_type_descs [nameslot - icall_type_names];
8398 #endif /* HAVE_ARRAY_ELEM_INIT */
8400 #endif /* DISABLE_ICALL_TABLES */
8403 * we should probably export this as an helper (handle nested types).
8404 * Returns the number of chars written in buf.
8407 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8409 int nspacelen, cnamelen;
8410 nspacelen = strlen (klass->name_space);
8411 cnamelen = strlen (klass->name);
8412 if (nspacelen + cnamelen + 2 > bufsize)
8415 memcpy (buf, klass->name_space, nspacelen);
8416 buf [nspacelen ++] = '.';
8418 memcpy (buf + nspacelen, klass->name, cnamelen);
8419 buf [nspacelen + cnamelen] = 0;
8420 return nspacelen + cnamelen;
8423 #ifdef DISABLE_ICALL_TABLES
8425 no_icall_table (void)
8427 g_assert_not_reached ();
8432 mono_lookup_internal_call (MonoMethod *method)
8437 int typelen = 0, mlen, siglen;
8439 #ifndef DISABLE_ICALL_TABLES
8440 const IcallTypeDesc *imap = NULL;
8443 g_assert (method != NULL);
8445 if (method->is_inflated)
8446 method = ((MonoMethodInflated *) method)->declaring;
8448 if (method->klass->nested_in) {
8449 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8453 mname [pos++] = '/';
8456 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8462 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8467 #ifndef DISABLE_ICALL_TABLES
8468 imap = find_class_icalls (mname);
8471 mname [typelen] = ':';
8472 mname [typelen + 1] = ':';
8474 mlen = strlen (method->name);
8475 memcpy (mname + typelen + 2, method->name, mlen);
8476 sigstart = mname + typelen + 2 + mlen;
8479 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8480 siglen = strlen (tmpsig);
8481 if (typelen + mlen + siglen + 6 > sizeof (mname))
8484 memcpy (sigstart + 1, tmpsig, siglen);
8485 sigstart [siglen + 1] = ')';
8486 sigstart [siglen + 2] = 0;
8491 res = g_hash_table_lookup (icall_hash, mname);
8493 mono_icall_unlock ();;
8496 /* try without signature */
8498 res = g_hash_table_lookup (icall_hash, mname);
8500 mono_icall_unlock ();
8504 #ifdef DISABLE_ICALL_TABLES
8505 mono_icall_unlock ();
8506 /* Fail only when the result is actually used */
8507 /* mono_marshal_get_native_wrapper () depends on this */
8508 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8509 return ves_icall_System_String_ctor_RedirectToCreateString;
8511 return no_icall_table;
8513 /* it wasn't found in the static call tables */
8515 mono_icall_unlock ();
8518 res = find_method_icall (imap, sigstart - mlen);
8520 mono_icall_unlock ();
8523 /* try _with_ signature */
8525 res = find_method_icall (imap, sigstart - mlen);
8527 mono_icall_unlock ();
8531 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8532 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8533 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8534 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8535 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");
8536 g_print ("If you see other errors or faults after this message they are probably related\n");
8537 g_print ("and you need to fix your mono install first.\n");
8539 mono_icall_unlock ();
8545 #ifdef ENABLE_ICALL_SYMBOL_MAP
8547 func_cmp (gconstpointer key, gconstpointer p)
8549 return (gsize)key - (gsize)*(gsize*)p;
8554 * mono_lookup_icall_symbol:
8556 * Given the icall METHOD, returns its C symbol.
8559 mono_lookup_icall_symbol (MonoMethod *m)
8561 #ifdef DISABLE_ICALL_TABLES
8562 g_assert_not_reached ();
8565 #ifdef ENABLE_ICALL_SYMBOL_MAP
8569 static gconstpointer *functions_sorted;
8570 static const char**symbols_sorted;
8571 static gboolean inited;
8576 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8577 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8578 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8579 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8580 /* Bubble sort the two arrays */
8584 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8585 if (functions_sorted [i] > functions_sorted [i + 1]) {
8588 tmp = functions_sorted [i];
8589 functions_sorted [i] = functions_sorted [i + 1];
8590 functions_sorted [i + 1] = tmp;
8591 tmp = symbols_sorted [i];
8592 symbols_sorted [i] = symbols_sorted [i + 1];
8593 symbols_sorted [i + 1] = tmp;
8600 func = mono_lookup_internal_call (m);
8603 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8607 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8609 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8610 g_assert_not_reached ();
8617 type_from_typename (char *type_name)
8619 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8621 if (!strcmp (type_name, "int"))
8622 klass = mono_defaults.int_class;
8623 else if (!strcmp (type_name, "ptr"))
8624 klass = mono_defaults.int_class;
8625 else if (!strcmp (type_name, "void"))
8626 klass = mono_defaults.void_class;
8627 else if (!strcmp (type_name, "int32"))
8628 klass = mono_defaults.int32_class;
8629 else if (!strcmp (type_name, "uint32"))
8630 klass = mono_defaults.uint32_class;
8631 else if (!strcmp (type_name, "int8"))
8632 klass = mono_defaults.sbyte_class;
8633 else if (!strcmp (type_name, "uint8"))
8634 klass = mono_defaults.byte_class;
8635 else if (!strcmp (type_name, "int16"))
8636 klass = mono_defaults.int16_class;
8637 else if (!strcmp (type_name, "uint16"))
8638 klass = mono_defaults.uint16_class;
8639 else if (!strcmp (type_name, "long"))
8640 klass = mono_defaults.int64_class;
8641 else if (!strcmp (type_name, "ulong"))
8642 klass = mono_defaults.uint64_class;
8643 else if (!strcmp (type_name, "float"))
8644 klass = mono_defaults.single_class;
8645 else if (!strcmp (type_name, "double"))
8646 klass = mono_defaults.double_class;
8647 else if (!strcmp (type_name, "object"))
8648 klass = mono_defaults.object_class;
8649 else if (!strcmp (type_name, "obj"))
8650 klass = mono_defaults.object_class;
8651 else if (!strcmp (type_name, "string"))
8652 klass = mono_defaults.string_class;
8653 else if (!strcmp (type_name, "bool"))
8654 klass = mono_defaults.boolean_class;
8655 else if (!strcmp (type_name, "boolean"))
8656 klass = mono_defaults.boolean_class;
8658 g_error ("%s", type_name);
8659 g_assert_not_reached ();
8661 return &klass->byval_arg;
8665 * LOCKING: Take the corlib image lock.
8667 MonoMethodSignature*
8668 mono_create_icall_signature (const char *sigstr)
8673 MonoMethodSignature *res, *res2;
8674 MonoImage *corlib = mono_defaults.corlib;
8676 mono_image_lock (corlib);
8677 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8678 mono_image_unlock (corlib);
8683 parts = g_strsplit (sigstr, " ", 256);
8692 res = mono_metadata_signature_alloc (corlib, len - 1);
8697 * Under windows, the default pinvoke calling convention is STDCALL but
8700 res->call_convention = MONO_CALL_C;
8703 res->ret = type_from_typename (parts [0]);
8704 for (i = 1; i < len; ++i) {
8705 res->params [i - 1] = type_from_typename (parts [i]);
8710 mono_image_lock (corlib);
8711 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8713 res = res2; /*Value is allocated in the image pool*/
8715 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8716 mono_image_unlock (corlib);
8722 mono_find_jit_icall_by_name (const char *name)
8724 MonoJitICallInfo *info;
8725 g_assert (jit_icall_hash_name);
8728 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8729 mono_icall_unlock ();
8734 mono_find_jit_icall_by_addr (gconstpointer addr)
8736 MonoJitICallInfo *info;
8737 g_assert (jit_icall_hash_addr);
8740 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8741 mono_icall_unlock ();
8747 * mono_get_jit_icall_info:
8749 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8750 * caller should access it while holding the icall lock.
8753 mono_get_jit_icall_info (void)
8755 return jit_icall_hash_name;
8759 * mono_lookup_jit_icall_symbol:
8761 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8764 mono_lookup_jit_icall_symbol (const char *name)
8766 MonoJitICallInfo *info;
8767 const char *res = NULL;
8770 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8772 res = info->c_symbol;
8773 mono_icall_unlock ();
8778 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8781 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8782 mono_icall_unlock ();
8786 * 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
8787 * icalls without wrappers in some cases.
8790 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8792 MonoJitICallInfo *info;
8799 if (!jit_icall_hash_name) {
8800 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8801 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8804 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8805 g_warning ("jit icall already defined \"%s\"\n", name);
8806 g_assert_not_reached ();
8809 info = g_new0 (MonoJitICallInfo, 1);
8814 info->c_symbol = c_symbol;
8815 info->no_raise = no_raise;
8818 info->wrapper = func;
8820 info->wrapper = NULL;
8823 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8824 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8826 mono_icall_unlock ();
8831 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8833 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);