5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
9 * Aleksey Kliger (aleksey@xamarin.com)
11 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
12 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
14 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
25 #ifdef HAVE_SYS_TIME_H
31 #if defined (HOST_WIN32)
34 #if defined (HAVE_WCHAR_H)
38 #include "mono/utils/mono-membar.h"
39 #include <mono/metadata/object.h>
40 #include <mono/metadata/threads.h>
41 #include <mono/metadata/threads-types.h>
42 #include <mono/metadata/threadpool-ms.h>
43 #include <mono/metadata/threadpool-ms-io.h>
44 #include <mono/metadata/monitor.h>
45 #include <mono/metadata/reflection.h>
46 #include <mono/metadata/assembly.h>
47 #include <mono/metadata/tabledefs.h>
48 #include <mono/metadata/exception.h>
49 #include <mono/metadata/exception-internals.h>
50 #include <mono/metadata/file-io.h>
51 #include <mono/metadata/console-io.h>
52 #include <mono/metadata/mono-route.h>
53 #include <mono/metadata/socket-io.h>
54 #include <mono/metadata/mono-endian.h>
55 #include <mono/metadata/tokentype.h>
56 #include <mono/metadata/domain-internals.h>
57 #include <mono/metadata/metadata-internals.h>
58 #include <mono/metadata/class-internals.h>
59 #include <mono/metadata/reflection-internals.h>
60 #include <mono/metadata/marshal.h>
61 #include <mono/metadata/gc-internals.h>
62 #include <mono/metadata/mono-gc.h>
63 #include <mono/metadata/rand.h>
64 #include <mono/metadata/sysmath.h>
65 #include <mono/metadata/string-icalls.h>
66 #include <mono/metadata/debug-helpers.h>
67 #include <mono/metadata/process.h>
68 #include <mono/metadata/environment.h>
69 #include <mono/metadata/profiler-private.h>
70 #include <mono/metadata/locales.h>
71 #include <mono/metadata/filewatcher.h>
72 #include <mono/metadata/security.h>
73 #include <mono/metadata/mono-config.h>
74 #include <mono/metadata/cil-coff.h>
75 #include <mono/metadata/number-formatter.h>
76 #include <mono/metadata/security-manager.h>
77 #include <mono/metadata/security-core-clr.h>
78 #include <mono/metadata/mono-perfcounters.h>
79 #include <mono/metadata/mono-debug.h>
80 #include <mono/metadata/mono-ptr-array.h>
81 #include <mono/metadata/verify-internals.h>
82 #include <mono/metadata/runtime.h>
83 #include <mono/metadata/file-mmap.h>
84 #include <mono/metadata/seq-points-data.h>
85 #include <mono/io-layer/io-layer.h>
86 #include <mono/utils/monobitset.h>
87 #include <mono/utils/mono-time.h>
88 #include <mono/utils/mono-proclib.h>
89 #include <mono/utils/mono-string.h>
90 #include <mono/utils/mono-error-internals.h>
91 #include <mono/utils/mono-mmap.h>
92 #include <mono/utils/mono-io-portability.h>
93 #include <mono/utils/mono-digest.h>
94 #include <mono/utils/bsearch.h>
95 #include <mono/utils/mono-os-mutex.h>
96 #include <mono/utils/mono-threads.h>
98 #if defined (HOST_WIN32)
102 #include "decimal-ms.h"
103 #include "number-ms.h"
105 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
106 #include <sys/utsname.h>
109 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
111 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
113 /* Lazy class loading functions */
114 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
115 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
116 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
119 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
122 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
124 static inline MonoBoolean
125 is_generic_parameter (MonoType *type)
127 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
131 mono_class_init_checked (MonoClass *klass, MonoError *error)
133 mono_error_init (error);
135 if (!mono_class_init (klass))
136 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
139 ICALL_EXPORT MonoObject *
140 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
146 MonoObject *result = NULL;
148 ac = (MonoClass *)arr->obj.vtable->klass;
150 esize = mono_array_element_size (ac);
151 ea = (gpointer*)((char*)arr->vector + (pos * esize));
153 if (ac->element_class->valuetype) {
154 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
155 mono_error_set_pending_exception (&error);
157 result = (MonoObject *)*ea;
161 ICALL_EXPORT MonoObject *
162 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
168 MONO_CHECK_ARG_NULL (idxs, NULL);
171 ic = (MonoClass *)io->obj.vtable->klass;
173 ac = (MonoClass *)arr->obj.vtable->klass;
175 g_assert (ic->rank == 1);
176 if (io->bounds != NULL || io->max_length != ac->rank) {
177 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
181 ind = (gint32 *)io->vector;
183 if (arr->bounds == NULL) {
184 if (*ind < 0 || *ind >= arr->max_length) {
185 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
189 return ves_icall_System_Array_GetValueImpl (arr, *ind);
192 for (i = 0; i < ac->rank; i++) {
193 if ((ind [i] < arr->bounds [i].lower_bound) ||
194 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
195 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
200 pos = ind [0] - arr->bounds [0].lower_bound;
201 for (i = 1; i < ac->rank; i++)
202 pos = pos * arr->bounds [i].length + ind [i] -
203 arr->bounds [i].lower_bound;
205 return ves_icall_System_Array_GetValueImpl (arr, pos);
209 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
212 MonoClass *ac, *vc, *ec;
221 mono_error_init (&error);
224 vc = value->vtable->klass;
228 ac = arr->obj.vtable->klass;
229 ec = ac->element_class;
231 esize = mono_array_element_size (ac);
232 ea = (gpointer*)((char*)arr->vector + (pos * esize));
233 va = (gpointer*)((char*)value + sizeof (MonoObject));
235 if (mono_class_is_nullable (ec)) {
236 mono_nullable_init ((guint8*)ea, value, ec);
241 mono_gc_bzero_atomic (ea, esize);
245 #define NO_WIDENING_CONVERSION G_STMT_START{\
246 mono_set_pending_exception (mono_get_exception_argument ( \
247 "value", "not a widening conversion")); \
251 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
252 if (esize < vsize + (extra)) { \
253 mono_set_pending_exception (mono_get_exception_argument ( \
254 "value", "not a widening conversion")); \
259 #define INVALID_CAST G_STMT_START{ \
260 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
261 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
265 /* Check element (destination) type. */
266 switch (ec->byval_arg.type) {
267 case MONO_TYPE_STRING:
268 switch (vc->byval_arg.type) {
269 case MONO_TYPE_STRING:
275 case MONO_TYPE_BOOLEAN:
276 switch (vc->byval_arg.type) {
277 case MONO_TYPE_BOOLEAN:
290 NO_WIDENING_CONVERSION;
299 if (!ec->valuetype) {
300 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
301 if (mono_error_set_pending_exception (&error))
305 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
309 if (mono_object_isinst_checked (value, ec, &error)) {
310 if (ec->has_references)
311 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
313 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
316 if (mono_error_set_pending_exception (&error))
322 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
324 et = ec->byval_arg.type;
325 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
326 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
328 vt = vc->byval_arg.type;
329 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
330 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
332 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
338 case MONO_TYPE_CHAR: \
339 CHECK_WIDENING_CONVERSION(0); \
340 *(etype *) ea = (etype) u64; \
342 /* You can't assign a signed value to an unsigned array. */ \
347 /* You can't assign a floating point number to an integer array. */ \
350 NO_WIDENING_CONVERSION; \
354 #define ASSIGN_SIGNED(etype) G_STMT_START{\
360 CHECK_WIDENING_CONVERSION(0); \
361 *(etype *) ea = (etype) i64; \
363 /* You can assign an unsigned value to a signed array if the array's */ \
364 /* element size is larger than the value size. */ \
369 case MONO_TYPE_CHAR: \
370 CHECK_WIDENING_CONVERSION(1); \
371 *(etype *) ea = (etype) u64; \
373 /* You can't assign a floating point number to an integer array. */ \
376 NO_WIDENING_CONVERSION; \
380 #define ASSIGN_REAL(etype) G_STMT_START{\
384 CHECK_WIDENING_CONVERSION(0); \
385 *(etype *) ea = (etype) r64; \
387 /* All integer values fit into a floating point array, so we don't */ \
388 /* need to CHECK_WIDENING_CONVERSION here. */ \
393 *(etype *) ea = (etype) i64; \
399 case MONO_TYPE_CHAR: \
400 *(etype *) ea = (etype) u64; \
407 u64 = *(guint8 *) va;
410 u64 = *(guint16 *) va;
413 u64 = *(guint32 *) va;
416 u64 = *(guint64 *) va;
422 i64 = *(gint16 *) va;
425 i64 = *(gint32 *) va;
428 i64 = *(gint64 *) va;
431 r64 = *(gfloat *) va;
434 r64 = *(gdouble *) va;
437 u64 = *(guint16 *) va;
439 case MONO_TYPE_BOOLEAN:
440 /* Boolean is only compatible with itself. */
453 NO_WIDENING_CONVERSION;
460 /* If we can't do a direct copy, let's try a widening conversion. */
463 ASSIGN_UNSIGNED (guint16);
465 ASSIGN_UNSIGNED (guint8);
467 ASSIGN_UNSIGNED (guint16);
469 ASSIGN_UNSIGNED (guint32);
471 ASSIGN_UNSIGNED (guint64);
473 ASSIGN_SIGNED (gint8);
475 ASSIGN_SIGNED (gint16);
477 ASSIGN_SIGNED (gint32);
479 ASSIGN_SIGNED (gint64);
481 ASSIGN_REAL (gfloat);
483 ASSIGN_REAL (gdouble);
487 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
491 #undef NO_WIDENING_CONVERSION
492 #undef CHECK_WIDENING_CONVERSION
493 #undef ASSIGN_UNSIGNED
499 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
505 MONO_CHECK_ARG_NULL (idxs,);
507 ic = idxs->obj.vtable->klass;
508 ac = arr->obj.vtable->klass;
510 g_assert (ic->rank == 1);
511 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
512 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
516 ind = (gint32 *)idxs->vector;
518 if (arr->bounds == NULL) {
519 if (*ind < 0 || *ind >= arr->max_length) {
520 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
524 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
528 for (i = 0; i < ac->rank; i++)
529 if ((ind [i] < arr->bounds [i].lower_bound) ||
530 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
531 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
535 pos = ind [0] - arr->bounds [0].lower_bound;
536 for (i = 1; i < ac->rank; i++)
537 pos = pos * arr->bounds [i].length + ind [i] -
538 arr->bounds [i].lower_bound;
540 ves_icall_System_Array_SetValueImpl (arr, value, pos);
543 ICALL_EXPORT MonoArray *
544 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
547 MonoClass *aklass, *klass;
550 gboolean bounded = FALSE;
552 MONO_CHECK_ARG_NULL (type, NULL);
553 MONO_CHECK_ARG_NULL (lengths, NULL);
555 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
557 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
559 for (i = 0; i < mono_array_length (lengths); i++) {
560 if (mono_array_get (lengths, gint32, i) < 0) {
561 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
566 klass = mono_class_from_mono_type (type->type);
567 mono_class_init_checked (klass, &error);
568 if (mono_error_set_pending_exception (&error))
571 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
572 /* vectors are not the same as one dimensional arrays with no-zero bounds */
577 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
579 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
580 for (i = 0; i < aklass->rank; ++i) {
581 sizes [i] = mono_array_get (lengths, guint32, i);
583 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
585 sizes [i + aklass->rank] = 0;
588 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
589 mono_error_set_pending_exception (&error);
594 ICALL_EXPORT MonoArray *
595 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
598 MonoClass *aklass, *klass;
601 gboolean bounded = FALSE;
603 MONO_CHECK_ARG_NULL (type, NULL);
604 MONO_CHECK_ARG_NULL (lengths, NULL);
606 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
608 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
610 for (i = 0; i < mono_array_length (lengths); i++) {
611 if ((mono_array_get (lengths, gint64, i) < 0) ||
612 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
613 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
618 klass = mono_class_from_mono_type (type->type);
619 mono_class_init_checked (klass, &error);
620 if (mono_error_set_pending_exception (&error))
623 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
624 /* vectors are not the same as one dimensional arrays with no-zero bounds */
629 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
631 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
632 for (i = 0; i < aklass->rank; ++i) {
633 sizes [i] = mono_array_get (lengths, guint64, i);
635 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
637 sizes [i + aklass->rank] = 0;
640 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
641 mono_error_set_pending_exception (&error);
647 ves_icall_System_Array_GetRank (MonoObject *arr)
649 return arr->vtable->klass->rank;
653 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
655 gint32 rank = arr->obj.vtable->klass->rank;
658 if ((dimension < 0) || (dimension >= rank)) {
659 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
663 if (arr->bounds == NULL)
664 length = arr->max_length;
666 length = arr->bounds [dimension].length;
668 #ifdef MONO_BIG_ARRAYS
669 if (length > G_MAXINT32) {
670 mono_set_pending_exception (mono_get_exception_overflow ());
678 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
680 gint32 rank = arr->obj.vtable->klass->rank;
682 if ((dimension < 0) || (dimension >= rank)) {
683 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
687 if (arr->bounds == NULL)
688 return arr->max_length;
690 return arr->bounds [dimension].length;
694 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
696 gint32 rank = arr->obj.vtable->klass->rank;
698 if ((dimension < 0) || (dimension >= rank)) {
699 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
703 if (arr->bounds == NULL)
706 return arr->bounds [dimension].lower_bound;
710 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
712 int sz = mono_array_element_size (mono_object_class (arr));
713 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
716 ICALL_EXPORT gboolean
717 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
722 MonoVTable *src_vtable;
723 MonoVTable *dest_vtable;
724 MonoClass *src_class;
725 MonoClass *dest_class;
727 src_vtable = source->obj.vtable;
728 dest_vtable = dest->obj.vtable;
730 if (src_vtable->rank != dest_vtable->rank)
733 if (source->bounds || dest->bounds)
736 /* there's no integer overflow since mono_array_length returns an unsigned integer */
737 if ((dest_idx + length > mono_array_length_fast (dest)) ||
738 (source_idx + length > mono_array_length_fast (source)))
741 src_class = src_vtable->klass->element_class;
742 dest_class = dest_vtable->klass->element_class;
745 * Handle common cases.
748 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
749 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
751 if (src_class == mono_defaults.object_class && dest_class->valuetype)
754 /* Check if we're copying a char[] <==> (u)short[] */
755 if (src_class != dest_class) {
756 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
759 /* 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. */
760 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
764 if (dest_class->valuetype) {
765 element_size = mono_array_element_size (source->obj.vtable->klass);
766 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
767 if (dest_class->has_references) {
768 mono_value_copy_array (dest, dest_idx, source_addr, length);
770 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
771 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
774 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
781 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
787 ac = (MonoClass *)arr->obj.vtable->klass;
789 esize = mono_array_element_size (ac);
790 ea = (gpointer*)((char*)arr->vector + (pos * esize));
792 mono_gc_memmove_atomic (value, ea, esize);
796 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
802 ac = (MonoClass *)arr->obj.vtable->klass;
803 ec = ac->element_class;
805 esize = mono_array_element_size (ac);
806 ea = (gpointer*)((char*)arr->vector + (pos * esize));
808 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
809 g_assert (esize == sizeof (gpointer));
810 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
812 g_assert (ec->inited);
813 g_assert (esize == mono_class_value_size (ec, NULL));
814 if (ec->has_references)
815 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
817 mono_gc_memmove_atomic (ea, value, esize);
822 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
824 MonoClass *klass = array->obj.vtable->klass;
825 guint32 size = mono_array_element_size (klass);
826 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
828 const char *field_data;
830 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
831 MonoException *exc = mono_get_exception_argument("array",
832 "Cannot initialize array of non-primitive type.");
833 mono_set_pending_exception (exc);
837 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
838 MonoException *exc = mono_get_exception_argument("field_handle",
839 "Field doesn't have an RVA");
840 mono_set_pending_exception (exc);
844 size *= array->max_length;
845 field_data = mono_field_get_data (field_handle);
847 if (size > mono_type_size (field_handle->type, &align)) {
848 MonoException *exc = mono_get_exception_argument("field_handle",
849 "Field not large enough to fill array");
850 mono_set_pending_exception (exc);
854 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
856 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
857 guint ## n *src = (guint ## n *) field_data; \
859 nEnt = (size / sizeof(guint ## n)); \
861 for (i = 0; i < nEnt; i++) { \
862 data[i] = read ## n (&src[i]); \
866 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
868 switch (type->type) {
885 memcpy (mono_array_addr (array, char, 0), field_data, size);
889 memcpy (mono_array_addr (array, char, 0), field_data, size);
894 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
896 return offsetof (MonoString, chars);
899 ICALL_EXPORT MonoObject *
900 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
902 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
906 MonoObject *ret = mono_object_clone_checked (obj, &error);
907 mono_error_set_pending_exception (&error);
914 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
920 MONO_CHECK_ARG_NULL (handle,);
922 klass = mono_class_from_mono_type (handle);
923 MONO_CHECK_ARG (handle, klass,);
925 if (klass->generic_container)
928 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
929 if (!is_ok (&error)) {
930 mono_error_set_pending_exception (&error);
934 /* This will call the type constructor */
935 if (!mono_runtime_class_init_full (vtable, &error))
936 mono_error_set_pending_exception (&error);
940 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
944 mono_image_check_for_module_cctor (image);
945 if (image->has_module_cctor) {
946 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
947 if (!mono_error_ok (&error)) {
948 mono_error_set_pending_exception (&error);
951 /*It's fine to raise the exception here*/
952 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
953 if (!is_ok (&error)) {
954 mono_error_set_pending_exception (&error);
957 if (!mono_runtime_class_init_full (vtable, &error))
958 mono_error_set_pending_exception (&error);
962 ICALL_EXPORT MonoBoolean
963 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
968 /* later make this configurable and per-arch */
969 int min_size = 4096 * 4 * sizeof (void*);
970 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
971 /* if we have no info we are optimistic and assume there is enough room */
975 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
979 current = (guint8 *)&stack_addr;
980 if (current > stack_addr) {
981 if ((current - stack_addr) < min_size)
984 if (current - (stack_addr - stack_size) < min_size)
990 ICALL_EXPORT MonoObject *
991 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
994 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
995 mono_error_set_pending_exception (&error);
1001 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1005 MonoObject **values = NULL;
1008 gint32 result = (int)(gsize)mono_defaults.int32_class;
1009 MonoClassField* field;
1012 klass = mono_object_class (this_obj);
1014 if (mono_class_num_fields (klass) == 0)
1018 * Compute the starting value of the hashcode for fields of primitive
1019 * types, and return the remaining fields in an array to the managed side.
1020 * This way, we can avoid costly reflection operations in managed code.
1023 while ((field = mono_class_get_fields (klass, &iter))) {
1024 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1026 if (mono_field_is_deleted (field))
1028 /* FIXME: Add more types */
1029 switch (field->type->type) {
1031 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1033 case MONO_TYPE_STRING: {
1035 s = *(MonoString**)((guint8*)this_obj + field->offset);
1037 result ^= mono_string_hash (s);
1042 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1043 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1044 if (!is_ok (&error)) {
1045 mono_error_set_pending_exception (&error);
1048 values [count++] = o;
1054 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1055 for (i = 0; i < count; ++i)
1056 mono_array_setref (*fields, i, values [i]);
1063 ICALL_EXPORT MonoBoolean
1064 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1068 MonoObject **values = NULL;
1070 MonoClassField* field;
1074 MONO_CHECK_ARG_NULL (that, FALSE);
1076 if (this_obj->vtable != that->vtable)
1079 klass = mono_object_class (this_obj);
1081 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1082 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1085 * Do the comparison for fields of primitive type and return a result if
1086 * possible. Otherwise, return the remaining fields in an array to the
1087 * managed side. This way, we can avoid costly reflection operations in
1092 while ((field = mono_class_get_fields (klass, &iter))) {
1093 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1095 if (mono_field_is_deleted (field))
1097 /* FIXME: Add more types */
1098 switch (field->type->type) {
1101 case MONO_TYPE_BOOLEAN:
1102 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1107 case MONO_TYPE_CHAR:
1108 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1113 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1118 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1122 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1126 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1131 case MONO_TYPE_STRING: {
1132 MonoString *s1, *s2;
1133 guint32 s1len, s2len;
1134 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1135 s2 = *(MonoString**)((guint8*)that + field->offset);
1138 if ((s1 == NULL) || (s2 == NULL))
1140 s1len = mono_string_length (s1);
1141 s2len = mono_string_length (s2);
1145 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1151 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1152 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1153 if (!is_ok (&error)) {
1154 mono_error_set_pending_exception (&error);
1157 values [count++] = o;
1158 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1159 if (!is_ok (&error)) {
1160 mono_error_set_pending_exception (&error);
1163 values [count++] = o;
1166 if (klass->enumtype)
1167 /* enums only have one non-static field */
1173 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1174 for (i = 0; i < count; ++i)
1175 mono_array_setref_fast (*fields, i, values [i]);
1182 ICALL_EXPORT MonoReflectionType *
1183 ves_icall_System_Object_GetType (MonoObject *obj)
1186 MonoReflectionType *ret;
1187 #ifndef DISABLE_REMOTING
1188 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1189 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1192 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1194 mono_error_set_pending_exception (&error);
1199 ves_icall_MonoType_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1201 mtype->type = &obj->vtable->klass->byval_arg;
1202 g_assert (mtype->type->type);
1206 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1208 MONO_CHECK_ARG_NULL (obj, 0);
1211 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1212 mono_error_set_pending_exception (&error);
1217 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1218 MonoReflectionMethod *method,
1219 MonoArray *opt_param_types)
1221 MONO_CHECK_ARG_NULL (method, 0);
1224 gint32 result = mono_image_create_method_token (
1225 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1226 mono_error_set_pending_exception (&error);
1231 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1234 mono_image_create_pefile (mb, file, &error);
1235 mono_error_set_pending_exception (&error);
1239 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1242 mono_image_build_metadata (mb, &error);
1243 mono_error_set_pending_exception (&error);
1247 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1249 mono_image_register_token (mb->dynamic_image, token, obj);
1252 ICALL_EXPORT MonoObject*
1253 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1257 mono_loader_lock ();
1258 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1259 mono_loader_unlock ();
1264 ICALL_EXPORT MonoReflectionModule*
1265 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1268 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1269 mono_error_set_pending_exception (&error);
1273 ICALL_EXPORT MonoArray*
1274 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
1277 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
1278 mono_error_set_pending_exception (&error);
1283 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1285 MonoMethod **dest = (MonoMethod **)data;
1287 /* skip unmanaged frames */
1303 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1305 MonoMethod **dest = (MonoMethod **)data;
1307 /* skip unmanaged frames */
1312 if (!strcmp (m->klass->name_space, "System.Reflection"))
1321 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1323 MonoMethod **dest = (MonoMethod **)data;
1325 /* skip unmanaged frames */
1329 if (m->wrapper_type != MONO_WRAPPER_NONE)
1332 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1346 static MonoReflectionType *
1347 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1349 MonoMethod *m, *dest;
1351 MonoType *type = NULL;
1352 MonoAssembly *assembly = NULL;
1353 gboolean type_resolve = FALSE;
1355 mono_error_init (error);
1358 * We must compute the calling assembly as type loading must happen under a metadata context.
1359 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1360 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1362 m = mono_method_get_last_managed ();
1365 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1370 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1371 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1372 * to crash. This only seems to happen in some strange remoting
1373 * scenarios and I was unable to figure out what's happening there.
1374 * Dec 10, 2005 - Martin.
1378 assembly = dest->klass->image->assembly;
1379 type_resolve = TRUE;
1381 g_warning (G_STRLOC);
1384 if (info->assembly.name)
1385 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1389 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1390 type = mono_reflection_get_type_checked (assembly->image, info, ignoreCase, &type_resolve, error);
1391 return_val_if_nok (error, NULL);
1394 if (!info->assembly.name && !type) {
1396 type = mono_reflection_get_type_checked (NULL, info, ignoreCase, &type_resolve, error);
1397 return_val_if_nok (error, NULL);
1399 if (assembly && !type && type_resolve) {
1400 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1401 type = mono_reflection_get_type_checked (assembly->image, info, ignoreCase, &type_resolve, error);
1402 return_val_if_nok (error, NULL);
1408 return mono_type_get_object_checked (mono_domain_get (), type, error);
1411 ICALL_EXPORT MonoReflectionType*
1412 ves_icall_System_Type_internal_from_name (MonoString *name,
1413 MonoBoolean throwOnError,
1414 MonoBoolean ignoreCase)
1417 char *str = mono_string_to_utf8 (name);
1418 MonoTypeNameParse info;
1419 MonoReflectionType *type;
1422 parsedOk = mono_reflection_parse_type (str, &info);
1424 /* mono_reflection_parse_type() mangles the string */
1426 mono_reflection_free_type_info (&info);
1429 mono_set_pending_exception (mono_get_exception_argument("typeName", "failed parse"));
1434 type = type_from_parsed_name (&info, ignoreCase, &error);
1436 mono_reflection_free_type_info (&info);
1439 if (!mono_error_ok (&error)) {
1441 mono_error_set_pending_exception (&error);
1443 mono_error_cleanup (&error);
1448 MonoException *e = NULL;
1451 e = mono_get_exception_type_load (name, NULL);
1453 mono_loader_clear_error ();
1455 mono_set_pending_exception (e);
1464 ICALL_EXPORT MonoReflectionType*
1465 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1468 MonoReflectionType *ret;
1469 MonoDomain *domain = mono_domain_get ();
1471 ret = mono_type_get_object_checked (domain, handle, &error);
1472 mono_error_set_pending_exception (&error);
1477 /* System.TypeCode */
1496 TYPECODE_STRING = 18
1499 ICALL_EXPORT guint32
1500 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1502 int t = type->type->type;
1504 if (type->type->byref)
1505 return TYPECODE_OBJECT;
1509 case MONO_TYPE_VOID:
1510 return TYPECODE_OBJECT;
1511 case MONO_TYPE_BOOLEAN:
1512 return TYPECODE_BOOLEAN;
1514 return TYPECODE_BYTE;
1516 return TYPECODE_SBYTE;
1518 return TYPECODE_UINT16;
1520 return TYPECODE_INT16;
1521 case MONO_TYPE_CHAR:
1522 return TYPECODE_CHAR;
1526 return TYPECODE_OBJECT;
1528 return TYPECODE_UINT32;
1530 return TYPECODE_INT32;
1532 return TYPECODE_UINT64;
1534 return TYPECODE_INT64;
1536 return TYPECODE_SINGLE;
1538 return TYPECODE_DOUBLE;
1539 case MONO_TYPE_VALUETYPE: {
1540 MonoClass *klass = type->type->data.klass;
1542 if (klass->enumtype) {
1543 t = mono_class_enum_basetype (klass)->type;
1545 } else if (mono_is_corlib_image (klass->image)) {
1546 if (strcmp (klass->name_space, "System") == 0) {
1547 if (strcmp (klass->name, "Decimal") == 0)
1548 return TYPECODE_DECIMAL;
1549 else if (strcmp (klass->name, "DateTime") == 0)
1550 return TYPECODE_DATETIME;
1553 return TYPECODE_OBJECT;
1555 case MONO_TYPE_STRING:
1556 return TYPECODE_STRING;
1557 case MONO_TYPE_SZARRAY:
1558 case MONO_TYPE_ARRAY:
1559 case MONO_TYPE_OBJECT:
1561 case MONO_TYPE_MVAR:
1562 case MONO_TYPE_TYPEDBYREF:
1563 return TYPECODE_OBJECT;
1564 case MONO_TYPE_CLASS:
1566 MonoClass *klass = type->type->data.klass;
1567 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1568 if (strcmp (klass->name, "DBNull") == 0)
1569 return TYPECODE_DBNULL;
1572 return TYPECODE_OBJECT;
1573 case MONO_TYPE_GENERICINST:
1574 return TYPECODE_OBJECT;
1576 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1582 mono_type_is_primitive (MonoType *type)
1584 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1585 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1589 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1591 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1592 return mono_class_enum_basetype (type->data.klass);
1593 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1594 return mono_class_enum_basetype (type->data.generic_class->container_class);
1598 ICALL_EXPORT guint32
1599 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1604 g_assert (type != NULL);
1606 klass = mono_class_from_mono_type (type->type);
1607 klassc = mono_class_from_mono_type (c->type);
1609 if (type->type->byref ^ c->type->byref)
1612 if (type->type->byref) {
1613 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1614 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1616 klass = mono_class_from_mono_type (t);
1617 klassc = mono_class_from_mono_type (ot);
1619 if (mono_type_is_primitive (t)) {
1620 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1621 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1622 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1623 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1624 return t->type == ot->type;
1626 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1629 if (klass->valuetype)
1630 return klass == klassc;
1631 return klass->valuetype == klassc->valuetype;
1634 return mono_class_is_assignable_from (klass, klassc);
1637 ICALL_EXPORT guint32
1638 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1641 MonoClass *klass = mono_class_from_mono_type (type->type);
1642 mono_class_init_checked (klass, &error);
1643 if (!is_ok (&error)) {
1644 mono_error_set_pending_exception (&error);
1647 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1648 mono_error_set_pending_exception (&error);
1652 ICALL_EXPORT guint32
1653 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1655 MonoClass *klass = mono_class_from_mono_type (type->type);
1656 return klass->flags;
1659 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1660 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1663 MonoClass *klass = field->field->parent;
1664 MonoMarshalType *info;
1668 if (klass->generic_container ||
1669 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1672 ftype = mono_field_get_type (field->field);
1673 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1676 info = mono_marshal_load_type_info (klass);
1678 for (i = 0; i < info->num_fields; ++i) {
1679 if (info->fields [i].field == field->field) {
1680 if (!info->fields [i].mspec)
1683 MonoReflectionMarshalAsAttribute* obj;
1684 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1685 if (!mono_error_ok (&error))
1686 mono_error_set_pending_exception (&error);
1695 ICALL_EXPORT MonoReflectionField*
1696 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1699 gboolean found = FALSE;
1706 klass = handle->parent;
1708 klass = mono_class_from_mono_type (type);
1710 /* Check that the field belongs to the class */
1711 for (k = klass; k; k = k->parent) {
1712 if (k == handle->parent) {
1719 /* The managed code will throw the exception */
1723 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1724 mono_error_set_pending_exception (&error);
1728 ICALL_EXPORT MonoArray*
1729 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1732 MonoType *type = mono_field_get_type_checked (field->field, &error);
1735 if (!mono_error_ok (&error)) {
1736 mono_error_set_pending_exception (&error);
1740 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1741 mono_error_set_pending_exception (&error);
1746 vell_icall_get_method_attributes (MonoMethod *method)
1748 return method->flags;
1752 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1755 MonoReflectionType *rt;
1756 MonoDomain *domain = mono_domain_get ();
1757 MonoMethodSignature* sig;
1759 sig = mono_method_signature_checked (method, &error);
1760 if (!mono_error_ok (&error)) {
1761 mono_error_set_pending_exception (&error);
1765 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1766 if (!mono_error_ok (&error)) {
1767 mono_error_set_pending_exception (&error);
1771 MONO_STRUCT_SETREF (info, parent, rt);
1773 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1774 if (!mono_error_ok (&error)) {
1775 mono_error_set_pending_exception (&error);
1779 MONO_STRUCT_SETREF (info, ret, rt);
1781 info->attrs = method->flags;
1782 info->implattrs = method->iflags;
1783 if (sig->call_convention == MONO_CALL_DEFAULT)
1784 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1786 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1791 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1794 ICALL_EXPORT MonoArray*
1795 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1798 MonoDomain *domain = mono_domain_get ();
1800 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1801 mono_error_set_pending_exception (&error);
1805 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1806 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1809 MonoDomain *domain = mono_domain_get ();
1810 MonoReflectionMarshalAsAttribute* res = NULL;
1811 MonoMarshalSpec **mspecs;
1814 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1815 mono_method_get_marshal_info (method, mspecs);
1818 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1819 if (!mono_error_ok (&error)) {
1820 mono_error_set_pending_exception (&error);
1825 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1827 mono_metadata_free_marshal_spec (mspecs [i]);
1834 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1836 MonoClass *parent = field->field->parent;
1837 if (!parent->size_inited)
1838 mono_class_init (parent);
1839 mono_class_setup_fields_locking (parent);
1841 return field->field->offset - sizeof (MonoObject);
1844 ICALL_EXPORT MonoReflectionType*
1845 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1848 MonoReflectionType *ret;
1851 parent = declaring? field->field->parent: field->klass;
1853 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1854 mono_error_set_pending_exception (&error);
1860 ICALL_EXPORT MonoObject *
1861 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1864 MonoClass *fklass = field->klass;
1865 MonoClassField *cf = field->field;
1866 MonoDomain *domain = mono_object_domain (field);
1868 if (fklass->image->assembly->ref_only) {
1869 mono_set_pending_exception (mono_get_exception_invalid_operation (
1870 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1874 if (mono_security_core_clr_enabled () &&
1875 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1876 mono_error_set_pending_exception (&error);
1880 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1881 mono_error_set_pending_exception (&error);
1886 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1889 MonoClassField *cf = field->field;
1893 if (field->klass->image->assembly->ref_only) {
1894 mono_set_pending_exception (mono_get_exception_invalid_operation (
1895 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1899 if (mono_security_core_clr_enabled () &&
1900 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1901 mono_error_set_pending_exception (&error);
1905 type = mono_field_get_type_checked (cf, &error);
1906 if (!mono_error_ok (&error)) {
1907 mono_error_set_pending_exception (&error);
1911 v = (gchar *) value;
1913 switch (type->type) {
1916 case MONO_TYPE_BOOLEAN:
1919 case MONO_TYPE_CHAR:
1928 case MONO_TYPE_VALUETYPE:
1931 v += sizeof (MonoObject);
1933 case MONO_TYPE_STRING:
1934 case MONO_TYPE_OBJECT:
1935 case MONO_TYPE_CLASS:
1936 case MONO_TYPE_ARRAY:
1937 case MONO_TYPE_SZARRAY:
1940 case MONO_TYPE_GENERICINST: {
1941 MonoGenericClass *gclass = type->data.generic_class;
1942 g_assert (!gclass->context.class_inst->is_open);
1944 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1945 MonoClass *nklass = mono_class_from_mono_type (type);
1946 MonoObject *nullable;
1949 * Convert the boxed vtype into a Nullable structure.
1950 * This is complicated by the fact that Nullables have
1951 * a variable structure.
1953 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1954 if (!mono_error_ok (&error)) {
1955 mono_error_set_pending_exception (&error);
1959 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1961 v = (gchar *)mono_object_unbox (nullable);
1964 if (gclass->container_class->valuetype && (v != NULL))
1965 v += sizeof (MonoObject);
1969 g_error ("type 0x%x not handled in "
1970 "ves_icall_FieldInfo_SetValueInternal", type->type);
1975 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1976 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
1977 if (!is_ok (&error)) {
1978 mono_error_set_pending_exception (&error);
1981 if (!vtable->initialized) {
1982 if (!mono_runtime_class_init_full (vtable, &error)) {
1983 mono_error_set_pending_exception (&error);
1987 mono_field_static_set_value (vtable, cf, v);
1989 mono_field_set_value (obj, cf, v);
1994 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2003 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2004 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2008 if (MONO_TYPE_IS_REFERENCE (f->type))
2009 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2011 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2014 ICALL_EXPORT MonoObject *
2015 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2017 MonoObject *o = NULL;
2018 MonoClassField *field = rfield->field;
2020 MonoDomain *domain = mono_object_domain (rfield);
2022 MonoTypeEnum def_type;
2023 const char *def_value;
2027 mono_class_init (field->parent);
2029 t = mono_field_get_type_checked (field, &error);
2030 if (!mono_error_ok (&error)) {
2031 mono_error_set_pending_exception (&error);
2035 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2036 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2040 if (image_is_dynamic (field->parent->image)) {
2041 MonoClass *klass = field->parent;
2042 int fidx = field - klass->fields;
2044 g_assert (fidx >= 0 && fidx < klass->field.count);
2045 g_assert (klass->ext);
2046 g_assert (klass->ext->field_def_values);
2047 def_type = klass->ext->field_def_values [fidx].def_type;
2048 def_value = klass->ext->field_def_values [fidx].data;
2049 if (def_type == MONO_TYPE_END) {
2050 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2054 def_value = mono_class_get_field_default_value (field, &def_type);
2055 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2057 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2062 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2066 case MONO_TYPE_BOOLEAN:
2069 case MONO_TYPE_CHAR:
2077 case MONO_TYPE_R8: {
2080 /* boxed value type */
2081 t = g_new0 (MonoType, 1);
2083 klass = mono_class_from_mono_type (t);
2085 o = mono_object_new_checked (domain, klass, &error);
2086 if (!mono_error_ok (&error)) {
2087 mono_error_set_pending_exception (&error);
2090 v = ((gchar *) o) + sizeof (MonoObject);
2091 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2094 case MONO_TYPE_STRING:
2095 case MONO_TYPE_CLASS:
2096 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2099 g_assert_not_reached ();
2105 ICALL_EXPORT MonoReflectionType*
2106 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2109 MonoReflectionType *ret;
2112 type = mono_field_get_type_checked (ref_field->field, &error);
2113 if (!mono_error_ok (&error)) {
2114 mono_error_set_pending_exception (&error);
2118 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2119 if (!mono_error_ok (&error)) {
2120 mono_error_set_pending_exception (&error);
2127 /* From MonoProperty.cs */
2129 PInfo_Attributes = 1,
2130 PInfo_GetMethod = 1 << 1,
2131 PInfo_SetMethod = 1 << 2,
2132 PInfo_ReflectedType = 1 << 3,
2133 PInfo_DeclaringType = 1 << 4,
2138 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2141 MonoReflectionType *rt;
2142 MonoReflectionMethod *rm;
2143 MonoDomain *domain = mono_object_domain (property);
2144 const MonoProperty *pproperty = property->property;
2146 if ((req_info & PInfo_ReflectedType) != 0) {
2147 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2148 if (mono_error_set_pending_exception (&error))
2151 MONO_STRUCT_SETREF (info, parent, rt);
2153 if ((req_info & PInfo_DeclaringType) != 0) {
2154 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2155 if (mono_error_set_pending_exception (&error))
2158 MONO_STRUCT_SETREF (info, declaring_type, rt);
2161 if ((req_info & PInfo_Name) != 0)
2162 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2164 if ((req_info & PInfo_Attributes) != 0)
2165 info->attrs = pproperty->attrs;
2167 if ((req_info & PInfo_GetMethod) != 0) {
2168 if (pproperty->get &&
2169 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2170 pproperty->get->klass == property->klass)) {
2171 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2172 if (mono_error_set_pending_exception (&error))
2178 MONO_STRUCT_SETREF (info, get, rm);
2180 if ((req_info & PInfo_SetMethod) != 0) {
2181 if (pproperty->set &&
2182 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2183 pproperty->set->klass == property->klass)) {
2184 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2185 if (mono_error_set_pending_exception (&error))
2191 MONO_STRUCT_SETREF (info, set, rm);
2194 * There may be other methods defined for properties, though, it seems they are not exposed
2195 * in the reflection API
2200 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2203 MonoReflectionType *rt;
2204 MonoReflectionMethod *rm;
2205 MonoDomain *domain = mono_object_domain (event);
2207 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2208 if (mono_error_set_pending_exception (&error))
2211 MONO_STRUCT_SETREF (info, reflected_type, rt);
2213 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2214 if (mono_error_set_pending_exception (&error))
2217 MONO_STRUCT_SETREF (info, declaring_type, rt);
2219 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2220 info->attrs = event->event->attrs;
2222 if (event->event->add) {
2223 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2224 if (mono_error_set_pending_exception (&error))
2230 MONO_STRUCT_SETREF (info, add_method, rm);
2232 if (event->event->remove) {
2233 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2234 if (mono_error_set_pending_exception (&error))
2240 MONO_STRUCT_SETREF (info, remove_method, rm);
2242 if (event->event->raise) {
2243 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2244 if (mono_error_set_pending_exception (&error))
2250 MONO_STRUCT_SETREF (info, raise_method, rm);
2252 #ifndef MONO_SMALL_CONFIG
2253 if (event->event->other) {
2255 while (event->event->other [n])
2257 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2259 for (i = 0; i < n; i++) {
2260 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2261 if (mono_error_set_pending_exception (&error))
2263 mono_array_setref (info->other_methods, i, rm);
2270 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2275 mono_class_setup_interfaces (klass, error);
2276 if (!mono_error_ok (error))
2279 for (i = 0; i < klass->interface_count; i++) {
2280 ic = klass->interfaces [i];
2281 g_hash_table_insert (ifaces, ic, ic);
2283 collect_interfaces (ic, ifaces, error);
2284 if (!mono_error_ok (error))
2290 MonoArray *iface_array;
2291 MonoGenericContext *context;
2295 } FillIfaceArrayData;
2298 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2300 MonoReflectionType *rt;
2301 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2302 MonoClass *ic = (MonoClass *)key;
2303 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2305 if (!mono_error_ok (data->error))
2308 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2309 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2310 if (!mono_error_ok (data->error))
2314 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2315 if (!mono_error_ok (data->error))
2318 mono_array_setref (data->iface_array, data->next_idx++, rt);
2321 mono_metadata_free_type (inflated);
2325 get_interfaces_hash (gconstpointer v1)
2327 MonoClass *k = (MonoClass*)v1;
2329 return k->type_token;
2332 ICALL_EXPORT MonoArray*
2333 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2336 MonoClass *klass = mono_class_from_mono_type (type->type);
2338 FillIfaceArrayData data = { 0 };
2341 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2343 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2344 data.context = mono_class_get_context (klass);
2345 klass = klass->generic_class->container_class;
2348 for (parent = klass; parent; parent = parent->parent) {
2349 mono_class_setup_interfaces (parent, &error);
2350 if (!mono_error_ok (&error))
2352 collect_interfaces (parent, iface_hash, &error);
2353 if (!mono_error_ok (&error))
2357 data.error = &error;
2358 data.domain = mono_object_domain (type);
2360 len = g_hash_table_size (iface_hash);
2362 g_hash_table_destroy (iface_hash);
2363 if (!data.domain->empty_types)
2364 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2365 return data.domain->empty_types;
2368 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2369 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2370 if (!mono_error_ok (&error))
2373 g_hash_table_destroy (iface_hash);
2374 return data.iface_array;
2377 g_hash_table_destroy (iface_hash);
2378 mono_error_set_pending_exception (&error);
2383 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2385 gboolean variance_used;
2386 MonoClass *klass = mono_class_from_mono_type (type->type);
2387 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2388 MonoReflectionMethod *member;
2391 int i = 0, len, ioffset;
2395 mono_class_init_checked (klass, &error);
2396 if (mono_error_set_pending_exception (&error))
2398 mono_class_init_checked (iclass, &error);
2399 if (mono_error_set_pending_exception (&error))
2402 mono_class_setup_vtable (klass);
2404 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2408 len = mono_class_num_methods (iclass);
2409 domain = mono_object_domain (type);
2410 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2411 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2413 while ((method = mono_class_get_methods (iclass, &iter))) {
2414 member = mono_method_get_object_checked (domain, method, iclass, &error);
2415 if (mono_error_set_pending_exception (&error))
2417 mono_array_setref (*methods, i, member);
2418 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2419 if (mono_error_set_pending_exception (&error))
2421 mono_array_setref (*targets, i, member);
2428 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2431 MonoClass *klass = mono_class_from_mono_type (type->type);
2433 mono_class_init_checked (klass, &error);
2434 if (mono_error_set_pending_exception (&error))
2437 if (image_is_dynamic (klass->image)) {
2438 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2439 *packing = tb->packing_size;
2440 *size = tb->class_size;
2442 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2446 ICALL_EXPORT MonoReflectionType*
2447 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2450 MonoReflectionType *ret;
2453 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2454 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2455 mono_error_set_pending_exception (&error);
2459 klass = mono_class_from_mono_type (type->type);
2460 mono_class_init_checked (klass, &error);
2461 if (mono_error_set_pending_exception (&error))
2465 // GetElementType should only return a type for:
2466 // Array Pointer PassedByRef
2467 if (type->type->byref)
2468 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2469 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2470 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2471 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2472 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2476 mono_error_set_pending_exception (&error);
2481 ICALL_EXPORT MonoReflectionType*
2482 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2485 MonoReflectionType *ret;
2487 if (type->type->byref)
2490 MonoClass *klass = mono_class_from_mono_type (type->type);
2494 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2495 mono_error_set_pending_exception (&error);
2500 ICALL_EXPORT MonoBoolean
2501 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2503 return type->type->type == MONO_TYPE_PTR;
2506 ICALL_EXPORT MonoBoolean
2507 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2509 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)));
2512 ICALL_EXPORT MonoBoolean
2513 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2515 return type->type->byref;
2518 ICALL_EXPORT MonoBoolean
2519 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2522 MonoClass *klass = mono_class_from_mono_type (type->type);
2523 mono_class_init_checked (klass, &error);
2524 if (mono_error_set_pending_exception (&error))
2527 return mono_class_is_com_object (klass);
2530 ICALL_EXPORT guint32
2531 ves_icall_reflection_get_token (MonoObject* obj)
2534 guint32 result = mono_reflection_get_token_checked (obj, &error);
2535 mono_error_set_pending_exception (&error);
2539 ICALL_EXPORT MonoReflectionModule*
2540 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2543 MonoReflectionModule *result = NULL;
2544 MonoClass *klass = mono_class_from_mono_type (type->type);
2545 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2546 mono_error_set_pending_exception (&error);
2550 ICALL_EXPORT MonoReflectionAssembly*
2551 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2554 MonoDomain *domain = mono_domain_get ();
2555 MonoClass *klass = mono_class_from_mono_type (type->type);
2556 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2557 mono_error_set_pending_exception (&error);
2561 ICALL_EXPORT MonoReflectionType*
2562 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2565 MonoReflectionType *ret;
2566 MonoDomain *domain = mono_domain_get ();
2569 if (type->type->byref)
2571 if (type->type->type == MONO_TYPE_VAR) {
2572 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2573 klass = param ? param->owner.klass : NULL;
2574 } else if (type->type->type == MONO_TYPE_MVAR) {
2575 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2576 klass = param ? param->owner.method->klass : NULL;
2578 klass = mono_class_from_mono_type (type->type)->nested_in;
2584 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2585 mono_error_set_pending_exception (&error);
2590 ICALL_EXPORT MonoString*
2591 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2593 MonoDomain *domain = mono_domain_get ();
2594 MonoClass *klass = mono_class_from_mono_type (type->type);
2596 if (type->type->byref) {
2597 char *n = g_strdup_printf ("%s&", klass->name);
2598 MonoString *res = mono_string_new (domain, n);
2604 return mono_string_new (domain, klass->name);
2608 ICALL_EXPORT MonoString*
2609 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2611 MonoDomain *domain = mono_domain_get ();
2612 MonoClass *klass = mono_class_from_mono_type (type->type);
2614 while (klass->nested_in)
2615 klass = klass->nested_in;
2617 if (klass->name_space [0] == '\0')
2620 return mono_string_new (domain, klass->name_space);
2624 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2628 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2629 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2633 klass = mono_class_from_mono_type (type->type);
2639 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2642 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2646 ICALL_EXPORT MonoArray*
2647 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2650 MonoReflectionType *rt;
2652 MonoClass *klass, *pklass;
2653 MonoDomain *domain = mono_object_domain (type);
2656 klass = mono_class_from_mono_type (type->type);
2658 if (klass->generic_container) {
2659 MonoGenericContainer *container = klass->generic_container;
2660 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2661 for (i = 0; i < container->type_argc; ++i) {
2662 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2664 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2665 if (mono_error_set_pending_exception (&error))
2668 mono_array_setref (res, i, rt);
2670 } else if (klass->generic_class) {
2671 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2672 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2673 for (i = 0; i < inst->type_argc; ++i) {
2674 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2675 if (mono_error_set_pending_exception (&error))
2678 mono_array_setref (res, i, rt);
2686 ICALL_EXPORT gboolean
2687 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2691 if (!IS_MONOTYPE (type))
2694 if (type->type->byref)
2697 klass = mono_class_from_mono_type (type->type);
2698 return klass->generic_container != NULL;
2701 ICALL_EXPORT MonoReflectionType*
2702 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2705 MonoReflectionType *ret;
2708 if (type->type->byref)
2711 klass = mono_class_from_mono_type (type->type);
2713 if (klass->generic_container) {
2714 return type; /* check this one */
2716 if (klass->generic_class) {
2717 MonoClass *generic_class = klass->generic_class->container_class;
2720 tb = mono_class_get_ref_info (generic_class);
2722 if (generic_class->wastypebuilder && tb)
2723 return (MonoReflectionType *)tb;
2725 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2726 mono_error_set_pending_exception (&error);
2734 ICALL_EXPORT MonoReflectionType*
2735 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2738 MonoReflectionType *ret;
2740 MonoType *geninst, **types;
2743 g_assert (IS_MONOTYPE (type));
2744 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2745 if (mono_error_set_pending_exception (&error))
2748 count = mono_array_length (type_array);
2749 types = g_new0 (MonoType *, count);
2751 for (i = 0; i < count; i++) {
2752 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2753 types [i] = t->type;
2756 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2759 mono_error_set_pending_exception (&error);
2763 klass = mono_class_from_mono_type (geninst);
2765 /*we might inflate to the GTD*/
2766 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2767 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2771 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2772 mono_error_set_pending_exception (&error);
2777 ICALL_EXPORT gboolean
2778 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2782 if (!IS_MONOTYPE (type))
2785 if (type->type->byref)
2788 klass = mono_class_from_mono_type (type->type);
2789 return klass->generic_class != NULL || klass->generic_container != NULL;
2793 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2795 if (!IS_MONOTYPE (type))
2798 if (is_generic_parameter (type->type))
2799 return mono_type_get_generic_param_num (type->type);
2803 ICALL_EXPORT GenericParameterAttributes
2804 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2806 g_assert (IS_MONOTYPE (type));
2807 g_assert (is_generic_parameter (type->type));
2808 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2811 ICALL_EXPORT MonoArray *
2812 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2815 MonoReflectionType *rt;
2816 MonoGenericParamInfo *param_info;
2822 g_assert (IS_MONOTYPE (type));
2824 domain = mono_object_domain (type);
2825 param_info = mono_generic_param_info (type->type->data.generic_param);
2826 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2829 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2830 for (i = 0; i < count; i++) {
2831 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2832 if (mono_error_set_pending_exception (&error))
2835 mono_array_setref (res, i, rt);
2842 ICALL_EXPORT MonoBoolean
2843 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2845 return is_generic_parameter (type->type);
2848 ICALL_EXPORT MonoBoolean
2849 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2851 return is_generic_parameter (tb->type.type);
2855 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2856 MonoReflectionType *t)
2858 enumtype->type = t->type;
2861 ICALL_EXPORT MonoReflectionMethod*
2862 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2863 MonoReflectionMethod* generic)
2870 MonoReflectionMethod *ret = NULL;
2872 domain = ((MonoObject *)type)->vtable->domain;
2874 klass = mono_class_from_mono_type (type->type);
2875 mono_class_init_checked (klass, &error);
2876 if (mono_error_set_pending_exception (&error))
2880 while ((method = mono_class_get_methods (klass, &iter))) {
2881 if (method->token == generic->method->token) {
2882 ret = mono_method_get_object_checked (domain, method, klass, &error);
2883 if (mono_error_set_pending_exception (&error))
2891 ICALL_EXPORT MonoReflectionMethod *
2892 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2895 MonoType *type = ref_type->type;
2897 MonoReflectionMethod *ret = NULL;
2899 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2900 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2903 if (type->type == MONO_TYPE_VAR)
2906 method = mono_type_get_generic_param_owner (type)->owner.method;
2909 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2910 if (!mono_error_ok (&error))
2911 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2915 ICALL_EXPORT MonoBoolean
2916 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2918 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2922 ICALL_EXPORT MonoBoolean
2923 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2925 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2930 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2932 MonoDomain *domain = mono_domain_get ();
2933 MonoImage *image = method->method->klass->image;
2934 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2935 MonoTableInfo *tables = image->tables;
2936 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2937 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2938 guint32 im_cols [MONO_IMPLMAP_SIZE];
2939 guint32 scope_token;
2940 const char *import = NULL;
2941 const char *scope = NULL;
2943 if (image_is_dynamic (image)) {
2944 MonoReflectionMethodAux *method_aux =
2945 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2947 import = method_aux->dllentry;
2948 scope = method_aux->dll;
2951 if (!import || !scope) {
2952 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2957 if (piinfo->implmap_idx) {
2958 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2960 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2961 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2962 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2963 scope = mono_metadata_string_heap (image, scope_token);
2967 *flags = piinfo->piflags;
2968 *entry_point = mono_string_new (domain, import);
2969 *dll_name = mono_string_new (domain, scope);
2972 ICALL_EXPORT MonoReflectionMethod *
2973 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2975 MonoMethodInflated *imethod;
2977 MonoReflectionMethod *ret = NULL;
2980 if (method->method->is_generic)
2983 if (!method->method->is_inflated)
2986 imethod = (MonoMethodInflated *) method->method;
2988 result = imethod->declaring;
2989 /* Not a generic method. */
2990 if (!result->is_generic)
2993 if (image_is_dynamic (method->method->klass->image)) {
2994 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2995 MonoReflectionMethod *res;
2998 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2999 * the dynamic case as well ?
3001 mono_image_lock ((MonoImage*)image);
3002 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3003 mono_image_unlock ((MonoImage*)image);
3009 if (imethod->context.class_inst) {
3010 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3011 /*Generic methods gets the context of the GTD.*/
3012 if (mono_class_get_context (klass)) {
3013 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3014 if (!mono_error_ok (&error))
3019 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3021 if (!mono_error_ok (&error))
3022 mono_error_set_pending_exception (&error);
3026 ICALL_EXPORT gboolean
3027 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3029 return mono_method_signature (method->method)->generic_param_count != 0;
3032 ICALL_EXPORT gboolean
3033 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3035 return method->method->is_generic;
3038 ICALL_EXPORT MonoArray*
3039 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3042 MonoReflectionType *rt;
3047 domain = mono_object_domain (method);
3049 if (method->method->is_inflated) {
3050 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3053 count = inst->type_argc;
3054 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3056 for (i = 0; i < count; i++) {
3057 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3058 if (mono_error_set_pending_exception (&error))
3061 mono_array_setref (res, i, rt);
3068 count = mono_method_signature (method->method)->generic_param_count;
3069 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3071 for (i = 0; i < count; i++) {
3072 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3073 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3074 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3076 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3077 if (mono_error_set_pending_exception (&error))
3080 mono_array_setref (res, i, rt);
3086 ICALL_EXPORT MonoObject *
3087 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3091 * Invoke from reflection is supposed to always be a virtual call (the API
3092 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3093 * greater flexibility.
3095 MonoMethod *m = method->method;
3096 MonoMethodSignature *sig = mono_method_signature (m);
3099 void *obj = this_arg;
3103 if (mono_security_core_clr_enabled () &&
3104 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3105 mono_error_set_pending_exception (&error);
3109 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3110 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3111 mono_error_cleanup (&error); /* FIXME does this make sense? */
3112 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3117 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3118 if (!is_ok (&error)) {
3119 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3122 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3123 char *target_name = mono_type_get_full_name (m->klass);
3124 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3125 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3127 g_free (target_name);
3131 m = mono_object_get_virtual_method (this_arg, m);
3132 /* must pass the pointer to the value for valuetype methods */
3133 if (m->klass->valuetype)
3134 obj = mono_object_unbox (this_arg);
3135 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3136 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3141 if (sig->ret->byref) {
3142 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"));
3146 pcount = params? mono_array_length (params): 0;
3147 if (pcount != sig->param_count) {
3148 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3152 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3153 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."));
3157 image = m->klass->image;
3158 if (image->assembly->ref_only) {
3159 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."));
3163 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3164 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3168 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3172 intptr_t *lower_bounds;
3173 pcount = mono_array_length (params);
3174 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3175 /* Note: the synthetized array .ctors have int32 as argument type */
3176 for (i = 0; i < pcount; ++i)
3177 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3179 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3180 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3181 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3182 if (!mono_error_ok (&error)) {
3183 mono_error_set_pending_exception (&error);
3187 for (i = 0; i < mono_array_length (arr); ++i) {
3188 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3189 if (!mono_error_ok (&error)) {
3190 mono_error_set_pending_exception (&error);
3193 mono_array_setref_fast (arr, i, subarray);
3195 return (MonoObject*)arr;
3198 if (m->klass->rank == pcount) {
3199 /* Only lengths provided. */
3200 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3201 if (!mono_error_ok (&error)) {
3202 mono_error_set_pending_exception (&error);
3206 return (MonoObject*)arr;
3208 g_assert (pcount == (m->klass->rank * 2));
3209 /* The arguments are lower-bound-length pairs */
3210 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3212 for (i = 0; i < pcount / 2; ++i) {
3213 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3214 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3217 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3218 if (!mono_error_ok (&error)) {
3219 mono_error_set_pending_exception (&error);
3223 return (MonoObject*)arr;
3226 return mono_runtime_invoke_array (m, obj, params, NULL);
3229 #ifndef DISABLE_REMOTING
3230 ICALL_EXPORT MonoObject *
3231 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3234 MonoDomain *domain = mono_object_domain (method);
3235 MonoMethod *m = method->method;
3236 MonoMethodSignature *sig = mono_method_signature (m);
3237 MonoArray *out_args;
3239 int i, j, outarg_count = 0;
3241 if (m->klass == mono_defaults.object_class) {
3242 if (!strcmp (m->name, "FieldGetter")) {
3243 MonoClass *k = this_arg->vtable->klass;
3247 /* If this is a proxy, then it must be a CBO */
3248 if (k == mono_defaults.transparent_proxy_class) {
3249 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3250 this_arg = tp->rp->unwrapped_server;
3251 g_assert (this_arg);
3252 k = this_arg->vtable->klass;
3255 name = mono_array_get (params, MonoString *, 1);
3256 str = mono_string_to_utf8 (name);
3259 MonoClassField* field = mono_class_get_field_from_name (k, str);
3261 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3262 if (field_klass->valuetype) {
3263 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3264 mono_error_set_pending_exception (&error);
3265 /* fallthru to cleanup */
3267 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3269 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3270 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3271 mono_array_setref (out_args, 0, result);
3279 g_assert_not_reached ();
3281 } else if (!strcmp (m->name, "FieldSetter")) {
3282 MonoClass *k = this_arg->vtable->klass;
3288 /* If this is a proxy, then it must be a CBO */
3289 if (k == mono_defaults.transparent_proxy_class) {
3290 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3291 this_arg = tp->rp->unwrapped_server;
3292 g_assert (this_arg);
3293 k = this_arg->vtable->klass;
3296 name = mono_array_get (params, MonoString *, 1);
3297 str = mono_string_to_utf8 (name);
3300 MonoClassField* field = mono_class_get_field_from_name (k, str);
3302 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3303 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3305 if (field_klass->valuetype) {
3306 size = mono_type_size (field->type, &align);
3307 g_assert (size == mono_class_value_size (field_klass, NULL));
3308 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3310 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3313 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3314 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3324 g_assert_not_reached ();
3329 for (i = 0; i < mono_array_length (params); i++) {
3330 if (sig->params [i]->byref)
3334 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3336 /* handle constructors only for objects already allocated */
3337 if (!strcmp (method->method->name, ".ctor"))
3338 g_assert (this_arg);
3340 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3341 g_assert (!method->method->klass->valuetype);
3342 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3344 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3345 if (sig->params [i]->byref) {
3347 arg = mono_array_get (params, gpointer, i);
3348 mono_array_setref (out_args, j, arg);
3353 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3360 read_enum_value (const char *mem, int type)
3363 case MONO_TYPE_BOOLEAN:
3365 return *(guint8*)mem;
3367 return *(gint8*)mem;
3368 case MONO_TYPE_CHAR:
3370 return read16 (mem);
3372 return (gint16) read16 (mem);
3374 return read32 (mem);
3376 return (gint32) read32 (mem);
3379 return read64 (mem);
3381 g_assert_not_reached ();
3387 write_enum_value (char *mem, int type, guint64 value)
3391 case MONO_TYPE_I1: {
3392 guint8 *p = (guint8*)mem;
3397 case MONO_TYPE_I2: {
3398 guint16 *p = (guint16 *)mem;
3403 case MONO_TYPE_I4: {
3404 guint32 *p = (guint32 *)mem;
3409 case MONO_TYPE_I8: {
3410 guint64 *p = (guint64 *)mem;
3415 g_assert_not_reached ();
3420 ICALL_EXPORT MonoObject *
3421 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3429 domain = mono_object_domain (enumType);
3430 enumc = mono_class_from_mono_type (enumType->type);
3432 mono_class_init_checked (enumc, &error);
3433 if (mono_error_set_pending_exception (&error))
3436 etype = mono_class_enum_basetype (enumc);
3438 res = mono_object_new_checked (domain, enumc, &error);
3439 if (mono_error_set_pending_exception (&error))
3441 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3446 ICALL_EXPORT MonoBoolean
3447 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3449 int size = mono_class_value_size (a->vtable->klass, NULL);
3450 guint64 a_val = 0, b_val = 0;
3452 memcpy (&a_val, mono_object_unbox (a), size);
3453 memcpy (&b_val, mono_object_unbox (b), size);
3455 return (a_val & b_val) == b_val;
3458 ICALL_EXPORT MonoObject *
3459 ves_icall_System_Enum_get_value (MonoObject *eobj)
3471 g_assert (eobj->vtable->klass->enumtype);
3473 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3474 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3475 if (mono_error_set_pending_exception (&error))
3477 dst = (char *)res + sizeof (MonoObject);
3478 src = (char *)eobj + sizeof (MonoObject);
3479 size = mono_class_value_size (enumc, NULL);
3481 memcpy (dst, src, size);
3486 ICALL_EXPORT MonoReflectionType *
3487 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3490 MonoReflectionType *ret;
3494 klass = mono_class_from_mono_type (type->type);
3495 mono_class_init_checked (klass, &error);
3496 if (mono_error_set_pending_exception (&error))
3499 etype = mono_class_enum_basetype (klass);
3501 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3505 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3506 mono_error_set_pending_exception (&error);
3512 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3514 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3515 gpointer odata = (char *)other + sizeof (MonoObject);
3516 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3517 g_assert (basetype);
3522 if (eobj->vtable->klass != other->vtable->klass)
3525 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3526 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3527 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3530 return me > other ? 1 : -1; \
3533 switch (basetype->type) {
3535 COMPARE_ENUM_VALUES (guint8);
3537 COMPARE_ENUM_VALUES (gint8);
3538 case MONO_TYPE_CHAR:
3540 COMPARE_ENUM_VALUES (guint16);
3542 COMPARE_ENUM_VALUES (gint16);
3544 COMPARE_ENUM_VALUES (guint32);
3546 COMPARE_ENUM_VALUES (gint32);
3548 COMPARE_ENUM_VALUES (guint64);
3550 COMPARE_ENUM_VALUES (gint64);
3554 #undef COMPARE_ENUM_VALUES
3555 /* indicates that the enum was of an unsupported unerlying type */
3560 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3562 gpointer data = (char *)eobj + sizeof (MonoObject);
3563 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3564 g_assert (basetype);
3566 switch (basetype->type) {
3567 case MONO_TYPE_I1: {
3568 gint8 value = *((gint8*)data);
3569 return ((int)value ^ (int)value << 8);
3572 return *((guint8*)data);
3573 case MONO_TYPE_CHAR:
3575 return *((guint16*)data);
3577 case MONO_TYPE_I2: {
3578 gint16 value = *((gint16*)data);
3579 return ((int)(guint16)value | (((int)value) << 16));
3582 return *((guint32*)data);
3584 return *((gint32*)data);
3586 case MONO_TYPE_I8: {
3587 gint64 value = *((gint64*)data);
3588 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3591 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3596 ICALL_EXPORT MonoBoolean
3597 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3600 MonoDomain *domain = mono_object_domain (type);
3601 MonoClass *enumc = mono_class_from_mono_type (type->type);
3602 guint j = 0, nvalues;
3604 MonoClassField *field;
3606 guint64 field_value, previous_value = 0;
3607 gboolean sorted = TRUE;
3609 mono_class_init_checked (enumc, &error);
3610 if (mono_error_set_pending_exception (&error))
3614 if (!enumc->enumtype) {
3615 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3619 base_type = mono_class_enum_basetype (enumc)->type;
3621 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3622 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3623 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3626 while ((field = mono_class_get_fields (enumc, &iter))) {
3628 MonoTypeEnum def_type;
3630 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3632 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3634 if (mono_field_is_deleted (field))
3636 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3638 p = mono_class_get_field_default_value (field, &def_type);
3639 /* len = */ mono_metadata_decode_blob_size (p, &p);
3641 field_value = read_enum_value (p, base_type);
3642 mono_array_set (*values, guint64, j, field_value);
3644 if (previous_value > field_value)
3647 previous_value = field_value;
3655 BFLAGS_IgnoreCase = 1,
3656 BFLAGS_DeclaredOnly = 2,
3657 BFLAGS_Instance = 4,
3659 BFLAGS_Public = 0x10,
3660 BFLAGS_NonPublic = 0x20,
3661 BFLAGS_FlattenHierarchy = 0x40,
3662 BFLAGS_InvokeMethod = 0x100,
3663 BFLAGS_CreateInstance = 0x200,
3664 BFLAGS_GetField = 0x400,
3665 BFLAGS_SetField = 0x800,
3666 BFLAGS_GetProperty = 0x1000,
3667 BFLAGS_SetProperty = 0x2000,
3668 BFLAGS_ExactBinding = 0x10000,
3669 BFLAGS_SuppressChangeType = 0x20000,
3670 BFLAGS_OptionalParamBinding = 0x40000
3673 ICALL_EXPORT MonoArray*
3674 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3678 MonoClass *startklass, *klass, *refklass;
3683 char *utf8_name = NULL;
3684 int (*compare_func) (const char *s1, const char *s2) = NULL;
3685 MonoClassField *field;
3686 MonoPtrArray tmp_array;
3688 domain = ((MonoObject *)type)->vtable->domain;
3689 if (type->type->byref)
3690 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3692 klass = startklass = mono_class_from_mono_type (type->type);
3693 refklass = mono_class_from_mono_type (reftype->type);
3695 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3698 if (mono_class_has_failure (klass)) {
3699 mono_ptr_array_destroy (tmp_array);
3700 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3705 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3706 guint32 flags = mono_field_get_flags (field);
3708 if (mono_field_is_deleted_with_flags (field, flags))
3710 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3711 if (bflags & BFLAGS_Public)
3713 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3714 if (bflags & BFLAGS_NonPublic) {
3721 if (flags & FIELD_ATTRIBUTE_STATIC) {
3722 if (bflags & BFLAGS_Static)
3723 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3726 if (bflags & BFLAGS_Instance)
3734 if (utf8_name == NULL) {
3735 utf8_name = mono_string_to_utf8 (name);
3736 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3739 if (compare_func (mono_field_get_name (field), utf8_name))
3743 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3744 if (!mono_error_ok (&error))
3746 mono_ptr_array_append (tmp_array, member);
3748 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3751 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3753 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3754 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3756 mono_ptr_array_destroy (tmp_array);
3758 if (utf8_name != NULL)
3763 mono_ptr_array_destroy (tmp_array);
3764 mono_error_set_pending_exception (&error);
3769 method_nonpublic (MonoMethod* method, gboolean start_klass)
3771 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3772 case METHOD_ATTRIBUTE_ASSEM:
3773 return (start_klass || mono_defaults.generic_ilist_class);
3774 case METHOD_ATTRIBUTE_PRIVATE:
3776 case METHOD_ATTRIBUTE_PUBLIC:
3784 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3787 MonoClass *startklass;
3791 /*FIXME, use MonoBitSet*/
3792 guint32 method_slots_default [8];
3793 guint32 *method_slots = NULL;
3794 int (*compare_func) (const char *s1, const char *s2) = NULL;
3796 array = g_ptr_array_new ();
3801 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3803 /* An optimization for calls made from Delegate:CreateDelegate () */
3804 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3805 method = mono_get_delegate_invoke (klass);
3806 if (mono_loader_get_last_error ())
3809 g_ptr_array_add (array, method);
3813 mono_class_setup_methods (klass);
3814 mono_class_setup_vtable (klass);
3815 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3818 if (is_generic_parameter (&klass->byval_arg))
3819 nslots = mono_class_get_vtable_size (klass->parent);
3821 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3822 if (nslots >= sizeof (method_slots_default) * 8) {
3823 method_slots = g_new0 (guint32, nslots / 32 + 1);
3825 method_slots = method_slots_default;
3826 memset (method_slots, 0, sizeof (method_slots_default));
3829 mono_class_setup_methods (klass);
3830 mono_class_setup_vtable (klass);
3831 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3835 while ((method = mono_class_get_methods (klass, &iter))) {
3837 if (method->slot != -1) {
3838 g_assert (method->slot < nslots);
3839 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3841 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3842 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3845 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3847 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3848 if (bflags & BFLAGS_Public)
3850 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3856 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3857 if (bflags & BFLAGS_Static)
3858 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3861 if (bflags & BFLAGS_Instance)
3869 if (compare_func (name, method->name))
3874 g_ptr_array_add (array, method);
3876 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3878 if (method_slots != method_slots_default)
3879 g_free (method_slots);
3884 if (method_slots != method_slots_default)
3885 g_free (method_slots);
3886 g_ptr_array_free (array, TRUE);
3888 if (mono_class_has_failure (klass)) {
3889 *ex = mono_class_get_exception_for_failure (klass);
3891 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3892 mono_loader_clear_error ();
3897 ICALL_EXPORT MonoArray*
3898 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3900 static MonoClass *MethodInfo_array;
3904 MonoVTable *array_vtable;
3905 MonoException *ex = NULL;
3906 const char *mname = NULL;
3907 GPtrArray *method_array;
3908 MonoClass *klass, *refklass;
3911 mono_error_init (&error);
3913 if (!MethodInfo_array) {
3914 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3915 mono_memory_barrier ();
3916 MethodInfo_array = klass;
3919 klass = mono_class_from_mono_type (type->type);
3920 refklass = mono_class_from_mono_type (reftype->type);
3921 domain = ((MonoObject *)type)->vtable->domain;
3922 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3923 if (!is_ok (&error)) {
3924 mono_error_set_pending_exception (&error);
3927 if (type->type->byref) {
3928 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3929 mono_error_set_pending_exception (&error);
3935 mname = mono_string_to_utf8 (name);
3937 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3938 g_free ((char*)mname);
3940 mono_set_pending_exception (ex);
3944 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3945 if (!mono_error_ok (&error)) {
3946 mono_error_set_pending_exception (&error);
3950 for (i = 0; i < method_array->len; ++i) {
3951 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3952 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3953 if (!mono_error_ok (&error))
3955 mono_array_setref (res, i, rm);
3959 g_ptr_array_free (method_array, TRUE);
3960 if (!mono_error_ok (&error))
3961 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3965 ICALL_EXPORT MonoArray*
3966 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3969 MonoClass *startklass, *klass, *refklass;
3974 gpointer iter = NULL;
3975 MonoPtrArray tmp_array;
3978 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3980 domain = ((MonoObject *)type)->vtable->domain;
3981 if (type->type->byref)
3982 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3983 klass = startklass = mono_class_from_mono_type (type->type);
3984 refklass = mono_class_from_mono_type (reftype->type);
3986 mono_class_setup_methods (klass);
3987 if (mono_class_has_failure (klass)) {
3988 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3993 while ((method = mono_class_get_methods (klass, &iter))) {
3995 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3997 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3998 if (bflags & BFLAGS_Public)
4001 if (bflags & BFLAGS_NonPublic)
4007 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4008 if (bflags & BFLAGS_Static)
4009 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4012 if (bflags & BFLAGS_Instance)
4018 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
4019 if (!mono_error_ok (&error)) {
4020 mono_error_set_pending_exception (&error);
4024 mono_ptr_array_append (tmp_array, member);
4027 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
4029 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4030 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4032 mono_ptr_array_destroy (tmp_array);
4038 property_hash (gconstpointer data)
4040 MonoProperty *prop = (MonoProperty*)data;
4042 return g_str_hash (prop->name);
4046 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
4048 if (method1->is_inflated)
4049 method1 = ((MonoMethodInflated*) method1)->declaring;
4050 if (method2->is_inflated)
4051 method2 = ((MonoMethodInflated*) method2)->declaring;
4053 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4057 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4059 // Properties are hide-by-name-and-signature
4060 if (!g_str_equal (prop1->name, prop2->name))
4063 /* If we see a property in a generic method, we want to
4064 compare the generic signatures, not the inflated signatures
4065 because we might conflate two properties that were
4069 public T this[T t] { getter { return t; } } // method 1
4070 public U this[U u] { getter { return u; } } // method 2
4073 If we see int Foo<int,int>::Item[int] we need to know if
4074 the indexer came from method 1 or from method 2, and we
4075 shouldn't conflate them. (Bugzilla 36283)
4077 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
4080 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4087 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4092 return method_nonpublic (accessor, start_klass);
4095 ICALL_EXPORT MonoArray*
4096 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4100 MonoClass *startklass, *klass;
4106 gchar *propname = NULL;
4107 int (*compare_func) (const char *s1, const char *s2) = NULL;
4109 GHashTable *properties = NULL;
4110 MonoPtrArray tmp_array;
4112 mono_error_init (&error);
4114 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4116 domain = ((MonoObject *)type)->vtable->domain;
4117 if (type->type->byref)
4118 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
4119 klass = startklass = mono_class_from_mono_type (type->type);
4122 propname = mono_string_to_utf8 (name);
4123 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4126 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4128 mono_class_setup_methods (klass);
4129 mono_class_setup_vtable (klass);
4130 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4134 while ((prop = mono_class_get_properties (klass, &iter))) {
4140 flags = method->flags;
4143 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4144 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4145 if (bflags & BFLAGS_Public)
4147 } else if (bflags & BFLAGS_NonPublic) {
4148 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4149 property_accessor_nonpublic(prop->set, startklass == klass)) {
4156 if (flags & METHOD_ATTRIBUTE_STATIC) {
4157 if (bflags & BFLAGS_Static)
4158 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4161 if (bflags & BFLAGS_Instance)
4170 if (compare_func (propname, prop->name))
4174 if (g_hash_table_lookup (properties, prop))
4177 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4180 mono_ptr_array_append (tmp_array, pr);
4182 g_hash_table_insert (properties, prop, prop);
4184 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4187 g_hash_table_destroy (properties);
4190 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4191 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4192 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4194 mono_ptr_array_destroy (tmp_array);
4201 if (mono_class_has_failure (klass)) {
4202 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4204 mono_error_set_from_loader_error (&error);
4205 mono_loader_clear_error ();
4210 g_hash_table_destroy (properties);
4213 mono_ptr_array_destroy (tmp_array);
4215 mono_error_set_pending_exception (&error);
4221 event_hash (gconstpointer data)
4223 MonoEvent *event = (MonoEvent*)data;
4225 return g_str_hash (event->name);
4229 event_equal (MonoEvent *event1, MonoEvent *event2)
4231 // Events are hide-by-name
4232 return g_str_equal (event1->name, event2->name);
4235 ICALL_EXPORT MonoArray*
4236 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4240 MonoClass *startklass, *klass;
4246 char *utf8_name = NULL;
4247 int (*compare_func) (const char *s1, const char *s2) = NULL;
4248 GHashTable *events = NULL;
4249 MonoPtrArray tmp_array;
4251 mono_error_init (&error);
4253 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4255 domain = mono_object_domain (type);
4256 if (type->type->byref)
4257 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4258 klass = startklass = mono_class_from_mono_type (type->type);
4260 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4262 mono_class_setup_methods (klass);
4263 mono_class_setup_vtable (klass);
4264 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4268 while ((event = mono_class_get_events (klass, &iter))) {
4270 method = event->add;
4272 method = event->remove;
4274 method = event->raise;
4276 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4277 if (bflags & BFLAGS_Public)
4279 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4280 if (bflags & BFLAGS_NonPublic)
4285 if (bflags & BFLAGS_NonPublic)
4291 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4292 if (bflags & BFLAGS_Static)
4293 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4296 if (bflags & BFLAGS_Instance)
4301 if (bflags & BFLAGS_Instance)
4307 if (utf8_name == NULL) {
4308 utf8_name = mono_string_to_utf8 (name);
4309 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4312 if (compare_func (event->name, utf8_name))
4316 if (g_hash_table_lookup (events, event))
4319 MonoReflectionEvent *ev_obj;
4320 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4323 mono_ptr_array_append (tmp_array, ev_obj);
4325 g_hash_table_insert (events, event, event);
4327 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4330 g_hash_table_destroy (events);
4332 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4334 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4335 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4337 mono_ptr_array_destroy (tmp_array);
4339 if (utf8_name != NULL)
4345 if (mono_class_has_failure (klass)) {
4346 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4348 mono_error_set_from_loader_error (&error);
4349 mono_loader_clear_error ();
4355 g_hash_table_destroy (events);
4356 if (utf8_name != NULL)
4359 mono_ptr_array_destroy (tmp_array);
4361 mono_error_set_pending_exception (&error);
4365 ICALL_EXPORT MonoArray*
4366 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4369 MonoReflectionType *rt;
4372 MonoArray *res = NULL;
4377 MonoPtrArray tmp_array;
4379 mono_error_init (&error);
4381 domain = ((MonoObject *)type)->vtable->domain;
4382 if (type->type->byref)
4383 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4384 klass = mono_class_from_mono_type (type->type);
4387 * If a nested type is generic, return its generic type definition.
4388 * Note that this means that the return value is essentially the set
4389 * of nested types of the generic type definition of @klass.
4391 * A note in MSDN claims that a generic type definition can have
4392 * nested types that aren't generic. In any case, the container of that
4393 * nested type would be the generic type definition.
4395 if (klass->generic_class)
4396 klass = klass->generic_class->container_class;
4398 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4400 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4402 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4403 if (bflags & BFLAGS_Public)
4406 if (bflags & BFLAGS_NonPublic)
4414 str = mono_string_to_utf8 (name);
4415 mono_identifier_unescape_type_name_chars (str);
4418 if (strcmp (nested->name, str))
4422 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4423 if (!is_ok (&error))
4426 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4429 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4431 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4432 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4435 mono_ptr_array_destroy (tmp_array);
4439 mono_error_set_pending_exception (&error);
4443 ICALL_EXPORT MonoReflectionType*
4444 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4447 MonoReflectionType *ret;
4449 MonoType *type = NULL;
4450 MonoTypeNameParse info;
4451 gboolean type_resolve;
4453 /* On MS.NET, this does not fire a TypeResolve event */
4454 type_resolve = TRUE;
4455 str = mono_string_to_utf8 (name);
4456 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4457 if (!mono_reflection_parse_type (str, &info)) {
4459 mono_reflection_free_type_info (&info);
4461 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4464 /*g_print ("failed parse\n");*/
4468 if (info.assembly.name) {
4470 mono_reflection_free_type_info (&info);
4472 /* 1.0 and 2.0 throw different exceptions */
4473 if (mono_defaults.generic_ilist_class)
4474 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4476 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4482 if (module != NULL) {
4483 if (module->image) {
4484 type = mono_reflection_get_type_checked (module->image, &info, ignoreCase, &type_resolve, &error);
4485 if (!is_ok (&error)) {
4487 mono_reflection_free_type_info (&info);
4488 mono_error_set_pending_exception (&error);
4495 if (assembly_is_dynamic (assembly->assembly)) {
4496 /* Enumerate all modules */
4497 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4501 if (abuilder->modules) {
4502 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4503 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4504 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4505 if (!is_ok (&error)) {
4507 mono_reflection_free_type_info (&info);
4508 mono_error_set_pending_exception (&error);
4516 if (!type && abuilder->loaded_modules) {
4517 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4518 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4519 type = mono_reflection_get_type_checked (mod->image, &info, ignoreCase, &type_resolve, &error);
4520 if (!is_ok (&error)) {
4522 mono_reflection_free_type_info (&info);
4523 mono_error_set_pending_exception (&error);
4532 type = mono_reflection_get_type_checked (assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4533 if (!is_ok (&error)) {
4535 mono_reflection_free_type_info (&info);
4536 mono_error_set_pending_exception (&error);
4541 mono_reflection_free_type_info (&info);
4543 MonoException *e = NULL;
4546 e = mono_get_exception_type_load (name, NULL);
4548 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4549 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4551 mono_loader_clear_error ();
4554 mono_set_pending_exception (e);
4556 } else if (mono_loader_get_last_error ()) {
4558 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4561 mono_loader_clear_error ();
4564 if (type->type == MONO_TYPE_CLASS) {
4565 MonoClass *klass = mono_type_get_class (type);
4567 /* need to report exceptions ? */
4568 if (throwOnError && mono_class_has_failure (klass)) {
4569 /* report SecurityException (or others) that occured when loading the assembly */
4570 MonoException *exc = mono_class_get_exception_for_failure (klass);
4571 mono_loader_clear_error ();
4572 mono_set_pending_exception (exc);
4577 /* g_print ("got it\n"); */
4578 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4579 mono_error_set_pending_exception (&error);
4585 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4588 gchar *shadow_ini_file;
4591 /* Check for shadow-copied assembly */
4592 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4593 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4595 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4596 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4602 g_free (shadow_ini_file);
4603 if (content != NULL) {
4606 *filename = content;
4613 ICALL_EXPORT MonoString *
4614 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4616 MonoDomain *domain = mono_object_domain (assembly);
4617 MonoAssembly *mass = assembly->assembly;
4618 MonoString *res = NULL;
4623 if (g_path_is_absolute (mass->image->name)) {
4624 absolute = g_strdup (mass->image->name);
4625 dirname = g_path_get_dirname (absolute);
4627 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4628 dirname = g_strdup (mass->basedir);
4631 replace_shadow_path (domain, dirname, &absolute);
4636 for (i = strlen (absolute) - 1; i >= 0; i--)
4637 if (absolute [i] == '\\')
4642 uri = g_filename_to_uri (absolute, NULL, NULL);
4644 const char *prepend = "file://";
4646 if (*absolute == '/' && *(absolute + 1) == '/') {
4649 prepend = "file:///";
4652 uri = g_strconcat (prepend, absolute, NULL);
4656 res = mono_string_new (domain, uri);
4663 ICALL_EXPORT MonoBoolean
4664 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4666 MonoAssembly *mass = assembly->assembly;
4668 return mass->in_gac;
4671 ICALL_EXPORT MonoReflectionAssembly*
4672 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4677 MonoImageOpenStatus status;
4678 MonoReflectionAssembly* result = NULL;
4680 name = mono_string_to_utf8 (mname);
4681 res = mono_assembly_load_with_partial_name (name, &status);
4687 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4689 mono_error_set_pending_exception (&error);
4693 ICALL_EXPORT MonoString *
4694 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4696 MonoDomain *domain = mono_object_domain (assembly);
4699 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4704 ICALL_EXPORT MonoBoolean
4705 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4707 return assembly->assembly->ref_only;
4710 ICALL_EXPORT MonoString *
4711 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4713 MonoDomain *domain = mono_object_domain (assembly);
4715 return mono_string_new (domain, assembly->assembly->image->version);
4718 ICALL_EXPORT MonoReflectionMethod*
4719 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4722 MonoReflectionMethod *res = NULL;
4725 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4729 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4730 if (!mono_error_ok (&error))
4733 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4736 if (!mono_error_ok (&error))
4737 mono_error_set_pending_exception (&error);
4741 ICALL_EXPORT MonoReflectionModule*
4742 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4745 MonoReflectionModule *result = NULL;
4746 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4747 if (!mono_error_ok (&error))
4748 mono_error_set_pending_exception (&error);
4752 ICALL_EXPORT MonoArray*
4753 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4755 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4756 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4760 for (i = 0; i < table->rows; ++i) {
4761 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4762 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4768 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4770 static MonoMethod *create_version = NULL;
4774 mono_error_init (error);
4777 if (!create_version) {
4778 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4779 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4780 g_assert (create_version);
4781 mono_method_desc_free (desc);
4787 args [3] = &revision;
4788 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4789 return_val_if_nok (error, NULL);
4791 mono_runtime_invoke_checked (create_version, result, args, error);
4792 return_val_if_nok (error, NULL);
4797 ICALL_EXPORT MonoArray*
4798 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4802 MonoDomain *domain = mono_object_domain (assembly);
4804 static MonoMethod *create_culture = NULL;
4805 MonoImage *image = assembly->assembly->image;
4809 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4812 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4814 if (count > 0 && !create_culture) {
4815 MonoMethodDesc *desc = mono_method_desc_new (
4816 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4817 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4818 g_assert (create_culture);
4819 mono_method_desc_free (desc);
4822 for (i = 0; i < count; i++) {
4823 MonoObject *version;
4824 MonoReflectionAssemblyName *aname;
4825 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4827 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4829 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4830 domain, mono_class_get_assembly_name_class (), &error);
4831 if (mono_error_set_pending_exception (&error))
4834 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4836 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4837 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4838 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4839 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4840 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4841 aname->versioncompat = 1; /* SameMachine (default) */
4842 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4844 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4845 if (mono_error_set_pending_exception (&error))
4848 MONO_OBJECT_SETREF (aname, version, version);
4850 if (create_culture) {
4852 MonoBoolean assembly_ref = 1;
4853 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4854 args [1] = &assembly_ref;
4856 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4857 if (mono_error_set_pending_exception (&error))
4860 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4863 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4864 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4865 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4867 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4868 /* public key token isn't copied - the class library will
4869 automatically generate it from the public key if required */
4870 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4871 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4873 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4874 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4877 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4880 /* note: this function doesn't return the codebase on purpose (i.e. it can
4881 be used under partial trust as path information isn't present). */
4883 mono_array_setref (result, i, aname);
4888 /* move this in some file in mono/util/ */
4890 g_concat_dir_and_file (const char *dir, const char *file)
4892 g_return_val_if_fail (dir != NULL, NULL);
4893 g_return_val_if_fail (file != NULL, NULL);
4896 * If the directory name doesn't have a / on the end, we need
4897 * to add one so we get a proper path to the file
4899 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4900 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4902 return g_strconcat (dir, file, NULL);
4906 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4909 char *n = mono_string_to_utf8 (name);
4910 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4912 guint32 cols [MONO_MANIFEST_SIZE];
4913 guint32 impl, file_idx;
4917 for (i = 0; i < table->rows; ++i) {
4918 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4919 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4920 if (strcmp (val, n) == 0)
4924 if (i == table->rows)
4927 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4930 * this code should only be called after obtaining the
4931 * ResourceInfo and handling the other cases.
4933 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4934 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4936 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4941 module = assembly->assembly->image;
4944 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4945 if (mono_error_set_pending_exception (&error))
4947 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4949 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4952 ICALL_EXPORT gboolean
4953 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4956 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4958 guint32 cols [MONO_MANIFEST_SIZE];
4959 guint32 file_cols [MONO_FILE_SIZE];
4963 n = mono_string_to_utf8 (name);
4964 for (i = 0; i < table->rows; ++i) {
4965 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4966 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4967 if (strcmp (val, n) == 0)
4971 if (i == table->rows)
4974 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4975 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4978 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4979 case MONO_IMPLEMENTATION_FILE:
4980 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4981 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4982 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4983 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4984 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4985 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4988 info->location = RESOURCE_LOCATION_EMBEDDED;
4991 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4992 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4993 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4994 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4995 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4996 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4998 mono_set_pending_exception (ex);
5001 MonoReflectionAssembly *assm_obj;
5002 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5004 mono_error_set_pending_exception (&error);
5007 MONO_OBJECT_SETREF (info, assembly, assm_obj);
5009 /* Obtain info recursively */
5010 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5011 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5014 case MONO_IMPLEMENTATION_EXP_TYPE:
5015 g_assert_not_reached ();
5023 ICALL_EXPORT MonoObject*
5024 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
5026 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5027 MonoArray *result = NULL;
5032 /* check hash if needed */
5034 n = mono_string_to_utf8 (name);
5035 for (i = 0; i < table->rows; ++i) {
5036 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5037 if (strcmp (val, n) == 0) {
5040 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5041 fn = mono_string_new (mono_object_domain (assembly), n);
5043 return (MonoObject*)fn;
5051 for (i = 0; i < table->rows; ++i) {
5052 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5056 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
5059 for (i = 0; i < table->rows; ++i) {
5060 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5061 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5062 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5063 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5068 return (MonoObject*)result;
5071 ICALL_EXPORT MonoArray*
5072 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5075 MonoDomain *domain = mono_domain_get();
5078 int i, j, file_count = 0;
5079 MonoImage **modules;
5080 guint32 module_count, real_module_count;
5081 MonoTableInfo *table;
5082 guint32 cols [MONO_FILE_SIZE];
5083 MonoImage *image = assembly->assembly->image;
5085 g_assert (image != NULL);
5086 g_assert (!assembly_is_dynamic (assembly->assembly));
5088 table = &image->tables [MONO_TABLE_FILE];
5089 file_count = table->rows;
5091 modules = image->modules;
5092 module_count = image->module_count;
5094 real_module_count = 0;
5095 for (i = 0; i < module_count; ++i)
5097 real_module_count ++;
5099 klass = mono_class_get_module_class ();
5100 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
5102 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5103 if (mono_error_set_pending_exception (&error))
5106 mono_array_setref (res, 0, image_obj);
5108 for (i = 0; i < module_count; ++i)
5110 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5111 if (mono_error_set_pending_exception (&error))
5113 mono_array_setref (res, j, rm);
5117 for (i = 0; i < file_count; ++i, ++j) {
5118 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5119 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5120 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5121 if (mono_error_set_pending_exception (&error))
5123 mono_array_setref (res, j, rm);
5126 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5128 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5129 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5132 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5133 if (mono_error_set_pending_exception (&error))
5135 mono_array_setref (res, j, rm);
5142 ICALL_EXPORT MonoReflectionMethod*
5143 ves_icall_GetCurrentMethod (void)
5145 MonoReflectionMethod *res = NULL;
5148 MonoMethod *m = mono_method_get_last_managed ();
5151 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5155 while (m->is_inflated)
5156 m = ((MonoMethodInflated*)m)->declaring;
5158 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5159 mono_error_set_pending_exception (&error);
5165 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5168 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5171 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5172 //method is inflated, we should inflate it on the other class
5173 MonoGenericContext ctx;
5174 ctx.method_inst = inflated->context.method_inst;
5175 ctx.class_inst = inflated->context.class_inst;
5176 if (klass->generic_class)
5177 ctx.class_inst = klass->generic_class->context.class_inst;
5178 else if (klass->generic_container)
5179 ctx.class_inst = klass->generic_container->context.class_inst;
5180 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5181 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5185 mono_class_setup_methods (method->klass);
5186 if (mono_class_has_failure (method->klass))
5188 for (i = 0; i < method->klass->method.count; ++i) {
5189 if (method->klass->methods [i] == method) {
5194 mono_class_setup_methods (klass);
5195 if (mono_class_has_failure (klass))
5197 g_assert (offset >= 0 && offset < klass->method.count);
5198 return klass->methods [offset];
5201 ICALL_EXPORT MonoReflectionMethod*
5202 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5204 MonoReflectionMethod *res = NULL;
5208 klass = mono_class_from_mono_type (type);
5209 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5211 if (method->klass != klass) {
5212 method = mono_method_get_equivalent_method (method, klass);
5217 klass = method->klass;
5218 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5219 mono_error_set_pending_exception (&error);
5223 ICALL_EXPORT MonoReflectionMethodBody*
5224 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5227 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5228 mono_error_set_pending_exception (&error);
5232 ICALL_EXPORT MonoReflectionAssembly*
5233 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5236 MonoReflectionAssembly *result;
5237 MonoMethod *dest = NULL;
5239 mono_stack_walk_no_il (get_executing, &dest);
5241 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5243 mono_error_set_pending_exception (&error);
5248 ICALL_EXPORT MonoReflectionAssembly*
5249 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5252 MonoReflectionAssembly *result;
5253 MonoDomain* domain = mono_domain_get ();
5255 if (!domain->entry_assembly)
5258 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5260 mono_error_set_pending_exception (&error);
5264 ICALL_EXPORT MonoReflectionAssembly*
5265 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5270 MonoReflectionAssembly *result;
5273 mono_stack_walk_no_il (get_executing, &dest);
5275 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5279 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5282 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5284 mono_error_set_pending_exception (&error);
5288 ICALL_EXPORT MonoString *
5289 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5290 gboolean assembly_qualified)
5292 MonoDomain *domain = mono_object_domain (object);
5293 MonoTypeNameFormat format;
5298 format = assembly_qualified ?
5299 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5300 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5302 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5304 name = mono_type_get_name_full (object->type, format);
5308 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5313 res = mono_string_new (domain, name);
5320 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5323 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5325 mono_class_init_checked (klass, &error);
5326 mono_error_set_pending_exception (&error);
5327 return mono_security_core_clr_class_level (klass);
5331 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5333 MonoClassField *field = rfield->field;
5334 return mono_security_core_clr_field_level (field, TRUE);
5338 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5340 MonoMethod *method = rfield->method;
5341 return mono_security_core_clr_method_level (method, TRUE);
5345 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)
5347 static MonoMethod *create_culture = NULL;
5351 const char *pkey_ptr;
5353 MonoBoolean assembly_ref = 0;
5355 mono_error_init (error);
5357 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5358 aname->major = name->major;
5359 aname->minor = name->minor;
5360 aname->build = name->build;
5361 aname->flags = name->flags;
5362 aname->revision = name->revision;
5363 aname->hashalg = name->hash_alg;
5364 aname->versioncompat = 1; /* SameMachine (default) */
5365 aname->processor_architecture = name->arch;
5367 if (by_default_version) {
5368 MonoObject *version;
5370 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5371 return_if_nok (error);
5373 MONO_OBJECT_SETREF (aname, version, version);
5377 if (absolute != NULL && *absolute != '\0') {
5378 const gchar *prepend = "file://";
5381 codebase = g_strdup (absolute);
5386 for (i = strlen (codebase) - 1; i >= 0; i--)
5387 if (codebase [i] == '\\')
5390 if (*codebase == '/' && *(codebase + 1) == '/') {
5393 prepend = "file:///";
5397 result = g_strconcat (prepend, codebase, NULL);
5403 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5407 if (!create_culture) {
5408 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5409 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5410 g_assert (create_culture);
5411 mono_method_desc_free (desc);
5414 if (name->culture) {
5415 args [0] = mono_string_new (domain, name->culture);
5416 args [1] = &assembly_ref;
5418 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5419 return_if_nok (error);
5421 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5424 if (name->public_key) {
5425 pkey_ptr = (char*)name->public_key;
5426 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5428 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5429 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5430 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5431 } else if (default_publickey) {
5432 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5433 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5436 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5437 if (name->public_key_token [0]) {
5441 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5442 p = mono_array_addr (aname->keyToken, char, 0);
5444 for (i = 0, j = 0; i < 8; i++) {
5445 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5446 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5449 } else if (default_token) {
5450 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5454 ICALL_EXPORT MonoString *
5455 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5457 MonoDomain *domain = mono_object_domain (assembly);
5458 MonoAssembly *mass = assembly->assembly;
5462 name = mono_stringify_assembly_name (&mass->aname);
5463 res = mono_string_new (domain, name);
5470 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5474 MonoAssembly *mass = assembly->assembly;
5476 if (g_path_is_absolute (mass->image->name)) {
5477 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5478 mono_error_set_pending_exception (&error);
5481 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5483 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5484 mono_error_set_pending_exception (&error);
5490 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5494 MonoImageOpenStatus status = MONO_IMAGE_OK;
5497 MonoAssemblyName name;
5500 filename = mono_string_to_utf8 (fname);
5502 dirname = g_path_get_dirname (filename);
5503 replace_shadow_path (mono_domain_get (), dirname, &filename);
5506 image = mono_image_open (filename, &status);
5512 if (status == MONO_IMAGE_IMAGE_INVALID)
5513 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5515 exc = mono_get_exception_file_not_found2 (NULL, fname);
5516 mono_set_pending_exception (exc);
5520 res = mono_assembly_fill_assembly_name (image, &name);
5522 mono_image_close (image);
5524 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5528 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5529 mono_error_set_pending_exception (&error);
5531 mono_image_close (image);
5535 ICALL_EXPORT MonoBoolean
5536 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5537 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5539 MonoBoolean result = FALSE;
5540 MonoDeclSecurityEntry entry;
5542 /* SecurityAction.RequestMinimum */
5543 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5544 *minimum = entry.blob;
5545 *minLength = entry.size;
5548 /* SecurityAction.RequestOptional */
5549 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5550 *optional = entry.blob;
5551 *optLength = entry.size;
5554 /* SecurityAction.RequestRefuse */
5555 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5556 *refused = entry.blob;
5557 *refLength = entry.size;
5565 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5567 guint32 attrs, visibility;
5569 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5570 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5571 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5574 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5580 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5582 MonoReflectionType *rt;
5585 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5588 mono_error_init (error);
5590 /* we start the count from 1 because we skip the special type <Module> */
5593 for (i = 1; i < tdef->rows; ++i) {
5594 if (mono_module_type_is_visible (tdef, image, i + 1))
5598 count = tdef->rows - 1;
5600 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5601 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5603 for (i = 1; i < tdef->rows; ++i) {
5604 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5605 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5606 mono_loader_assert_no_error (); /* Plug any leaks */
5609 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5610 return_val_if_nok (error, NULL);
5612 mono_array_setref (res, count, rt);
5614 MonoException *ex = mono_error_convert_to_exception (error);
5615 mono_array_setref (*exceptions, count, ex);
5624 ICALL_EXPORT MonoArray*
5625 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5628 MonoArray *res = NULL;
5629 MonoArray *exceptions = NULL;
5630 MonoImage *image = NULL;
5631 MonoTableInfo *table = NULL;
5634 int i, len, ex_count;
5636 domain = mono_object_domain (assembly);
5638 g_assert (!assembly_is_dynamic (assembly->assembly));
5639 image = assembly->assembly->image;
5640 table = &image->tables [MONO_TABLE_FILE];
5641 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5642 if (mono_error_set_pending_exception (&error))
5645 /* Append data from all modules in the assembly */
5646 for (i = 0; i < table->rows; ++i) {
5647 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5648 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5653 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5654 if (mono_error_set_pending_exception (&error))
5658 /* Append the new types to the end of the array */
5659 if (mono_array_length (res2) > 0) {
5661 MonoArray *res3, *ex3;
5663 len1 = mono_array_length (res);
5664 len2 = mono_array_length (res2);
5666 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5667 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5668 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5671 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5672 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5673 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5680 /* the ReflectionTypeLoadException must have all the types (Types property),
5681 * NULL replacing types which throws an exception. The LoaderException must
5682 * contain all exceptions for NULL items.
5685 len = mono_array_length (res);
5688 for (i = 0; i < len; i++) {
5689 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5693 klass = mono_type_get_class (t->type);
5694 if ((klass != NULL) && mono_class_has_failure (klass)) {
5695 /* keep the class in the list */
5696 list = g_list_append (list, klass);
5697 /* and replace Type with NULL */
5698 mono_array_setref (res, i, NULL);
5705 if (list || ex_count) {
5707 MonoException *exc = NULL;
5708 MonoArray *exl = NULL;
5709 int j, length = g_list_length (list) + ex_count;
5711 mono_loader_clear_error ();
5713 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5714 /* Types for which mono_class_get_checked () succeeded */
5715 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5716 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5717 mono_array_setref (exl, i, exc);
5719 /* Types for which it don't */
5720 for (j = 0; j < mono_array_length (exceptions); ++j) {
5721 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5723 g_assert (i < length);
5724 mono_array_setref (exl, i, exc);
5731 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5732 if (!is_ok (&error)) {
5733 mono_error_set_pending_exception (&error);
5736 mono_loader_clear_error ();
5737 mono_set_pending_exception (exc);
5744 ICALL_EXPORT gboolean
5745 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5748 MonoAssemblyName aname;
5749 MonoDomain *domain = mono_object_domain (name);
5751 gboolean is_version_defined;
5752 gboolean is_token_defined;
5754 aname.public_key = NULL;
5755 val = mono_string_to_utf8 (assname);
5756 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5757 g_free ((guint8*) aname.public_key);
5762 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5763 mono_error_set_pending_exception (&error);
5765 mono_assembly_name_free (&aname);
5766 g_free ((guint8*) aname.public_key);
5772 ICALL_EXPORT MonoReflectionType*
5773 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5776 MonoReflectionType *ret;
5777 MonoDomain *domain = mono_object_domain (module);
5780 g_assert (module->image);
5782 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5783 /* These images do not have a global type */
5786 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5787 if (!mono_error_ok (&error)) {
5788 mono_error_set_pending_exception (&error);
5792 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5793 if (!mono_error_ok (&error)) {
5794 mono_error_set_pending_exception (&error);
5802 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5804 /*if (module->image)
5805 mono_image_close (module->image);*/
5808 ICALL_EXPORT MonoString*
5809 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5811 MonoDomain *domain = mono_object_domain (module);
5813 g_assert (module->image);
5814 return mono_string_new (domain, module->image->guid);
5817 ICALL_EXPORT gpointer
5818 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5821 if (module->image && module->image->is_module_handle)
5822 return module->image->raw_data;
5825 return (gpointer) (-1);
5829 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5831 if (image_is_dynamic (image)) {
5832 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5833 *pe_kind = dyn->pe_kind;
5834 *machine = dyn->machine;
5837 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5838 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5843 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5845 return (image->md_version_major << 16) | (image->md_version_minor);
5848 ICALL_EXPORT MonoArray*
5849 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5852 MonoArray *exceptions;
5856 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5860 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5861 if (mono_error_set_pending_exception (&error))
5864 for (i = 0; i < mono_array_length (exceptions); ++i) {
5865 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5867 mono_set_pending_exception (ex);
5876 mono_memberref_is_method (MonoImage *image, guint32 token)
5878 if (!image_is_dynamic (image)) {
5879 guint32 cols [MONO_MEMBERREF_SIZE];
5881 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5882 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5883 mono_metadata_decode_blob_size (sig, &sig);
5884 return (*sig != 0x6);
5887 MonoClass *handle_class;
5889 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5890 mono_error_cleanup (&error); /* just probing, ignore error */
5894 return mono_defaults.methodhandle_class == handle_class;
5899 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5902 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5903 mono_array_addr (type_args, MonoType*, 0));
5905 context->class_inst = NULL;
5907 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5908 mono_array_addr (method_args, MonoType*, 0));
5910 context->method_inst = NULL;
5913 ICALL_EXPORT MonoType*
5914 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5917 int table = mono_metadata_token_table (token);
5918 int index = mono_metadata_token_index (token);
5919 MonoGenericContext context;
5922 *resolve_error = ResolveTokenError_Other;
5924 /* Validate token */
5925 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5926 (table != MONO_TABLE_TYPESPEC)) {
5927 *resolve_error = ResolveTokenError_BadTable;
5931 if (image_is_dynamic (image)) {
5932 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5933 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5934 mono_error_cleanup (&error);
5935 return klass ? &klass->byval_arg : NULL;
5938 init_generic_context_from_args (&context, type_args, method_args);
5939 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5940 mono_error_cleanup (&error);
5941 return klass ? &klass->byval_arg : NULL;
5944 if ((index <= 0) || (index > image->tables [table].rows)) {
5945 *resolve_error = ResolveTokenError_OutOfRange;
5949 init_generic_context_from_args (&context, type_args, method_args);
5950 klass = mono_class_get_checked (image, token, &error);
5952 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5953 if (!mono_error_ok (&error)) {
5954 mono_error_set_pending_exception (&error);
5959 return &klass->byval_arg;
5964 ICALL_EXPORT MonoMethod*
5965 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5968 int table = mono_metadata_token_table (token);
5969 int index = mono_metadata_token_index (token);
5970 MonoGenericContext context;
5973 *resolve_error = ResolveTokenError_Other;
5975 /* Validate token */
5976 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5977 (table != MONO_TABLE_MEMBERREF)) {
5978 *resolve_error = ResolveTokenError_BadTable;
5982 if (image_is_dynamic (image)) {
5983 if (table == MONO_TABLE_METHOD) {
5984 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5985 mono_error_cleanup (&error);
5989 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5990 *resolve_error = ResolveTokenError_BadTable;
5994 init_generic_context_from_args (&context, type_args, method_args);
5995 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5996 mono_error_cleanup (&error);
6000 if ((index <= 0) || (index > image->tables [table].rows)) {
6001 *resolve_error = ResolveTokenError_OutOfRange;
6004 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6005 *resolve_error = ResolveTokenError_BadTable;
6009 init_generic_context_from_args (&context, type_args, method_args);
6010 method = mono_get_method_checked (image, token, NULL, &context, &error);
6011 mono_error_set_pending_exception (&error);
6016 ICALL_EXPORT MonoString*
6017 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6020 int index = mono_metadata_token_index (token);
6022 *resolve_error = ResolveTokenError_Other;
6024 /* Validate token */
6025 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6026 *resolve_error = ResolveTokenError_BadTable;
6030 if (image_is_dynamic (image)) {
6031 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6032 mono_error_cleanup (&error);
6036 if ((index <= 0) || (index >= image->heap_us.size)) {
6037 *resolve_error = ResolveTokenError_OutOfRange;
6041 /* FIXME: What to do if the index points into the middle of a string ? */
6043 return mono_ldstr (mono_domain_get (), image, index);
6046 ICALL_EXPORT MonoClassField*
6047 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6051 int table = mono_metadata_token_table (token);
6052 int index = mono_metadata_token_index (token);
6053 MonoGenericContext context;
6054 MonoClassField *field;
6056 *resolve_error = ResolveTokenError_Other;
6058 /* Validate token */
6059 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6060 *resolve_error = ResolveTokenError_BadTable;
6064 if (image_is_dynamic (image)) {
6065 if (table == MONO_TABLE_FIELD) {
6066 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6067 mono_error_cleanup (&error);
6071 if (mono_memberref_is_method (image, token)) {
6072 *resolve_error = ResolveTokenError_BadTable;
6076 init_generic_context_from_args (&context, type_args, method_args);
6077 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6078 mono_error_cleanup (&error);
6082 if ((index <= 0) || (index > image->tables [table].rows)) {
6083 *resolve_error = ResolveTokenError_OutOfRange;
6086 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6087 *resolve_error = ResolveTokenError_BadTable;
6091 init_generic_context_from_args (&context, type_args, method_args);
6092 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6093 mono_error_set_pending_exception (&error);
6099 ICALL_EXPORT MonoObject*
6100 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6104 int table = mono_metadata_token_table (token);
6106 *error = ResolveTokenError_Other;
6109 case MONO_TABLE_TYPEDEF:
6110 case MONO_TABLE_TYPEREF:
6111 case MONO_TABLE_TYPESPEC: {
6112 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6114 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6115 mono_error_set_pending_exception (&merror);
6122 case MONO_TABLE_METHOD:
6123 case MONO_TABLE_METHODSPEC: {
6124 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6126 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6127 mono_error_set_pending_exception (&merror);
6133 case MONO_TABLE_FIELD: {
6134 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6136 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6137 mono_error_set_pending_exception (&merror);
6143 case MONO_TABLE_MEMBERREF:
6144 if (mono_memberref_is_method (image, token)) {
6145 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6147 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6148 mono_error_set_pending_exception (&merror);
6155 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6157 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6158 mono_error_set_pending_exception (&merror);
6167 *error = ResolveTokenError_BadTable;
6173 ICALL_EXPORT MonoArray*
6174 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
6176 int table = mono_metadata_token_table (token);
6177 int idx = mono_metadata_token_index (token);
6178 MonoTableInfo *tables = image->tables;
6183 *error = ResolveTokenError_OutOfRange;
6185 /* FIXME: Support other tables ? */
6186 if (table != MONO_TABLE_STANDALONESIG)
6189 if (image_is_dynamic (image))
6192 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6195 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6197 ptr = mono_metadata_blob_heap (image, sig);
6198 len = mono_metadata_decode_blob_size (ptr, &ptr);
6200 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
6201 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6205 ICALL_EXPORT MonoReflectionType*
6206 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6209 MonoReflectionType *ret;
6211 int isbyref = 0, rank;
6212 char *str = mono_string_to_utf8 (smodifiers);
6215 klass = mono_class_from_mono_type (tb->type.type);
6217 /* logic taken from mono_reflection_parse_type(): keep in sync */
6221 if (isbyref) { /* only one level allowed by the spec */
6230 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6231 mono_error_set_pending_exception (&error);
6235 klass = mono_ptr_class_get (&klass->byval_arg);
6236 mono_class_init (klass);
6247 else if (*p != '*') { /* '*' means unknown lower bound */
6258 klass = mono_array_class_get (klass, rank);
6259 mono_class_init (klass);
6268 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6269 mono_error_set_pending_exception (&error);
6274 ICALL_EXPORT MonoBoolean
6275 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6281 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6287 check_for_invalid_type (MonoClass *klass, MonoError *error)
6292 mono_error_init (error);
6294 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6297 name = mono_type_get_full_name (klass);
6298 str = mono_string_new (mono_domain_get (), name);
6300 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6303 ICALL_EXPORT MonoReflectionType *
6304 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6307 MonoReflectionType *ret;
6308 MonoClass *klass, *aklass;
6310 klass = mono_class_from_mono_type (type->type);
6311 check_for_invalid_type (klass, &error);
6312 mono_error_set_pending_exception (&error);
6314 if (rank == 0) //single dimentional array
6315 aklass = mono_array_class_get (klass, 1);
6317 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6319 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6320 mono_error_set_pending_exception (&error);
6325 ICALL_EXPORT MonoReflectionType *
6326 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6329 MonoReflectionType *ret;
6332 klass = mono_class_from_mono_type (type->type);
6333 mono_class_init_checked (klass, &error);
6334 if (mono_error_set_pending_exception (&error))
6337 check_for_invalid_type (klass, &error);
6338 if (mono_error_set_pending_exception (&error))
6341 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6342 mono_error_set_pending_exception (&error);
6347 ICALL_EXPORT MonoReflectionType *
6348 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6351 MonoReflectionType *ret;
6352 MonoClass *klass, *pklass;
6354 klass = mono_class_from_mono_type (type->type);
6355 mono_class_init_checked (klass, &error);
6356 if (mono_error_set_pending_exception (&error))
6358 check_for_invalid_type (klass, &error);
6359 if (mono_error_set_pending_exception (&error))
6362 pklass = mono_ptr_class_get (type->type);
6364 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6365 mono_error_set_pending_exception (&error);
6370 ICALL_EXPORT MonoObject *
6371 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6372 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6375 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6376 MonoObject *delegate;
6378 MonoMethod *method = info->method;
6380 mono_class_init_checked (delegate_class, &error);
6381 if (mono_error_set_pending_exception (&error))
6384 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6385 /* FIXME improve this exception message */
6386 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6388 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6389 mono_error_set_pending_exception (&error);
6393 if (mono_security_core_clr_enabled ()) {
6394 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6395 if (throwOnBindFailure)
6396 mono_error_set_pending_exception (&error);
6398 mono_error_cleanup (&error);
6403 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6404 if (mono_error_set_pending_exception (&error))
6407 if (method_is_dynamic (method)) {
6408 /* Creating a trampoline would leak memory */
6409 func = mono_compile_method (method);
6411 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6412 method = mono_object_get_virtual_method (target, method);
6413 func = mono_create_ftnptr (mono_domain_get (),
6414 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6417 mono_delegate_ctor_with_method (delegate, target, func, method);
6422 ICALL_EXPORT MonoMulticastDelegate *
6423 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6426 MonoMulticastDelegate *ret;
6428 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6430 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6431 if (mono_error_set_pending_exception (&error))
6434 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6439 ICALL_EXPORT MonoReflectionMethod*
6440 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6442 MonoReflectionMethod *ret = NULL;
6444 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6445 mono_error_set_pending_exception (&error);
6451 static inline gint32
6452 mono_array_get_byte_length (MonoArray *array)
6458 klass = array->obj.vtable->klass;
6460 if (array->bounds == NULL)
6461 length = array->max_length;
6464 for (i = 0; i < klass->rank; ++ i)
6465 length *= array->bounds [i].length;
6468 switch (klass->element_class->byval_arg.type) {
6471 case MONO_TYPE_BOOLEAN:
6475 case MONO_TYPE_CHAR:
6483 return length * sizeof (gpointer);
6494 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6496 return mono_array_get_byte_length (array);
6500 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6502 return mono_array_get (array, gint8, idx);
6506 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6508 mono_array_set (array, gint8, idx, value);
6511 ICALL_EXPORT MonoBoolean
6512 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6514 guint8 *src_buf, *dest_buf;
6517 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6521 g_assert (count >= 0);
6523 /* This is called directly from the class libraries without going through the managed wrapper */
6524 MONO_CHECK_ARG_NULL (src, FALSE);
6525 MONO_CHECK_ARG_NULL (dest, FALSE);
6527 /* watch out for integer overflow */
6528 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6531 src_buf = (guint8 *)src->vector + src_offset;
6532 dest_buf = (guint8 *)dest->vector + dest_offset;
6535 memcpy (dest_buf, src_buf, count);
6537 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6542 #ifndef DISABLE_REMOTING
6543 ICALL_EXPORT MonoObject *
6544 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6547 MonoDomain *domain = mono_object_domain (this_obj);
6549 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6550 MonoTransparentProxy *tp;
6554 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6555 if (mono_error_set_pending_exception (&error))
6558 tp = (MonoTransparentProxy*) res;
6560 MONO_OBJECT_SETREF (tp, rp, rp);
6561 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6562 klass = mono_class_from_mono_type (type);
6564 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6565 mono_class_setup_vtable (klass);
6566 if (mono_class_has_failure (klass)) {
6567 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6571 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6572 if (!is_ok (&error)) {
6573 mono_error_set_pending_exception (&error);
6576 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6577 if (!is_ok (&error)) {
6578 mono_error_set_pending_exception (&error);
6582 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6586 ICALL_EXPORT MonoReflectionType *
6587 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6590 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6591 mono_error_set_pending_exception (&error);
6597 /* System.Environment */
6600 ves_icall_System_Environment_get_UserName (void)
6602 /* using glib is more portable */
6603 return mono_string_new (mono_domain_get (), g_get_user_name ());
6607 ICALL_EXPORT MonoString *
6608 ves_icall_System_Environment_get_MachineName (void)
6610 #if defined (HOST_WIN32)
6615 len = MAX_COMPUTERNAME_LENGTH + 1;
6616 buf = g_new (gunichar2, len);
6619 if (GetComputerName (buf, (PDWORD) &len)) {
6621 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6622 mono_error_set_pending_exception (&error);
6627 #elif !defined(DISABLE_SOCKETS)
6631 #if defined _SC_HOST_NAME_MAX
6632 n = sysconf (_SC_HOST_NAME_MAX);
6636 buf = g_malloc (n+1);
6638 if (gethostname (buf, n) == 0){
6640 result = mono_string_new (mono_domain_get (), buf);
6647 return mono_string_new (mono_domain_get (), "mono");
6652 ves_icall_System_Environment_get_Platform (void)
6654 #if defined (TARGET_WIN32)
6657 #elif defined(__MACH__)
6660 // Notice that the value is hidden from user code, and only exposed
6661 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6662 // define and making assumptions based on Unix/128/4 values before there
6663 // was a MacOS define. Lots of code would assume that not-Unix meant
6664 // Windows, but in this case, it would be OSX.
6673 ICALL_EXPORT MonoString *
6674 ves_icall_System_Environment_get_NewLine (void)
6676 #if defined (HOST_WIN32)
6677 return mono_string_new (mono_domain_get (), "\r\n");
6679 return mono_string_new (mono_domain_get (), "\n");
6683 ICALL_EXPORT MonoBoolean
6684 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6686 #if SIZEOF_VOID_P == 8
6690 gboolean isWow64Process = FALSE;
6691 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6692 return (MonoBoolean)isWow64Process;
6694 #elif defined(HAVE_SYS_UTSNAME_H)
6695 struct utsname name;
6697 if (uname (&name) >= 0) {
6698 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6705 ICALL_EXPORT MonoString *
6706 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6714 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6715 value = g_getenv (utf8_name);
6722 return mono_string_new (mono_domain_get (), value);
6726 * There is no standard way to get at environ.
6729 #ifndef __MINGW32_VERSION
6730 #if defined(__APPLE__)
6731 #if defined (TARGET_OSX)
6732 /* Apple defines this in crt_externs.h but doesn't provide that header for
6733 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6734 * in fact exist on all implementations (so far)
6736 gchar ***_NSGetEnviron(void);
6737 #define environ (*_NSGetEnviron())
6739 static char *mono_environ[1] = { NULL };
6740 #define environ mono_environ
6741 #endif /* defined (TARGET_OSX) */
6749 ICALL_EXPORT MonoArray *
6750 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6761 env_strings = GetEnvironmentStrings();
6764 env_string = env_strings;
6765 while (*env_string != '\0') {
6766 /* weird case that MS seems to skip */
6767 if (*env_string != '=')
6769 while (*env_string != '\0')
6775 domain = mono_domain_get ();
6776 names = mono_array_new (domain, mono_defaults.string_class, n);
6780 env_string = env_strings;
6781 while (*env_string != '\0') {
6782 /* weird case that MS seems to skip */
6783 if (*env_string != '=') {
6784 equal_str = wcschr(env_string, '=');
6785 g_assert(equal_str);
6787 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6788 if (mono_error_set_pending_exception (&error))
6791 mono_array_setref (names, n, str);
6794 while (*env_string != '\0')
6799 FreeEnvironmentStrings (env_strings);
6812 for (e = environ; *e != 0; ++ e)
6815 domain = mono_domain_get ();
6816 names = mono_array_new (domain, mono_defaults.string_class, n);
6819 for (e = environ; *e != 0; ++ e) {
6820 parts = g_strsplit (*e, "=", 2);
6822 str = mono_string_new (domain, *parts);
6823 mono_array_setref (names, n, str);
6836 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6838 #if !GLIB_CHECK_VERSION(2,4,0)
6839 #define g_setenv(a,b,c) setenv(a,b,c)
6840 #define g_unsetenv(a) unsetenv(a)
6844 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6847 gunichar2 *utf16_name, *utf16_value;
6849 gchar *utf8_name, *utf8_value;
6854 utf16_name = mono_string_to_utf16 (name);
6855 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6856 SetEnvironmentVariable (utf16_name, NULL);
6857 g_free (utf16_name);
6861 utf16_value = mono_string_to_utf16 (value);
6863 SetEnvironmentVariable (utf16_name, utf16_value);
6865 g_free (utf16_name);
6866 g_free (utf16_value);
6868 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6870 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6871 g_unsetenv (utf8_name);
6876 utf8_value = mono_string_to_utf8_checked (value, &error);
6877 if (!mono_error_ok (&error)) {
6879 mono_error_set_pending_exception (&error);
6882 g_setenv (utf8_name, utf8_value, TRUE);
6885 g_free (utf8_value);
6890 ves_icall_System_Environment_Exit (int result)
6892 mono_environment_exitcode_set (result);
6894 /* FIXME: There are some cleanup hangs that should be worked out, but
6895 * if the program is going to exit, everything will be cleaned up when
6896 * NaCl exits anyway.
6898 #ifndef __native_client__
6899 if (!mono_runtime_try_shutdown ())
6900 mono_thread_exit ();
6902 /* Suspend all managed threads since the runtime is going away */
6903 mono_thread_suspend_all_other_threads ();
6905 mono_runtime_quit ();
6908 /* we may need to do some cleanup here... */
6912 ICALL_EXPORT MonoString*
6913 ves_icall_System_Environment_GetGacPath (void)
6915 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6918 ICALL_EXPORT MonoString*
6919 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6921 #if defined (HOST_WIN32)
6922 #ifndef CSIDL_FLAG_CREATE
6923 #define CSIDL_FLAG_CREATE 0x8000
6926 WCHAR path [MAX_PATH];
6927 /* Create directory if no existing */
6928 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6933 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6934 mono_error_set_pending_exception (&error);
6938 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6940 return mono_string_new (mono_domain_get (), "");
6943 ICALL_EXPORT MonoArray *
6944 ves_icall_System_Environment_GetLogicalDrives (void)
6947 gunichar2 buf [256], *ptr, *dname;
6949 guint initial_size = 127, size = 128;
6952 MonoString *drivestr;
6953 MonoDomain *domain = mono_domain_get ();
6959 while (size > initial_size) {
6960 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6961 if (size > initial_size) {
6964 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6965 initial_size = size;
6979 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6984 while (*u16) { u16++; len ++; }
6985 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6986 if (mono_error_set_pending_exception (&error))
6989 mono_array_setref (result, ndrives++, drivestr);
6999 ICALL_EXPORT MonoString *
7000 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7002 gunichar2 volume_name [MAX_PATH + 1];
7004 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7006 return mono_string_from_utf16 (volume_name);
7009 ICALL_EXPORT MonoString *
7010 ves_icall_System_Environment_InternalGetHome (void)
7012 return mono_string_new (mono_domain_get (), g_get_home_dir ());
7015 static const char *encodings [] = {
7017 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7018 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7019 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7021 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7022 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7023 "x_unicode_2_0_utf_7",
7025 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7026 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7028 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7031 "unicodefffe", "utf_16be",
7038 * Returns the internal codepage, if the value of "int_code_page" is
7039 * 1 at entry, and we can not compute a suitable code page number,
7040 * returns the code page as a string
7042 ICALL_EXPORT MonoString*
7043 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
7048 char *codepage = NULL;
7050 int want_name = *int_code_page;
7053 *int_code_page = -1;
7055 g_get_charset (&cset);
7056 c = codepage = strdup (cset);
7057 for (c = codepage; *c; c++){
7058 if (isascii (*c) && isalpha (*c))
7063 /* g_print ("charset: %s\n", cset); */
7065 /* handle some common aliases */
7068 for (i = 0; p != 0; ){
7071 p = encodings [++i];
7074 if (strcmp (p, codepage) == 0){
7075 *int_code_page = code;
7078 p = encodings [++i];
7081 if (strstr (codepage, "utf_8") != NULL)
7082 *int_code_page |= 0x10000000;
7085 if (want_name && *int_code_page == -1)
7086 return mono_string_new (mono_domain_get (), cset);
7091 ICALL_EXPORT MonoBoolean
7092 ves_icall_System_Environment_get_HasShutdownStarted (void)
7094 if (mono_runtime_is_shutting_down ())
7097 if (mono_domain_is_unloading (mono_domain_get ()))
7104 ves_icall_System_Environment_BroadcastSettingChange (void)
7107 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7112 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7118 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
7119 MonoReflectionMethod *method,
7120 MonoArray *out_args)
7122 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
7125 #ifndef DISABLE_REMOTING
7126 ICALL_EXPORT MonoBoolean
7127 ves_icall_IsTransparentProxy (MonoObject *proxy)
7132 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7138 ICALL_EXPORT MonoReflectionMethod *
7139 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7140 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7142 MonoReflectionMethod *ret = NULL;
7147 MonoMethod **vtable;
7148 MonoMethod *res = NULL;
7150 MONO_CHECK_ARG_NULL (rtype, NULL);
7151 MONO_CHECK_ARG_NULL (rmethod, NULL);
7153 method = rmethod->method;
7154 klass = mono_class_from_mono_type (rtype->type);
7155 mono_class_init_checked (klass, &error);
7156 if (mono_error_set_pending_exception (&error))
7159 if (MONO_CLASS_IS_INTERFACE (klass))
7162 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7165 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7166 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7172 mono_class_setup_vtable (klass);
7173 vtable = klass->vtable;
7175 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7176 gboolean variance_used = FALSE;
7177 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7178 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7180 res = vtable [offs + method->slot];
7182 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7185 if (method->slot != -1)
7186 res = vtable [method->slot];
7192 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7193 mono_error_set_pending_exception (&error);
7198 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7204 klass = mono_class_from_mono_type (type->type);
7205 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7206 if (!is_ok (&error)) {
7207 mono_error_set_pending_exception (&error);
7211 mono_vtable_set_is_remote (vtable, enable);
7214 #else /* DISABLE_REMOTING */
7217 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7219 g_assert_not_reached ();
7224 ICALL_EXPORT MonoObject *
7225 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7232 domain = mono_object_domain (type);
7233 klass = mono_class_from_mono_type (type->type);
7234 mono_class_init_checked (klass, &error);
7235 if (mono_error_set_pending_exception (&error))
7238 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7239 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7243 if (klass->rank >= 1) {
7244 g_assert (klass->rank == 1);
7245 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7247 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7248 if (!is_ok (&error)) {
7249 mono_error_set_pending_exception (&error);
7252 /* Bypass remoting object creation check */
7253 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7254 mono_error_set_pending_exception (&error);
7260 ICALL_EXPORT MonoString *
7261 ves_icall_System_IO_get_temp_path (void)
7263 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7266 #ifndef PLATFORM_NO_DRIVEINFO
7267 ICALL_EXPORT MonoBoolean
7268 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7269 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7273 ULARGE_INTEGER wapi_free_bytes_avail;
7274 ULARGE_INTEGER wapi_total_number_of_bytes;
7275 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7277 *error = ERROR_SUCCESS;
7278 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7279 &wapi_total_number_of_free_bytes);
7282 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7283 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7284 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7286 *free_bytes_avail = 0;
7287 *total_number_of_bytes = 0;
7288 *total_number_of_free_bytes = 0;
7289 *error = GetLastError ();
7295 ICALL_EXPORT guint32
7296 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7298 return GetDriveType (mono_string_chars (root_path_name));
7302 ICALL_EXPORT gpointer
7303 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7305 return mono_compile_method (method);
7308 ICALL_EXPORT MonoString *
7309 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7314 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7316 #if defined (HOST_WIN32)
7317 /* Avoid mixing '/' and '\\' */
7320 for (i = strlen (path) - 1; i >= 0; i--)
7321 if (path [i] == '/')
7325 mcpath = mono_string_new (mono_domain_get (), path);
7332 get_bundled_app_config (void)
7334 const gchar *app_config;
7337 gchar *config_file_name, *config_file_path;
7338 gsize len, config_file_path_length, config_ext_length;
7341 domain = mono_domain_get ();
7342 file = domain->setup->configuration_file;
7343 if (!file || file->length == 0)
7346 // Retrieve config file and remove the extension
7347 config_file_name = mono_string_to_utf8 (file);
7348 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7349 if (!config_file_path)
7350 config_file_path = config_file_name;
7352 config_file_path_length = strlen (config_file_path);
7353 config_ext_length = strlen (".config");
7354 if (config_file_path_length <= config_ext_length)
7357 len = config_file_path_length - config_ext_length;
7358 module = (gchar *)g_malloc0 (len + 1);
7359 memcpy (module, config_file_path, len);
7360 // Get the config file from the module name
7361 app_config = mono_config_string_for_assembly_file (module);
7364 if (config_file_name != config_file_path)
7365 g_free (config_file_name);
7366 g_free (config_file_path);
7371 return mono_string_new (mono_domain_get (), app_config);
7375 get_bundled_machine_config (void)
7377 const gchar *machine_config;
7379 machine_config = mono_get_machine_config ();
7381 if (!machine_config)
7384 return mono_string_new (mono_domain_get (), machine_config);
7387 ICALL_EXPORT MonoString *
7388 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7393 path = g_path_get_dirname (mono_get_config_dir ());
7395 #if defined (HOST_WIN32)
7396 /* Avoid mixing '/' and '\\' */
7399 for (i = strlen (path) - 1; i >= 0; i--)
7400 if (path [i] == '/')
7404 ipath = mono_string_new (mono_domain_get (), path);
7410 ICALL_EXPORT gboolean
7411 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7413 MonoPEResourceDataEntry *entry;
7416 if (!assembly || !result || !size)
7421 image = assembly->assembly->image;
7422 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7426 *result = mono_image_rva_map (image, entry->rde_data_offset);
7431 *size = entry->rde_size;
7436 ICALL_EXPORT MonoBoolean
7437 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7439 return mono_is_debugger_attached ();
7442 ICALL_EXPORT MonoBoolean
7443 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7445 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7446 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7452 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7454 if (mono_get_runtime_callbacks ()->debug_log)
7455 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7459 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7461 #if defined (HOST_WIN32)
7462 OutputDebugString (mono_string_chars (message));
7464 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7468 /* Only used for value types */
7469 ICALL_EXPORT MonoObject *
7470 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7477 domain = mono_object_domain (type);
7478 klass = mono_class_from_mono_type (type->type);
7479 mono_class_init_checked (klass, &error);
7480 if (mono_error_set_pending_exception (&error))
7483 if (mono_class_is_nullable (klass))
7484 /* No arguments -> null */
7487 result = mono_object_new_checked (domain, klass, &error);
7488 mono_error_set_pending_exception (&error);
7492 ICALL_EXPORT MonoReflectionMethod *
7493 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7495 MonoReflectionMethod *ret = NULL;
7498 MonoClass *klass, *parent;
7499 MonoGenericContext *generic_inst = NULL;
7500 MonoMethod *method = m->method;
7501 MonoMethod *result = NULL;
7504 if (method->klass == NULL)
7507 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7508 MONO_CLASS_IS_INTERFACE (method->klass) ||
7509 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7512 slot = mono_method_get_vtable_slot (method);
7516 klass = method->klass;
7517 if (klass->generic_class) {
7518 generic_inst = mono_class_get_context (klass);
7519 klass = klass->generic_class->container_class;
7523 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7524 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7525 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7526 or klass is the generic container class and generic_inst is the instantiation.
7528 when we go to the parent, if the parent is an open constructed type, we need to
7529 replace the type parameters by the definitions from the generic_inst, and then take it
7530 apart again into the klass and the generic_inst.
7532 For cases like this:
7533 class C<T> : B<T, int> {
7534 public override void Foo () { ... }
7536 class B<U,V> : A<HashMap<U,V>> {
7537 public override void Foo () { ... }
7540 public virtual void Foo () { ... }
7543 if at each iteration the parent isn't open, we can skip inflating it. if at some
7544 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7547 MonoGenericContext *parent_inst = NULL;
7548 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7549 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7550 if (!mono_error_ok (&error)) {
7551 mono_error_set_pending_exception (&error);
7555 if (parent->generic_class) {
7556 parent_inst = mono_class_get_context (parent);
7557 parent = parent->generic_class->container_class;
7560 mono_class_setup_vtable (parent);
7561 if (parent->vtable_size <= slot)
7564 generic_inst = parent_inst;
7567 klass = klass->parent;
7570 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7571 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7572 if (!mono_error_ok (&error)) {
7573 mono_error_set_pending_exception (&error);
7577 generic_inst = NULL;
7579 if (klass->generic_class) {
7580 generic_inst = mono_class_get_context (klass);
7581 klass = klass->generic_class->container_class;
7587 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7588 if (!mono_error_ok (&error)) {
7589 mono_error_set_pending_exception (&error);
7594 if (klass == method->klass)
7597 /*This is possible if definition == FALSE.
7598 * Do it here to be really sure we don't read invalid memory.
7600 if (slot >= klass->vtable_size)
7603 mono_class_setup_vtable (klass);
7605 result = klass->vtable [slot];
7606 if (result == NULL) {
7607 /* It is an abstract method */
7608 gpointer iter = NULL;
7609 while ((result = mono_class_get_methods (klass, &iter)))
7610 if (result->slot == slot)
7617 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7618 mono_error_set_pending_exception (&error);
7622 ICALL_EXPORT MonoString*
7623 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7625 MonoMethod *method = m->method;
7627 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7632 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7634 iter->sig = *(MonoMethodSignature**)argsp;
7636 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7637 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7640 /* FIXME: it's not documented what start is exactly... */
7644 iter->args = argsp + sizeof (gpointer);
7646 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7648 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7651 ICALL_EXPORT MonoTypedRef
7652 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7654 guint32 i, arg_size;
7658 i = iter->sig->sentinelpos + iter->next_arg;
7660 g_assert (i < iter->sig->param_count);
7662 res.type = iter->sig->params [i];
7663 res.klass = mono_class_from_mono_type (res.type);
7664 arg_size = mono_type_stack_size (res.type, &align);
7665 #if defined(__arm__) || defined(__mips__)
7666 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7668 res.value = iter->args;
7669 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7670 /* Values are stored as 8 byte register sized objects, but 'value'
7671 * is dereferenced as a pointer in other routines.
7673 res.value = (char*)res.value + 4;
7675 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7676 if (arg_size <= sizeof (gpointer)) {
7678 int padding = arg_size - mono_type_size (res.type, &dummy);
7679 res.value = (guint8*)res.value + padding;
7682 iter->args = (char*)iter->args + arg_size;
7685 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7690 ICALL_EXPORT MonoTypedRef
7691 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7693 guint32 i, arg_size;
7697 i = iter->sig->sentinelpos + iter->next_arg;
7699 g_assert (i < iter->sig->param_count);
7701 while (i < iter->sig->param_count) {
7702 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7704 res.type = iter->sig->params [i];
7705 res.klass = mono_class_from_mono_type (res.type);
7706 /* FIXME: endianess issue... */
7707 arg_size = mono_type_stack_size (res.type, &align);
7708 #if defined(__arm__) || defined(__mips__)
7709 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7711 res.value = iter->args;
7712 iter->args = (char*)iter->args + arg_size;
7714 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7717 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7725 ICALL_EXPORT MonoType*
7726 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7730 i = iter->sig->sentinelpos + iter->next_arg;
7732 g_assert (i < iter->sig->param_count);
7734 return iter->sig->params [i];
7737 ICALL_EXPORT MonoObject*
7738 mono_TypedReference_ToObject (MonoTypedRef* tref)
7741 MonoObject *result = NULL;
7742 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7743 MonoObject** objp = (MonoObject **)tref->value;
7747 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7748 mono_error_set_pending_exception (&error);
7752 ICALL_EXPORT MonoTypedRef
7753 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7756 MonoReflectionField *f;
7758 MonoType *ftype = NULL;
7762 memset (&res, 0, sizeof (res));
7765 g_assert (mono_array_length (fields) > 0);
7767 klass = target->vtable->klass;
7769 for (i = 0; i < mono_array_length (fields); ++i) {
7770 f = mono_array_get (fields, MonoReflectionField*, i);
7772 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7775 if (f->field->parent != klass) {
7776 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7780 p = (guint8*)target + f->field->offset;
7782 p += f->field->offset - sizeof (MonoObject);
7783 klass = mono_class_from_mono_type (f->field->type);
7784 ftype = f->field->type;
7788 res.klass = mono_class_from_mono_type (ftype);
7795 prelink_method (MonoMethod *method, MonoError *error)
7797 const char *exc_class, *exc_arg;
7799 mono_error_init (error);
7800 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7802 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7804 mono_error_set_exception_instance (error,
7805 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7808 /* create the wrapper, too? */
7812 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7816 prelink_method (method->method, &error);
7817 mono_error_set_pending_exception (&error);
7821 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7824 MonoClass *klass = mono_class_from_mono_type (type->type);
7826 gpointer iter = NULL;
7828 mono_class_init_checked (klass, &error);
7829 if (mono_error_set_pending_exception (&error))
7832 while ((m = mono_class_get_methods (klass, &iter))) {
7833 prelink_method (m, &error);
7834 if (mono_error_set_pending_exception (&error))
7839 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7841 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7842 gint32 const **exponents,
7843 gunichar2 const **digitLowerTable,
7844 gunichar2 const **digitUpperTable,
7845 gint64 const **tenPowersList,
7846 gint32 const **decHexDigits)
7848 *mantissas = Formatter_MantissaBitsTable;
7849 *exponents = Formatter_TensExponentTable;
7850 *digitLowerTable = Formatter_DigitLowerTable;
7851 *digitUpperTable = Formatter_DigitUpperTable;
7852 *tenPowersList = Formatter_TenPowersList;
7853 *decHexDigits = Formatter_DecHexDigits;
7857 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7858 * and avoid useless allocations.
7861 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7863 MonoReflectionType *rt;
7867 mono_error_init (error);
7868 for (i = 0; i < type->num_mods; ++i) {
7869 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7874 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7876 for (i = 0; i < type->num_mods; ++i) {
7877 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7878 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7879 return_val_if_nok (error, NULL);
7881 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7882 return_val_if_nok (error, NULL);
7884 mono_array_setref (res, count, rt);
7891 ICALL_EXPORT MonoArray*
7892 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7895 MonoType *type = param->ClassImpl->type;
7896 MonoClass *member_class = mono_object_class (param->MemberImpl);
7897 MonoMethod *method = NULL;
7900 MonoMethodSignature *sig;
7903 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7904 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7905 method = rmethod->method;
7906 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7907 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7908 if (!(method = prop->property->get))
7909 method = prop->property->set;
7912 char *type_name = mono_type_get_full_name (member_class);
7913 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7914 MonoException *ex = mono_get_exception_not_supported (msg);
7917 mono_set_pending_exception (ex);
7921 image = method->klass->image;
7922 pos = param->PositionImpl;
7923 sig = mono_method_signature (method);
7927 type = sig->params [pos];
7929 res = type_array_from_modifiers (image, type, optional, &error);
7930 mono_error_set_pending_exception (&error);
7935 get_property_type (MonoProperty *prop)
7937 MonoMethodSignature *sig;
7939 sig = mono_method_signature (prop->get);
7941 } else if (prop->set) {
7942 sig = mono_method_signature (prop->set);
7943 return sig->params [sig->param_count - 1];
7948 ICALL_EXPORT MonoArray*
7949 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7952 MonoType *type = get_property_type (property->property);
7953 MonoImage *image = property->klass->image;
7958 res = type_array_from_modifiers (image, type, optional, &error);
7959 mono_error_set_pending_exception (&error);
7964 *Construct a MonoType suited to be used to decode a constant blob object.
7966 * @type is the target type which will be constructed
7967 * @blob_type is the blob type, for example, that comes from the constant table
7968 * @real_type is the expected constructed type.
7971 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7973 type->type = blob_type;
7974 type->data.klass = NULL;
7975 if (blob_type == MONO_TYPE_CLASS)
7976 type->data.klass = mono_defaults.object_class;
7977 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7978 /* For enums, we need to use the base type */
7979 type->type = MONO_TYPE_VALUETYPE;
7980 type->data.klass = mono_class_from_mono_type (real_type);
7982 type->data.klass = mono_class_from_mono_type (real_type);
7985 ICALL_EXPORT MonoObject*
7986 property_info_get_default_value (MonoReflectionProperty *property)
7990 MonoProperty *prop = property->property;
7991 MonoType *type = get_property_type (prop);
7992 MonoDomain *domain = mono_object_domain (property);
7993 MonoTypeEnum def_type;
7994 const char *def_value;
7997 mono_class_init (prop->parent);
7999 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8000 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8004 def_value = mono_class_get_property_default_value (prop, &def_type);
8006 mono_type_from_blob_type (&blob_type, def_type, type);
8007 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8009 mono_error_set_pending_exception (&error);
8013 ICALL_EXPORT MonoBoolean
8014 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8017 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8018 MonoCustomAttrInfo *cinfo;
8021 mono_class_init_checked (attr_class, &error);
8022 if (mono_error_set_pending_exception (&error))
8025 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8026 if (!is_ok (&error)) {
8027 mono_error_set_pending_exception (&error);
8032 found = mono_custom_attrs_has_attr (cinfo, attr_class);
8034 mono_custom_attrs_free (cinfo);
8038 ICALL_EXPORT MonoArray*
8039 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8041 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8046 mono_class_init_checked (attr_class, &error);
8047 if (mono_error_set_pending_exception (&error))
8051 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8052 if (!mono_error_ok (&error)) {
8053 mono_error_set_pending_exception (&error);
8057 if (mono_loader_get_last_error ()) {
8058 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8065 ICALL_EXPORT MonoArray*
8066 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8070 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8071 mono_error_set_pending_exception (&error);
8076 ICALL_EXPORT MonoString*
8077 ves_icall_Mono_Runtime_GetDisplayName (void)
8080 MonoString *display_name;
8082 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8083 display_name = mono_string_new (mono_domain_get (), info);
8085 return display_name;
8088 ICALL_EXPORT MonoString*
8089 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8092 MonoString *message;
8096 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8097 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8100 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8102 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8103 if (mono_error_set_pending_exception (&error))
8110 ICALL_EXPORT gpointer
8111 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8113 return GetCurrentProcess ();
8116 ICALL_EXPORT MonoBoolean
8117 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8119 return GetExitCodeProcess (handle, (guint32*) exitcode);
8122 ICALL_EXPORT MonoBoolean
8123 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8125 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8126 return CloseHandle (handle);
8128 return CloseProcess (handle);
8132 ICALL_EXPORT MonoBoolean
8133 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8135 return TerminateProcess (handle, exitcode);
8139 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8141 return WaitForInputIdle (handle, milliseconds);
8144 ICALL_EXPORT MonoBoolean
8145 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8147 return GetProcessWorkingSetSize (handle, min, max);
8150 ICALL_EXPORT MonoBoolean
8151 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8153 return SetProcessWorkingSetSize (handle, min, max);
8156 ICALL_EXPORT MonoBoolean
8157 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8159 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8163 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8165 return mono_process_current_pid ();
8169 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8171 return GetPriorityClass (handle);
8174 ICALL_EXPORT MonoBoolean
8175 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8177 return SetPriorityClass (handle, priorityClass);
8180 #ifndef DISABLE_ICALL_TABLES
8182 #define ICALL_TYPE(id,name,first)
8183 #define ICALL(id,name,func) Icall_ ## id,
8186 #include "metadata/icall-def.h"
8192 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8193 #define ICALL(id,name,func)
8195 #include "metadata/icall-def.h"
8201 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8202 #define ICALL(id,name,func)
8204 guint16 first_icall;
8207 static const IcallTypeDesc
8208 icall_type_descs [] = {
8209 #include "metadata/icall-def.h"
8213 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8216 #define ICALL_TYPE(id,name,first)
8219 #ifdef HAVE_ARRAY_ELEM_INIT
8220 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8221 #define MSGSTRFIELD1(line) str##line
8223 static const struct msgstrtn_t {
8224 #define ICALL(id,name,func)
8226 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8227 #include "metadata/icall-def.h"
8229 } icall_type_names_str = {
8230 #define ICALL_TYPE(id,name,first) (name),
8231 #include "metadata/icall-def.h"
8234 static const guint16 icall_type_names_idx [] = {
8235 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8236 #include "metadata/icall-def.h"
8239 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8241 static const struct msgstr_t {
8243 #define ICALL_TYPE(id,name,first)
8244 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8245 #include "metadata/icall-def.h"
8247 } icall_names_str = {
8248 #define ICALL(id,name,func) (name),
8249 #include "metadata/icall-def.h"
8252 static const guint16 icall_names_idx [] = {
8253 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8254 #include "metadata/icall-def.h"
8257 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8263 #define ICALL_TYPE(id,name,first) name,
8264 #define ICALL(id,name,func)
8265 static const char* const
8266 icall_type_names [] = {
8267 #include "metadata/icall-def.h"
8271 #define icall_type_name_get(id) (icall_type_names [(id)])
8275 #define ICALL_TYPE(id,name,first)
8276 #define ICALL(id,name,func) name,
8277 static const char* const
8279 #include "metadata/icall-def.h"
8282 #define icall_name_get(id) icall_names [(id)]
8284 #endif /* !HAVE_ARRAY_ELEM_INIT */
8288 #define ICALL_TYPE(id,name,first)
8289 #define ICALL(id,name,func) func,
8290 static const gconstpointer
8291 icall_functions [] = {
8292 #include "metadata/icall-def.h"
8296 #ifdef ENABLE_ICALL_SYMBOL_MAP
8299 #define ICALL_TYPE(id,name,first)
8300 #define ICALL(id,name,func) #func,
8301 static const gconstpointer
8302 icall_symbols [] = {
8303 #include "metadata/icall-def.h"
8308 #endif /* DISABLE_ICALL_TABLES */
8310 static mono_mutex_t icall_mutex;
8311 static GHashTable *icall_hash = NULL;
8312 static GHashTable *jit_icall_hash_name = NULL;
8313 static GHashTable *jit_icall_hash_addr = NULL;
8316 mono_icall_init (void)
8318 #ifndef DISABLE_ICALL_TABLES
8321 /* check that tables are sorted: disable in release */
8324 const char *prev_class = NULL;
8325 const char *prev_method;
8327 for (i = 0; i < Icall_type_num; ++i) {
8328 const IcallTypeDesc *desc;
8331 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8332 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8333 prev_class = icall_type_name_get (i);
8334 desc = &icall_type_descs [i];
8335 num_icalls = icall_desc_num_icalls (desc);
8336 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8337 for (j = 0; j < num_icalls; ++j) {
8338 const char *methodn = icall_name_get (desc->first_icall + j);
8339 if (prev_method && strcmp (prev_method, methodn) >= 0)
8340 g_print ("method %s should come before method %s\n", methodn, prev_method);
8341 prev_method = methodn;
8347 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8348 mono_os_mutex_init (&icall_mutex);
8352 mono_icall_lock (void)
8354 mono_locks_os_acquire (&icall_mutex, IcallLock);
8358 mono_icall_unlock (void)
8360 mono_locks_os_release (&icall_mutex, IcallLock);
8364 mono_icall_cleanup (void)
8366 g_hash_table_destroy (icall_hash);
8367 g_hash_table_destroy (jit_icall_hash_name);
8368 g_hash_table_destroy (jit_icall_hash_addr);
8369 mono_os_mutex_destroy (&icall_mutex);
8373 * mono_add_internal_call:
8374 * @name: method specification to surface to the managed world
8375 * @method: pointer to a C method to invoke when the method is called
8377 * This method surfaces the C function pointed by @method as a method
8378 * that has been surfaced in managed code with the method specified in
8379 * @name as an internal call.
8381 * Internal calls are surfaced to all app domains loaded and they are
8382 * accessibly by a type with the specified name.
8384 * You must provide a fully qualified type name, that is namespaces
8385 * and type name, followed by a colon and the method name, with an
8386 * optional signature to bind.
8388 * For example, the following are all valid declarations:
8390 * "MyApp.Services.ScriptService:Accelerate"
8391 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8393 * You use method parameters in cases where there might be more than
8394 * one surface method to managed code. That way you can register different
8395 * internal calls for different method overloads.
8397 * The internal calls are invoked with no marshalling. This means that .NET
8398 * types like System.String are exposed as `MonoString *` parameters. This is
8399 * different than the way that strings are surfaced in P/Invoke.
8401 * For more information on how the parameters are marshalled, see the
8402 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8405 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8406 * reference for more information on the format of method descriptions.
8409 mono_add_internal_call (const char *name, gconstpointer method)
8413 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8415 mono_icall_unlock ();
8418 #ifndef DISABLE_ICALL_TABLES
8420 #ifdef HAVE_ARRAY_ELEM_INIT
8422 compare_method_imap (const void *key, const void *elem)
8424 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8425 return strcmp (key, method_name);
8429 find_method_icall (const IcallTypeDesc *imap, const char *name)
8431 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);
8434 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8438 compare_class_imap (const void *key, const void *elem)
8440 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8441 return strcmp (key, class_name);
8444 static const IcallTypeDesc*
8445 find_class_icalls (const char *name)
8447 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);
8450 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8453 #else /* HAVE_ARRAY_ELEM_INIT */
8456 compare_method_imap (const void *key, const void *elem)
8458 const char** method_name = (const char**)elem;
8459 return strcmp (key, *method_name);
8463 find_method_icall (const IcallTypeDesc *imap, const char *name)
8465 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8468 return (gpointer)icall_functions [(nameslot - icall_names)];
8472 compare_class_imap (const void *key, const void *elem)
8474 const char** class_name = (const char**)elem;
8475 return strcmp (key, *class_name);
8478 static const IcallTypeDesc*
8479 find_class_icalls (const char *name)
8481 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8484 return &icall_type_descs [nameslot - icall_type_names];
8487 #endif /* HAVE_ARRAY_ELEM_INIT */
8489 #endif /* DISABLE_ICALL_TABLES */
8492 * we should probably export this as an helper (handle nested types).
8493 * Returns the number of chars written in buf.
8496 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8498 int nspacelen, cnamelen;
8499 nspacelen = strlen (klass->name_space);
8500 cnamelen = strlen (klass->name);
8501 if (nspacelen + cnamelen + 2 > bufsize)
8504 memcpy (buf, klass->name_space, nspacelen);
8505 buf [nspacelen ++] = '.';
8507 memcpy (buf + nspacelen, klass->name, cnamelen);
8508 buf [nspacelen + cnamelen] = 0;
8509 return nspacelen + cnamelen;
8512 #ifdef DISABLE_ICALL_TABLES
8514 no_icall_table (void)
8516 g_assert_not_reached ();
8521 mono_lookup_internal_call (MonoMethod *method)
8526 int typelen = 0, mlen, siglen;
8528 #ifndef DISABLE_ICALL_TABLES
8529 const IcallTypeDesc *imap = NULL;
8532 g_assert (method != NULL);
8534 if (method->is_inflated)
8535 method = ((MonoMethodInflated *) method)->declaring;
8537 if (method->klass->nested_in) {
8538 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8542 mname [pos++] = '/';
8545 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8551 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8556 #ifndef DISABLE_ICALL_TABLES
8557 imap = find_class_icalls (mname);
8560 mname [typelen] = ':';
8561 mname [typelen + 1] = ':';
8563 mlen = strlen (method->name);
8564 memcpy (mname + typelen + 2, method->name, mlen);
8565 sigstart = mname + typelen + 2 + mlen;
8568 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8569 siglen = strlen (tmpsig);
8570 if (typelen + mlen + siglen + 6 > sizeof (mname))
8573 memcpy (sigstart + 1, tmpsig, siglen);
8574 sigstart [siglen + 1] = ')';
8575 sigstart [siglen + 2] = 0;
8580 res = g_hash_table_lookup (icall_hash, mname);
8582 mono_icall_unlock ();;
8585 /* try without signature */
8587 res = g_hash_table_lookup (icall_hash, mname);
8589 mono_icall_unlock ();
8593 #ifdef DISABLE_ICALL_TABLES
8594 mono_icall_unlock ();
8595 /* Fail only when the result is actually used */
8596 /* mono_marshal_get_native_wrapper () depends on this */
8597 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8598 return ves_icall_System_String_ctor_RedirectToCreateString;
8600 return no_icall_table;
8602 /* it wasn't found in the static call tables */
8604 mono_icall_unlock ();
8607 res = find_method_icall (imap, sigstart - mlen);
8609 mono_icall_unlock ();
8612 /* try _with_ signature */
8614 res = find_method_icall (imap, sigstart - mlen);
8616 mono_icall_unlock ();
8620 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8621 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8622 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8623 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8624 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");
8625 g_print ("If you see other errors or faults after this message they are probably related\n");
8626 g_print ("and you need to fix your mono install first.\n");
8628 mono_icall_unlock ();
8634 #ifdef ENABLE_ICALL_SYMBOL_MAP
8636 func_cmp (gconstpointer key, gconstpointer p)
8638 return (gsize)key - (gsize)*(gsize*)p;
8643 * mono_lookup_icall_symbol:
8645 * Given the icall METHOD, returns its C symbol.
8648 mono_lookup_icall_symbol (MonoMethod *m)
8650 #ifdef DISABLE_ICALL_TABLES
8651 g_assert_not_reached ();
8654 #ifdef ENABLE_ICALL_SYMBOL_MAP
8658 static gconstpointer *functions_sorted;
8659 static const char**symbols_sorted;
8660 static gboolean inited;
8665 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8666 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8667 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8668 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8669 /* Bubble sort the two arrays */
8673 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8674 if (functions_sorted [i] > functions_sorted [i + 1]) {
8677 tmp = functions_sorted [i];
8678 functions_sorted [i] = functions_sorted [i + 1];
8679 functions_sorted [i + 1] = tmp;
8680 tmp = symbols_sorted [i];
8681 symbols_sorted [i] = symbols_sorted [i + 1];
8682 symbols_sorted [i + 1] = tmp;
8689 func = mono_lookup_internal_call (m);
8692 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8696 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8698 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8699 g_assert_not_reached ();
8706 type_from_typename (char *type_name)
8708 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8710 if (!strcmp (type_name, "int"))
8711 klass = mono_defaults.int_class;
8712 else if (!strcmp (type_name, "ptr"))
8713 klass = mono_defaults.int_class;
8714 else if (!strcmp (type_name, "void"))
8715 klass = mono_defaults.void_class;
8716 else if (!strcmp (type_name, "int32"))
8717 klass = mono_defaults.int32_class;
8718 else if (!strcmp (type_name, "uint32"))
8719 klass = mono_defaults.uint32_class;
8720 else if (!strcmp (type_name, "int8"))
8721 klass = mono_defaults.sbyte_class;
8722 else if (!strcmp (type_name, "uint8"))
8723 klass = mono_defaults.byte_class;
8724 else if (!strcmp (type_name, "int16"))
8725 klass = mono_defaults.int16_class;
8726 else if (!strcmp (type_name, "uint16"))
8727 klass = mono_defaults.uint16_class;
8728 else if (!strcmp (type_name, "long"))
8729 klass = mono_defaults.int64_class;
8730 else if (!strcmp (type_name, "ulong"))
8731 klass = mono_defaults.uint64_class;
8732 else if (!strcmp (type_name, "float"))
8733 klass = mono_defaults.single_class;
8734 else if (!strcmp (type_name, "double"))
8735 klass = mono_defaults.double_class;
8736 else if (!strcmp (type_name, "object"))
8737 klass = mono_defaults.object_class;
8738 else if (!strcmp (type_name, "obj"))
8739 klass = mono_defaults.object_class;
8740 else if (!strcmp (type_name, "string"))
8741 klass = mono_defaults.string_class;
8742 else if (!strcmp (type_name, "bool"))
8743 klass = mono_defaults.boolean_class;
8744 else if (!strcmp (type_name, "boolean"))
8745 klass = mono_defaults.boolean_class;
8747 g_error ("%s", type_name);
8748 g_assert_not_reached ();
8750 return &klass->byval_arg;
8754 * LOCKING: Take the corlib image lock.
8756 MonoMethodSignature*
8757 mono_create_icall_signature (const char *sigstr)
8762 MonoMethodSignature *res, *res2;
8763 MonoImage *corlib = mono_defaults.corlib;
8765 mono_image_lock (corlib);
8766 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8767 mono_image_unlock (corlib);
8772 parts = g_strsplit (sigstr, " ", 256);
8781 res = mono_metadata_signature_alloc (corlib, len - 1);
8786 * Under windows, the default pinvoke calling convention is STDCALL but
8789 res->call_convention = MONO_CALL_C;
8792 res->ret = type_from_typename (parts [0]);
8793 for (i = 1; i < len; ++i) {
8794 res->params [i - 1] = type_from_typename (parts [i]);
8799 mono_image_lock (corlib);
8800 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8802 res = res2; /*Value is allocated in the image pool*/
8804 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8805 mono_image_unlock (corlib);
8811 mono_find_jit_icall_by_name (const char *name)
8813 MonoJitICallInfo *info;
8814 g_assert (jit_icall_hash_name);
8817 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8818 mono_icall_unlock ();
8823 mono_find_jit_icall_by_addr (gconstpointer addr)
8825 MonoJitICallInfo *info;
8826 g_assert (jit_icall_hash_addr);
8829 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8830 mono_icall_unlock ();
8836 * mono_get_jit_icall_info:
8838 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8839 * caller should access it while holding the icall lock.
8842 mono_get_jit_icall_info (void)
8844 return jit_icall_hash_name;
8848 * mono_lookup_jit_icall_symbol:
8850 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8853 mono_lookup_jit_icall_symbol (const char *name)
8855 MonoJitICallInfo *info;
8856 const char *res = NULL;
8859 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8861 res = info->c_symbol;
8862 mono_icall_unlock ();
8867 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8870 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8871 mono_icall_unlock ();
8875 * 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
8876 * icalls without wrappers in some cases.
8879 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8881 MonoJitICallInfo *info;
8888 if (!jit_icall_hash_name) {
8889 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8890 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8893 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8894 g_warning ("jit icall already defined \"%s\"\n", name);
8895 g_assert_not_reached ();
8898 info = g_new0 (MonoJitICallInfo, 1);
8903 info->c_symbol = c_symbol;
8904 info->no_raise = no_raise;
8907 info->wrapper = func;
8909 info->wrapper = NULL;
8912 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8913 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8915 mono_icall_unlock ();
8920 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8922 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);