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);
1274 * ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class:
1275 * @tb: a TypeBuilder object
1278 * Creates the generic class after all generic parameters have been added.
1281 ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class (MonoReflectionTypeBuilder *tb)
1284 (void) mono_reflection_create_generic_class (tb, &error);
1285 mono_error_set_pending_exception (&error);
1288 #ifndef DISABLE_REFLECTION_EMIT
1289 ICALL_EXPORT MonoArray*
1290 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
1293 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
1294 mono_error_set_pending_exception (&error);
1300 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1302 MonoMethod **dest = (MonoMethod **)data;
1304 /* skip unmanaged frames */
1309 if (!strcmp (m->klass->name_space, "System.Reflection"))
1318 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1320 MonoMethod **dest = (MonoMethod **)data;
1322 /* skip unmanaged frames */
1326 if (m->wrapper_type != MONO_WRAPPER_NONE)
1334 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1345 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1347 MonoMethod **dest = (MonoMethod **)data;
1349 /* skip unmanaged frames */
1353 if (m->wrapper_type != MONO_WRAPPER_NONE)
1361 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1362 || (!strcmp (m->klass->name_space, "System"))))
1372 static MonoReflectionType *
1373 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1375 MonoMethod *m, *dest;
1377 MonoType *type = NULL;
1378 MonoAssembly *assembly = NULL;
1379 gboolean type_resolve = FALSE;
1380 MonoImage *rootimage = NULL;
1382 mono_error_init (error);
1385 * We must compute the calling assembly as type loading must happen under a metadata context.
1386 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1387 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1389 m = mono_method_get_last_managed ();
1391 if (m && m->klass->image != mono_defaults.corlib) {
1392 /* Happens with inlining */
1394 /* Ugly hack: type_from_parsed_name is called from
1395 * System.Type.internal_from_name, which is called most
1396 * directly from System.Type.GetType(string,bool,bool) but
1397 * also indirectly from places such as
1398 * System.Type.GetType(string,func,func) (via
1399 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1400 * so we need to skip over all of those to find the true caller.
1402 * It would be nice if we had stack marks.
1404 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1410 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1411 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1412 * to crash. This only seems to happen in some strange remoting
1413 * scenarios and I was unable to figure out what's happening there.
1414 * Dec 10, 2005 - Martin.
1418 assembly = dest->klass->image->assembly;
1419 type_resolve = TRUE;
1420 rootimage = assembly->image;
1422 g_warning (G_STRLOC);
1425 if (info->assembly.name)
1426 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1429 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1430 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1431 return_val_if_nok (error, NULL);
1435 // Say we're looking for System.Generic.Dict<int, Local>
1436 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1437 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1438 // is messed up when we go to construct the Local as the type arg...
1440 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1441 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1442 if (!info->assembly.name && !type) {
1444 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1445 return_val_if_nok (error, NULL);
1447 if (assembly && !type && type_resolve) {
1448 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1449 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1450 return_val_if_nok (error, NULL);
1456 return mono_type_get_object_checked (mono_domain_get (), type, error);
1459 ICALL_EXPORT MonoReflectionType*
1460 ves_icall_System_Type_internal_from_name (MonoString *name,
1461 MonoBoolean throwOnError,
1462 MonoBoolean ignoreCase)
1465 char *str = mono_string_to_utf8 (name);
1466 MonoTypeNameParse info;
1467 MonoReflectionType *type;
1470 parsedOk = mono_reflection_parse_type (str, &info);
1472 /* mono_reflection_parse_type() mangles the string */
1474 mono_reflection_free_type_info (&info);
1476 mono_error_init (&error);
1477 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1478 mono_error_set_pending_exception (&error);
1484 type = type_from_parsed_name (&info, ignoreCase, &error);
1486 mono_reflection_free_type_info (&info);
1489 if (!mono_error_ok (&error)) {
1491 mono_error_set_pending_exception (&error);
1493 mono_error_cleanup (&error);
1498 MonoException *e = NULL;
1501 e = mono_get_exception_type_load (name, NULL);
1504 mono_set_pending_exception (e);
1513 ICALL_EXPORT MonoReflectionType*
1514 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1517 MonoReflectionType *ret;
1518 MonoDomain *domain = mono_domain_get ();
1520 ret = mono_type_get_object_checked (domain, handle, &error);
1521 mono_error_set_pending_exception (&error);
1526 /* System.TypeCode */
1545 TYPECODE_STRING = 18
1548 ICALL_EXPORT guint32
1549 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1551 int t = type->type->type;
1553 if (type->type->byref)
1554 return TYPECODE_OBJECT;
1558 case MONO_TYPE_VOID:
1559 return TYPECODE_OBJECT;
1560 case MONO_TYPE_BOOLEAN:
1561 return TYPECODE_BOOLEAN;
1563 return TYPECODE_BYTE;
1565 return TYPECODE_SBYTE;
1567 return TYPECODE_UINT16;
1569 return TYPECODE_INT16;
1570 case MONO_TYPE_CHAR:
1571 return TYPECODE_CHAR;
1575 return TYPECODE_OBJECT;
1577 return TYPECODE_UINT32;
1579 return TYPECODE_INT32;
1581 return TYPECODE_UINT64;
1583 return TYPECODE_INT64;
1585 return TYPECODE_SINGLE;
1587 return TYPECODE_DOUBLE;
1588 case MONO_TYPE_VALUETYPE: {
1589 MonoClass *klass = type->type->data.klass;
1591 if (klass->enumtype) {
1592 t = mono_class_enum_basetype (klass)->type;
1594 } else if (mono_is_corlib_image (klass->image)) {
1595 if (strcmp (klass->name_space, "System") == 0) {
1596 if (strcmp (klass->name, "Decimal") == 0)
1597 return TYPECODE_DECIMAL;
1598 else if (strcmp (klass->name, "DateTime") == 0)
1599 return TYPECODE_DATETIME;
1602 return TYPECODE_OBJECT;
1604 case MONO_TYPE_STRING:
1605 return TYPECODE_STRING;
1606 case MONO_TYPE_SZARRAY:
1607 case MONO_TYPE_ARRAY:
1608 case MONO_TYPE_OBJECT:
1610 case MONO_TYPE_MVAR:
1611 case MONO_TYPE_TYPEDBYREF:
1612 return TYPECODE_OBJECT;
1613 case MONO_TYPE_CLASS:
1615 MonoClass *klass = type->type->data.klass;
1616 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1617 if (strcmp (klass->name, "DBNull") == 0)
1618 return TYPECODE_DBNULL;
1621 return TYPECODE_OBJECT;
1622 case MONO_TYPE_GENERICINST:
1623 return TYPECODE_OBJECT;
1625 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1631 mono_type_is_primitive (MonoType *type)
1633 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1634 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1638 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1640 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1641 return mono_class_enum_basetype (type->data.klass);
1642 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1643 return mono_class_enum_basetype (type->data.generic_class->container_class);
1647 ICALL_EXPORT guint32
1648 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1653 g_assert (type != NULL);
1655 klass = mono_class_from_mono_type (type->type);
1656 klassc = mono_class_from_mono_type (c->type);
1658 if (type->type->byref ^ c->type->byref)
1661 if (type->type->byref) {
1662 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1663 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1665 klass = mono_class_from_mono_type (t);
1666 klassc = mono_class_from_mono_type (ot);
1668 if (mono_type_is_primitive (t)) {
1669 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1670 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1671 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1672 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1673 return t->type == ot->type;
1675 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1678 if (klass->valuetype)
1679 return klass == klassc;
1680 return klass->valuetype == klassc->valuetype;
1683 return mono_class_is_assignable_from (klass, klassc);
1686 ICALL_EXPORT guint32
1687 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1690 MonoClass *klass = mono_class_from_mono_type (type->type);
1691 mono_class_init_checked (klass, &error);
1692 if (!is_ok (&error)) {
1693 mono_error_set_pending_exception (&error);
1696 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1697 mono_error_set_pending_exception (&error);
1701 ICALL_EXPORT guint32
1702 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1704 MonoClass *klass = mono_class_from_mono_type (type->type);
1705 return klass->flags;
1708 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1709 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1712 MonoClass *klass = field->field->parent;
1713 MonoMarshalType *info;
1717 if (klass->generic_container ||
1718 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1721 ftype = mono_field_get_type (field->field);
1722 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1725 info = mono_marshal_load_type_info (klass);
1727 for (i = 0; i < info->num_fields; ++i) {
1728 if (info->fields [i].field == field->field) {
1729 if (!info->fields [i].mspec)
1732 MonoReflectionMarshalAsAttribute* obj;
1733 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1734 if (!mono_error_ok (&error))
1735 mono_error_set_pending_exception (&error);
1744 ICALL_EXPORT MonoReflectionField*
1745 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1748 gboolean found = FALSE;
1755 klass = handle->parent;
1757 klass = mono_class_from_mono_type (type);
1759 /* Check that the field belongs to the class */
1760 for (k = klass; k; k = k->parent) {
1761 if (k == handle->parent) {
1768 /* The managed code will throw the exception */
1772 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1773 mono_error_set_pending_exception (&error);
1777 ICALL_EXPORT MonoArray*
1778 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1781 MonoType *type = mono_field_get_type_checked (field->field, &error);
1784 if (!mono_error_ok (&error)) {
1785 mono_error_set_pending_exception (&error);
1789 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1790 mono_error_set_pending_exception (&error);
1795 vell_icall_get_method_attributes (MonoMethod *method)
1797 return method->flags;
1801 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1804 MonoReflectionType *rt;
1805 MonoDomain *domain = mono_domain_get ();
1806 MonoMethodSignature* sig;
1808 sig = mono_method_signature_checked (method, &error);
1809 if (!mono_error_ok (&error)) {
1810 mono_error_set_pending_exception (&error);
1814 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1815 if (!mono_error_ok (&error)) {
1816 mono_error_set_pending_exception (&error);
1820 MONO_STRUCT_SETREF (info, parent, rt);
1822 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1823 if (!mono_error_ok (&error)) {
1824 mono_error_set_pending_exception (&error);
1828 MONO_STRUCT_SETREF (info, ret, rt);
1830 info->attrs = method->flags;
1831 info->implattrs = method->iflags;
1832 if (sig->call_convention == MONO_CALL_DEFAULT)
1833 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1835 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1840 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1843 ICALL_EXPORT MonoArray*
1844 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1847 MonoDomain *domain = mono_domain_get ();
1849 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1850 mono_error_set_pending_exception (&error);
1854 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1855 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1858 MonoDomain *domain = mono_domain_get ();
1859 MonoReflectionMarshalAsAttribute* res = NULL;
1860 MonoMarshalSpec **mspecs;
1863 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1864 mono_method_get_marshal_info (method, mspecs);
1867 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1868 if (!mono_error_ok (&error)) {
1869 mono_error_set_pending_exception (&error);
1874 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1876 mono_metadata_free_marshal_spec (mspecs [i]);
1883 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1885 MonoClass *parent = field->field->parent;
1886 if (!parent->size_inited)
1887 mono_class_init (parent);
1888 mono_class_setup_fields_locking (parent);
1890 return field->field->offset - sizeof (MonoObject);
1893 ICALL_EXPORT MonoReflectionType*
1894 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1897 MonoReflectionType *ret;
1900 parent = declaring? field->field->parent: field->klass;
1902 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1903 mono_error_set_pending_exception (&error);
1909 ICALL_EXPORT MonoObject *
1910 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1913 MonoClass *fklass = field->klass;
1914 MonoClassField *cf = field->field;
1915 MonoDomain *domain = mono_object_domain (field);
1917 if (fklass->image->assembly->ref_only) {
1918 mono_set_pending_exception (mono_get_exception_invalid_operation (
1919 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1923 if (mono_security_core_clr_enabled () &&
1924 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1925 mono_error_set_pending_exception (&error);
1929 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1930 mono_error_set_pending_exception (&error);
1935 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1938 MonoClassField *cf = field->field;
1942 if (field->klass->image->assembly->ref_only) {
1943 mono_set_pending_exception (mono_get_exception_invalid_operation (
1944 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1948 if (mono_security_core_clr_enabled () &&
1949 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1950 mono_error_set_pending_exception (&error);
1954 type = mono_field_get_type_checked (cf, &error);
1955 if (!mono_error_ok (&error)) {
1956 mono_error_set_pending_exception (&error);
1960 v = (gchar *) value;
1962 switch (type->type) {
1965 case MONO_TYPE_BOOLEAN:
1968 case MONO_TYPE_CHAR:
1977 case MONO_TYPE_VALUETYPE:
1980 v += sizeof (MonoObject);
1982 case MONO_TYPE_STRING:
1983 case MONO_TYPE_OBJECT:
1984 case MONO_TYPE_CLASS:
1985 case MONO_TYPE_ARRAY:
1986 case MONO_TYPE_SZARRAY:
1989 case MONO_TYPE_GENERICINST: {
1990 MonoGenericClass *gclass = type->data.generic_class;
1991 g_assert (!gclass->context.class_inst->is_open);
1993 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1994 MonoClass *nklass = mono_class_from_mono_type (type);
1995 MonoObject *nullable;
1998 * Convert the boxed vtype into a Nullable structure.
1999 * This is complicated by the fact that Nullables have
2000 * a variable structure.
2002 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2003 if (!mono_error_ok (&error)) {
2004 mono_error_set_pending_exception (&error);
2008 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2010 v = (gchar *)mono_object_unbox (nullable);
2013 if (gclass->container_class->valuetype && (v != NULL))
2014 v += sizeof (MonoObject);
2018 g_error ("type 0x%x not handled in "
2019 "ves_icall_FieldInfo_SetValueInternal", type->type);
2024 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2025 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2026 if (!is_ok (&error)) {
2027 mono_error_set_pending_exception (&error);
2030 if (!vtable->initialized) {
2031 if (!mono_runtime_class_init_full (vtable, &error)) {
2032 mono_error_set_pending_exception (&error);
2036 mono_field_static_set_value (vtable, cf, v);
2038 mono_field_set_value (obj, cf, v);
2043 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2052 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2053 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2057 if (MONO_TYPE_IS_REFERENCE (f->type))
2058 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2060 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2063 ICALL_EXPORT MonoObject *
2064 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2066 MonoObject *o = NULL;
2067 MonoClassField *field = rfield->field;
2069 MonoDomain *domain = mono_object_domain (rfield);
2071 MonoTypeEnum def_type;
2072 const char *def_value;
2076 mono_class_init (field->parent);
2078 t = mono_field_get_type_checked (field, &error);
2079 if (!mono_error_ok (&error)) {
2080 mono_error_set_pending_exception (&error);
2084 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2085 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2089 if (image_is_dynamic (field->parent->image)) {
2090 MonoClass *klass = field->parent;
2091 int fidx = field - klass->fields;
2093 g_assert (fidx >= 0 && fidx < klass->field.count);
2094 g_assert (klass->ext);
2095 g_assert (klass->ext->field_def_values);
2096 def_type = klass->ext->field_def_values [fidx].def_type;
2097 def_value = klass->ext->field_def_values [fidx].data;
2098 if (def_type == MONO_TYPE_END) {
2099 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2103 def_value = mono_class_get_field_default_value (field, &def_type);
2104 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2106 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2111 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2115 case MONO_TYPE_BOOLEAN:
2118 case MONO_TYPE_CHAR:
2126 case MONO_TYPE_R8: {
2129 /* boxed value type */
2130 t = g_new0 (MonoType, 1);
2132 klass = mono_class_from_mono_type (t);
2134 o = mono_object_new_checked (domain, klass, &error);
2135 if (!mono_error_ok (&error)) {
2136 mono_error_set_pending_exception (&error);
2139 v = ((gchar *) o) + sizeof (MonoObject);
2140 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2143 case MONO_TYPE_STRING:
2144 case MONO_TYPE_CLASS:
2145 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2148 g_assert_not_reached ();
2154 ICALL_EXPORT MonoReflectionType*
2155 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2158 MonoReflectionType *ret;
2161 type = mono_field_get_type_checked (ref_field->field, &error);
2162 if (!mono_error_ok (&error)) {
2163 mono_error_set_pending_exception (&error);
2167 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2168 if (!mono_error_ok (&error)) {
2169 mono_error_set_pending_exception (&error);
2176 /* From MonoProperty.cs */
2178 PInfo_Attributes = 1,
2179 PInfo_GetMethod = 1 << 1,
2180 PInfo_SetMethod = 1 << 2,
2181 PInfo_ReflectedType = 1 << 3,
2182 PInfo_DeclaringType = 1 << 4,
2187 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2190 MonoReflectionType *rt;
2191 MonoReflectionMethod *rm;
2192 MonoDomain *domain = mono_object_domain (property);
2193 const MonoProperty *pproperty = property->property;
2195 if ((req_info & PInfo_ReflectedType) != 0) {
2196 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2197 if (mono_error_set_pending_exception (&error))
2200 MONO_STRUCT_SETREF (info, parent, rt);
2202 if ((req_info & PInfo_DeclaringType) != 0) {
2203 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2204 if (mono_error_set_pending_exception (&error))
2207 MONO_STRUCT_SETREF (info, declaring_type, rt);
2210 if ((req_info & PInfo_Name) != 0)
2211 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2213 if ((req_info & PInfo_Attributes) != 0)
2214 info->attrs = pproperty->attrs;
2216 if ((req_info & PInfo_GetMethod) != 0) {
2217 if (pproperty->get &&
2218 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2219 pproperty->get->klass == property->klass)) {
2220 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2221 if (mono_error_set_pending_exception (&error))
2227 MONO_STRUCT_SETREF (info, get, rm);
2229 if ((req_info & PInfo_SetMethod) != 0) {
2230 if (pproperty->set &&
2231 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2232 pproperty->set->klass == property->klass)) {
2233 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2234 if (mono_error_set_pending_exception (&error))
2240 MONO_STRUCT_SETREF (info, set, rm);
2243 * There may be other methods defined for properties, though, it seems they are not exposed
2244 * in the reflection API
2249 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2252 MonoReflectionType *rt;
2253 MonoReflectionMethod *rm;
2254 MonoDomain *domain = mono_object_domain (event);
2256 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2257 if (mono_error_set_pending_exception (&error))
2260 MONO_STRUCT_SETREF (info, reflected_type, rt);
2262 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2263 if (mono_error_set_pending_exception (&error))
2266 MONO_STRUCT_SETREF (info, declaring_type, rt);
2268 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2269 info->attrs = event->event->attrs;
2271 if (event->event->add) {
2272 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2273 if (mono_error_set_pending_exception (&error))
2279 MONO_STRUCT_SETREF (info, add_method, rm);
2281 if (event->event->remove) {
2282 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2283 if (mono_error_set_pending_exception (&error))
2289 MONO_STRUCT_SETREF (info, remove_method, rm);
2291 if (event->event->raise) {
2292 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2293 if (mono_error_set_pending_exception (&error))
2299 MONO_STRUCT_SETREF (info, raise_method, rm);
2301 #ifndef MONO_SMALL_CONFIG
2302 if (event->event->other) {
2304 while (event->event->other [n])
2306 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2308 for (i = 0; i < n; i++) {
2309 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2310 if (mono_error_set_pending_exception (&error))
2312 mono_array_setref (info->other_methods, i, rm);
2319 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2324 mono_class_setup_interfaces (klass, error);
2325 if (!mono_error_ok (error))
2328 for (i = 0; i < klass->interface_count; i++) {
2329 ic = klass->interfaces [i];
2330 g_hash_table_insert (ifaces, ic, ic);
2332 collect_interfaces (ic, ifaces, error);
2333 if (!mono_error_ok (error))
2339 MonoArray *iface_array;
2340 MonoGenericContext *context;
2344 } FillIfaceArrayData;
2347 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2349 MonoReflectionType *rt;
2350 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2351 MonoClass *ic = (MonoClass *)key;
2352 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2354 if (!mono_error_ok (data->error))
2357 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2358 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2359 if (!mono_error_ok (data->error))
2363 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2364 if (!mono_error_ok (data->error))
2367 mono_array_setref (data->iface_array, data->next_idx++, rt);
2370 mono_metadata_free_type (inflated);
2374 get_interfaces_hash (gconstpointer v1)
2376 MonoClass *k = (MonoClass*)v1;
2378 return k->type_token;
2381 ICALL_EXPORT MonoArray*
2382 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2385 MonoClass *klass = mono_class_from_mono_type (type->type);
2387 FillIfaceArrayData data = { 0 };
2390 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2392 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2393 data.context = mono_class_get_context (klass);
2394 klass = klass->generic_class->container_class;
2397 for (parent = klass; parent; parent = parent->parent) {
2398 mono_class_setup_interfaces (parent, &error);
2399 if (!mono_error_ok (&error))
2401 collect_interfaces (parent, iface_hash, &error);
2402 if (!mono_error_ok (&error))
2406 data.error = &error;
2407 data.domain = mono_object_domain (type);
2409 len = g_hash_table_size (iface_hash);
2411 g_hash_table_destroy (iface_hash);
2412 if (!data.domain->empty_types)
2413 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2414 return data.domain->empty_types;
2417 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2418 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2419 if (!mono_error_ok (&error))
2422 g_hash_table_destroy (iface_hash);
2423 return data.iface_array;
2426 g_hash_table_destroy (iface_hash);
2427 mono_error_set_pending_exception (&error);
2432 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2434 gboolean variance_used;
2435 MonoClass *klass = mono_class_from_mono_type (type->type);
2436 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2437 MonoReflectionMethod *member;
2440 int i = 0, len, ioffset;
2444 mono_class_init_checked (klass, &error);
2445 if (mono_error_set_pending_exception (&error))
2447 mono_class_init_checked (iclass, &error);
2448 if (mono_error_set_pending_exception (&error))
2451 mono_class_setup_vtable (klass);
2453 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2457 len = mono_class_num_methods (iclass);
2458 domain = mono_object_domain (type);
2459 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2460 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2462 while ((method = mono_class_get_methods (iclass, &iter))) {
2463 member = mono_method_get_object_checked (domain, method, iclass, &error);
2464 if (mono_error_set_pending_exception (&error))
2466 mono_array_setref (*methods, i, member);
2467 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2468 if (mono_error_set_pending_exception (&error))
2470 mono_array_setref (*targets, i, member);
2477 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2480 MonoClass *klass = mono_class_from_mono_type (type->type);
2482 mono_class_init_checked (klass, &error);
2483 if (mono_error_set_pending_exception (&error))
2486 if (image_is_dynamic (klass->image)) {
2487 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2488 *packing = tb->packing_size;
2489 *size = tb->class_size;
2491 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2495 ICALL_EXPORT MonoReflectionType*
2496 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2499 MonoReflectionType *ret;
2502 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2503 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2504 mono_error_set_pending_exception (&error);
2508 klass = mono_class_from_mono_type (type->type);
2509 mono_class_init_checked (klass, &error);
2510 if (mono_error_set_pending_exception (&error))
2514 // GetElementType should only return a type for:
2515 // Array Pointer PassedByRef
2516 if (type->type->byref)
2517 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2518 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2519 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2520 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2521 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2525 mono_error_set_pending_exception (&error);
2530 ICALL_EXPORT MonoReflectionType*
2531 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2534 MonoReflectionType *ret;
2536 if (type->type->byref)
2539 MonoClass *klass = mono_class_from_mono_type (type->type);
2543 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2544 mono_error_set_pending_exception (&error);
2549 ICALL_EXPORT MonoBoolean
2550 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2552 return type->type->type == MONO_TYPE_PTR;
2555 ICALL_EXPORT MonoBoolean
2556 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2558 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)));
2561 ICALL_EXPORT MonoBoolean
2562 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2564 return type->type->byref;
2567 ICALL_EXPORT MonoBoolean
2568 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2571 MonoClass *klass = mono_class_from_mono_type (type->type);
2572 mono_class_init_checked (klass, &error);
2573 if (mono_error_set_pending_exception (&error))
2576 return mono_class_is_com_object (klass);
2579 ICALL_EXPORT guint32
2580 ves_icall_reflection_get_token (MonoObject* obj)
2583 guint32 result = mono_reflection_get_token_checked (obj, &error);
2584 mono_error_set_pending_exception (&error);
2588 ICALL_EXPORT MonoReflectionModule*
2589 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2592 MonoReflectionModule *result = NULL;
2593 MonoClass *klass = mono_class_from_mono_type (type->type);
2594 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2595 mono_error_set_pending_exception (&error);
2599 ICALL_EXPORT MonoReflectionAssembly*
2600 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2603 MonoDomain *domain = mono_domain_get ();
2604 MonoClass *klass = mono_class_from_mono_type (type->type);
2605 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2606 mono_error_set_pending_exception (&error);
2610 ICALL_EXPORT MonoReflectionType*
2611 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2614 MonoReflectionType *ret;
2615 MonoDomain *domain = mono_domain_get ();
2618 if (type->type->byref)
2620 if (type->type->type == MONO_TYPE_VAR) {
2621 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2622 klass = param ? param->owner.klass : NULL;
2623 } else if (type->type->type == MONO_TYPE_MVAR) {
2624 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2625 klass = param ? param->owner.method->klass : NULL;
2627 klass = mono_class_from_mono_type (type->type)->nested_in;
2633 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2634 mono_error_set_pending_exception (&error);
2639 ICALL_EXPORT MonoString*
2640 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2642 MonoDomain *domain = mono_domain_get ();
2643 MonoClass *klass = mono_class_from_mono_type (type->type);
2645 if (type->type->byref) {
2646 char *n = g_strdup_printf ("%s&", klass->name);
2647 MonoString *res = mono_string_new (domain, n);
2653 return mono_string_new (domain, klass->name);
2657 ICALL_EXPORT MonoString*
2658 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2660 MonoDomain *domain = mono_domain_get ();
2661 MonoClass *klass = mono_class_from_mono_type (type->type);
2663 while (klass->nested_in)
2664 klass = klass->nested_in;
2666 if (klass->name_space [0] == '\0')
2669 return mono_string_new (domain, klass->name_space);
2673 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2677 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2678 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2682 klass = mono_class_from_mono_type (type->type);
2688 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2691 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2695 ICALL_EXPORT MonoArray*
2696 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2699 MonoReflectionType *rt;
2701 MonoClass *klass, *pklass;
2702 MonoDomain *domain = mono_object_domain (type);
2705 klass = mono_class_from_mono_type (type->type);
2707 if (klass->generic_container) {
2708 MonoGenericContainer *container = klass->generic_container;
2709 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2710 for (i = 0; i < container->type_argc; ++i) {
2711 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2713 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2714 if (mono_error_set_pending_exception (&error))
2717 mono_array_setref (res, i, rt);
2719 } else if (klass->generic_class) {
2720 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2721 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2722 for (i = 0; i < inst->type_argc; ++i) {
2723 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2724 if (mono_error_set_pending_exception (&error))
2727 mono_array_setref (res, i, rt);
2735 ICALL_EXPORT gboolean
2736 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2740 if (!IS_MONOTYPE (type))
2743 if (type->type->byref)
2746 klass = mono_class_from_mono_type (type->type);
2747 return klass->generic_container != NULL;
2750 ICALL_EXPORT MonoReflectionType*
2751 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2754 MonoReflectionType *ret;
2757 if (type->type->byref)
2760 klass = mono_class_from_mono_type (type->type);
2762 if (klass->generic_container) {
2763 return type; /* check this one */
2765 if (klass->generic_class) {
2766 MonoClass *generic_class = klass->generic_class->container_class;
2769 tb = mono_class_get_ref_info (generic_class);
2771 if (generic_class->wastypebuilder && tb)
2772 return (MonoReflectionType *)tb;
2774 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2775 mono_error_set_pending_exception (&error);
2783 ICALL_EXPORT MonoReflectionType*
2784 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2787 MonoReflectionType *ret;
2789 MonoType *geninst, **types;
2792 g_assert (IS_MONOTYPE (type));
2793 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2794 if (mono_error_set_pending_exception (&error))
2797 count = mono_array_length (type_array);
2798 types = g_new0 (MonoType *, count);
2800 for (i = 0; i < count; i++) {
2801 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2802 types [i] = t->type;
2805 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2808 mono_error_set_pending_exception (&error);
2812 klass = mono_class_from_mono_type (geninst);
2814 /*we might inflate to the GTD*/
2815 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2816 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2820 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2821 mono_error_set_pending_exception (&error);
2826 ICALL_EXPORT gboolean
2827 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2831 if (!IS_MONOTYPE (type))
2834 if (type->type->byref)
2837 klass = mono_class_from_mono_type (type->type);
2838 return klass->generic_class != NULL || klass->generic_container != NULL;
2842 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2844 if (!IS_MONOTYPE (type))
2847 if (is_generic_parameter (type->type))
2848 return mono_type_get_generic_param_num (type->type);
2852 ICALL_EXPORT GenericParameterAttributes
2853 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2855 g_assert (IS_MONOTYPE (type));
2856 g_assert (is_generic_parameter (type->type));
2857 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2860 ICALL_EXPORT MonoArray *
2861 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2864 MonoReflectionType *rt;
2865 MonoGenericParamInfo *param_info;
2871 g_assert (IS_MONOTYPE (type));
2873 domain = mono_object_domain (type);
2874 param_info = mono_generic_param_info (type->type->data.generic_param);
2875 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2878 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2879 for (i = 0; i < count; i++) {
2880 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2881 if (mono_error_set_pending_exception (&error))
2884 mono_array_setref (res, i, rt);
2891 ICALL_EXPORT MonoBoolean
2892 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2894 return is_generic_parameter (type->type);
2897 ICALL_EXPORT MonoBoolean
2898 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2900 return is_generic_parameter (tb->type.type);
2904 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2905 MonoReflectionType *t)
2907 enumtype->type = t->type;
2910 ICALL_EXPORT MonoReflectionMethod*
2911 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2912 MonoReflectionMethod* generic)
2919 MonoReflectionMethod *ret = NULL;
2921 domain = ((MonoObject *)type)->vtable->domain;
2923 klass = mono_class_from_mono_type (type->type);
2924 mono_class_init_checked (klass, &error);
2925 if (mono_error_set_pending_exception (&error))
2929 while ((method = mono_class_get_methods (klass, &iter))) {
2930 if (method->token == generic->method->token) {
2931 ret = mono_method_get_object_checked (domain, method, klass, &error);
2932 if (mono_error_set_pending_exception (&error))
2940 ICALL_EXPORT MonoReflectionMethod *
2941 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2944 MonoType *type = ref_type->type;
2946 MonoReflectionMethod *ret = NULL;
2948 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2949 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2952 if (type->type == MONO_TYPE_VAR)
2955 method = mono_type_get_generic_param_owner (type)->owner.method;
2958 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2959 if (!mono_error_ok (&error))
2960 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2964 ICALL_EXPORT MonoBoolean
2965 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2967 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2971 ICALL_EXPORT MonoBoolean
2972 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2974 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2979 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2981 MonoDomain *domain = mono_domain_get ();
2982 MonoImage *image = method->method->klass->image;
2983 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2984 MonoTableInfo *tables = image->tables;
2985 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2986 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2987 guint32 im_cols [MONO_IMPLMAP_SIZE];
2988 guint32 scope_token;
2989 const char *import = NULL;
2990 const char *scope = NULL;
2992 if (image_is_dynamic (image)) {
2993 MonoReflectionMethodAux *method_aux =
2994 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2996 import = method_aux->dllentry;
2997 scope = method_aux->dll;
3000 if (!import || !scope) {
3001 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
3006 if (piinfo->implmap_idx) {
3007 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
3009 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
3010 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
3011 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
3012 scope = mono_metadata_string_heap (image, scope_token);
3016 *flags = piinfo->piflags;
3017 *entry_point = mono_string_new (domain, import);
3018 *dll_name = mono_string_new (domain, scope);
3021 ICALL_EXPORT MonoReflectionMethod *
3022 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3024 MonoMethodInflated *imethod;
3026 MonoReflectionMethod *ret = NULL;
3029 if (method->method->is_generic)
3032 if (!method->method->is_inflated)
3035 imethod = (MonoMethodInflated *) method->method;
3037 result = imethod->declaring;
3038 /* Not a generic method. */
3039 if (!result->is_generic)
3042 if (image_is_dynamic (method->method->klass->image)) {
3043 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3044 MonoReflectionMethod *res;
3047 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3048 * the dynamic case as well ?
3050 mono_image_lock ((MonoImage*)image);
3051 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3052 mono_image_unlock ((MonoImage*)image);
3058 if (imethod->context.class_inst) {
3059 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3060 /*Generic methods gets the context of the GTD.*/
3061 if (mono_class_get_context (klass)) {
3062 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3063 if (!mono_error_ok (&error))
3068 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3070 if (!mono_error_ok (&error))
3071 mono_error_set_pending_exception (&error);
3075 ICALL_EXPORT gboolean
3076 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3078 return mono_method_signature (method->method)->generic_param_count != 0;
3081 ICALL_EXPORT gboolean
3082 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3084 return method->method->is_generic;
3087 ICALL_EXPORT MonoArray*
3088 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3091 MonoReflectionType *rt;
3096 domain = mono_object_domain (method);
3098 if (method->method->is_inflated) {
3099 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3102 count = inst->type_argc;
3103 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3105 for (i = 0; i < count; i++) {
3106 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3107 if (mono_error_set_pending_exception (&error))
3110 mono_array_setref (res, i, rt);
3117 count = mono_method_signature (method->method)->generic_param_count;
3118 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3120 for (i = 0; i < count; i++) {
3121 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3122 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3123 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3125 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3126 if (mono_error_set_pending_exception (&error))
3129 mono_array_setref (res, i, rt);
3135 ICALL_EXPORT MonoObject *
3136 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3140 * Invoke from reflection is supposed to always be a virtual call (the API
3141 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3142 * greater flexibility.
3144 MonoMethod *m = method->method;
3145 MonoMethodSignature *sig = mono_method_signature (m);
3148 void *obj = this_arg;
3152 if (mono_security_core_clr_enabled () &&
3153 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3154 mono_error_set_pending_exception (&error);
3158 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3159 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3160 mono_error_cleanup (&error); /* FIXME does this make sense? */
3161 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3166 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3167 if (!is_ok (&error)) {
3168 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3171 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3172 char *target_name = mono_type_get_full_name (m->klass);
3173 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3174 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3176 g_free (target_name);
3180 m = mono_object_get_virtual_method (this_arg, m);
3181 /* must pass the pointer to the value for valuetype methods */
3182 if (m->klass->valuetype)
3183 obj = mono_object_unbox (this_arg);
3184 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3185 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3190 if (sig->ret->byref) {
3191 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"));
3195 pcount = params? mono_array_length (params): 0;
3196 if (pcount != sig->param_count) {
3197 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3201 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3202 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."));
3206 image = m->klass->image;
3207 if (image->assembly->ref_only) {
3208 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."));
3212 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3213 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3217 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3221 intptr_t *lower_bounds;
3222 pcount = mono_array_length (params);
3223 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3224 /* Note: the synthetized array .ctors have int32 as argument type */
3225 for (i = 0; i < pcount; ++i)
3226 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3228 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3229 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3230 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3231 if (!mono_error_ok (&error)) {
3232 mono_error_set_pending_exception (&error);
3236 for (i = 0; i < mono_array_length (arr); ++i) {
3237 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3238 if (!mono_error_ok (&error)) {
3239 mono_error_set_pending_exception (&error);
3242 mono_array_setref_fast (arr, i, subarray);
3244 return (MonoObject*)arr;
3247 if (m->klass->rank == pcount) {
3248 /* Only lengths provided. */
3249 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3250 if (!mono_error_ok (&error)) {
3251 mono_error_set_pending_exception (&error);
3255 return (MonoObject*)arr;
3257 g_assert (pcount == (m->klass->rank * 2));
3258 /* The arguments are lower-bound-length pairs */
3259 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3261 for (i = 0; i < pcount / 2; ++i) {
3262 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3263 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3266 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3267 if (!mono_error_ok (&error)) {
3268 mono_error_set_pending_exception (&error);
3272 return (MonoObject*)arr;
3275 return mono_runtime_invoke_array (m, obj, params, NULL);
3278 #ifndef DISABLE_REMOTING
3279 ICALL_EXPORT MonoObject *
3280 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3283 MonoDomain *domain = mono_object_domain (method);
3284 MonoMethod *m = method->method;
3285 MonoMethodSignature *sig = mono_method_signature (m);
3286 MonoArray *out_args;
3288 int i, j, outarg_count = 0;
3290 if (m->klass == mono_defaults.object_class) {
3291 if (!strcmp (m->name, "FieldGetter")) {
3292 MonoClass *k = this_arg->vtable->klass;
3296 /* If this is a proxy, then it must be a CBO */
3297 if (k == mono_defaults.transparent_proxy_class) {
3298 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3299 this_arg = tp->rp->unwrapped_server;
3300 g_assert (this_arg);
3301 k = this_arg->vtable->klass;
3304 name = mono_array_get (params, MonoString *, 1);
3305 str = mono_string_to_utf8 (name);
3308 MonoClassField* field = mono_class_get_field_from_name (k, str);
3310 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3311 if (field_klass->valuetype) {
3312 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3313 mono_error_set_pending_exception (&error);
3314 /* fallthru to cleanup */
3316 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3318 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3319 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3320 mono_array_setref (out_args, 0, result);
3328 g_assert_not_reached ();
3330 } else if (!strcmp (m->name, "FieldSetter")) {
3331 MonoClass *k = this_arg->vtable->klass;
3337 /* If this is a proxy, then it must be a CBO */
3338 if (k == mono_defaults.transparent_proxy_class) {
3339 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3340 this_arg = tp->rp->unwrapped_server;
3341 g_assert (this_arg);
3342 k = this_arg->vtable->klass;
3345 name = mono_array_get (params, MonoString *, 1);
3346 str = mono_string_to_utf8 (name);
3349 MonoClassField* field = mono_class_get_field_from_name (k, str);
3351 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3352 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3354 if (field_klass->valuetype) {
3355 size = mono_type_size (field->type, &align);
3356 g_assert (size == mono_class_value_size (field_klass, NULL));
3357 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3359 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3362 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3363 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3373 g_assert_not_reached ();
3378 for (i = 0; i < mono_array_length (params); i++) {
3379 if (sig->params [i]->byref)
3383 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3385 /* handle constructors only for objects already allocated */
3386 if (!strcmp (method->method->name, ".ctor"))
3387 g_assert (this_arg);
3389 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3390 g_assert (!method->method->klass->valuetype);
3391 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3393 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3394 if (sig->params [i]->byref) {
3396 arg = mono_array_get (params, gpointer, i);
3397 mono_array_setref (out_args, j, arg);
3402 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3409 read_enum_value (const char *mem, int type)
3412 case MONO_TYPE_BOOLEAN:
3414 return *(guint8*)mem;
3416 return *(gint8*)mem;
3417 case MONO_TYPE_CHAR:
3419 return read16 (mem);
3421 return (gint16) read16 (mem);
3423 return read32 (mem);
3425 return (gint32) read32 (mem);
3428 return read64 (mem);
3430 g_assert_not_reached ();
3436 write_enum_value (char *mem, int type, guint64 value)
3440 case MONO_TYPE_I1: {
3441 guint8 *p = (guint8*)mem;
3446 case MONO_TYPE_I2: {
3447 guint16 *p = (guint16 *)mem;
3452 case MONO_TYPE_I4: {
3453 guint32 *p = (guint32 *)mem;
3458 case MONO_TYPE_I8: {
3459 guint64 *p = (guint64 *)mem;
3464 g_assert_not_reached ();
3469 ICALL_EXPORT MonoObject *
3470 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3478 domain = mono_object_domain (enumType);
3479 enumc = mono_class_from_mono_type (enumType->type);
3481 mono_class_init_checked (enumc, &error);
3482 if (mono_error_set_pending_exception (&error))
3485 etype = mono_class_enum_basetype (enumc);
3487 res = mono_object_new_checked (domain, enumc, &error);
3488 if (mono_error_set_pending_exception (&error))
3490 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3495 ICALL_EXPORT MonoBoolean
3496 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3498 int size = mono_class_value_size (a->vtable->klass, NULL);
3499 guint64 a_val = 0, b_val = 0;
3501 memcpy (&a_val, mono_object_unbox (a), size);
3502 memcpy (&b_val, mono_object_unbox (b), size);
3504 return (a_val & b_val) == b_val;
3507 ICALL_EXPORT MonoObject *
3508 ves_icall_System_Enum_get_value (MonoObject *eobj)
3520 g_assert (eobj->vtable->klass->enumtype);
3522 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3523 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3524 if (mono_error_set_pending_exception (&error))
3526 dst = (char *)res + sizeof (MonoObject);
3527 src = (char *)eobj + sizeof (MonoObject);
3528 size = mono_class_value_size (enumc, NULL);
3530 memcpy (dst, src, size);
3535 ICALL_EXPORT MonoReflectionType *
3536 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3539 MonoReflectionType *ret;
3543 klass = mono_class_from_mono_type (type->type);
3544 mono_class_init_checked (klass, &error);
3545 if (mono_error_set_pending_exception (&error))
3548 etype = mono_class_enum_basetype (klass);
3550 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3554 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3555 mono_error_set_pending_exception (&error);
3561 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3563 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3564 gpointer odata = (char *)other + sizeof (MonoObject);
3565 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3566 g_assert (basetype);
3571 if (eobj->vtable->klass != other->vtable->klass)
3574 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3575 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3576 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3579 return me > other ? 1 : -1; \
3582 switch (basetype->type) {
3584 COMPARE_ENUM_VALUES (guint8);
3586 COMPARE_ENUM_VALUES (gint8);
3587 case MONO_TYPE_CHAR:
3589 COMPARE_ENUM_VALUES (guint16);
3591 COMPARE_ENUM_VALUES (gint16);
3593 COMPARE_ENUM_VALUES (guint32);
3595 COMPARE_ENUM_VALUES (gint32);
3597 COMPARE_ENUM_VALUES (guint64);
3599 COMPARE_ENUM_VALUES (gint64);
3603 #undef COMPARE_ENUM_VALUES
3604 /* indicates that the enum was of an unsupported unerlying type */
3609 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3611 gpointer data = (char *)eobj + sizeof (MonoObject);
3612 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3613 g_assert (basetype);
3615 switch (basetype->type) {
3616 case MONO_TYPE_I1: {
3617 gint8 value = *((gint8*)data);
3618 return ((int)value ^ (int)value << 8);
3621 return *((guint8*)data);
3622 case MONO_TYPE_CHAR:
3624 return *((guint16*)data);
3626 case MONO_TYPE_I2: {
3627 gint16 value = *((gint16*)data);
3628 return ((int)(guint16)value | (((int)value) << 16));
3631 return *((guint32*)data);
3633 return *((gint32*)data);
3635 case MONO_TYPE_I8: {
3636 gint64 value = *((gint64*)data);
3637 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3640 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3645 ICALL_EXPORT MonoBoolean
3646 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3649 MonoDomain *domain = mono_object_domain (type);
3650 MonoClass *enumc = mono_class_from_mono_type (type->type);
3651 guint j = 0, nvalues;
3653 MonoClassField *field;
3655 guint64 field_value, previous_value = 0;
3656 gboolean sorted = TRUE;
3658 mono_class_init_checked (enumc, &error);
3659 if (mono_error_set_pending_exception (&error))
3663 if (!enumc->enumtype) {
3664 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3668 base_type = mono_class_enum_basetype (enumc)->type;
3670 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3671 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3672 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3675 while ((field = mono_class_get_fields (enumc, &iter))) {
3677 MonoTypeEnum def_type;
3679 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3681 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3683 if (mono_field_is_deleted (field))
3685 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3687 p = mono_class_get_field_default_value (field, &def_type);
3688 /* len = */ mono_metadata_decode_blob_size (p, &p);
3690 field_value = read_enum_value (p, base_type);
3691 mono_array_set (*values, guint64, j, field_value);
3693 if (previous_value > field_value)
3696 previous_value = field_value;
3704 BFLAGS_IgnoreCase = 1,
3705 BFLAGS_DeclaredOnly = 2,
3706 BFLAGS_Instance = 4,
3708 BFLAGS_Public = 0x10,
3709 BFLAGS_NonPublic = 0x20,
3710 BFLAGS_FlattenHierarchy = 0x40,
3711 BFLAGS_InvokeMethod = 0x100,
3712 BFLAGS_CreateInstance = 0x200,
3713 BFLAGS_GetField = 0x400,
3714 BFLAGS_SetField = 0x800,
3715 BFLAGS_GetProperty = 0x1000,
3716 BFLAGS_SetProperty = 0x2000,
3717 BFLAGS_ExactBinding = 0x10000,
3718 BFLAGS_SuppressChangeType = 0x20000,
3719 BFLAGS_OptionalParamBinding = 0x40000
3722 ICALL_EXPORT MonoArray*
3723 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3727 MonoClass *startklass, *klass, *refklass;
3732 char *utf8_name = NULL;
3733 int (*compare_func) (const char *s1, const char *s2) = NULL;
3734 MonoClassField *field;
3735 MonoPtrArray tmp_array;
3737 domain = ((MonoObject *)type)->vtable->domain;
3738 if (type->type->byref)
3739 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3741 klass = startklass = mono_class_from_mono_type (type->type);
3742 refklass = mono_class_from_mono_type (reftype->type);
3744 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3747 if (mono_class_has_failure (klass)) {
3748 mono_ptr_array_destroy (tmp_array);
3749 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3754 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3755 guint32 flags = mono_field_get_flags (field);
3757 if (mono_field_is_deleted_with_flags (field, flags))
3759 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3760 if (bflags & BFLAGS_Public)
3762 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3763 if (bflags & BFLAGS_NonPublic) {
3770 if (flags & FIELD_ATTRIBUTE_STATIC) {
3771 if (bflags & BFLAGS_Static)
3772 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3775 if (bflags & BFLAGS_Instance)
3783 if (utf8_name == NULL) {
3784 utf8_name = mono_string_to_utf8 (name);
3785 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3788 if (compare_func (mono_field_get_name (field), utf8_name))
3792 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3793 if (!mono_error_ok (&error))
3795 mono_ptr_array_append (tmp_array, member);
3797 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3800 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3802 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3803 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3805 mono_ptr_array_destroy (tmp_array);
3807 if (utf8_name != NULL)
3812 mono_ptr_array_destroy (tmp_array);
3813 mono_error_set_pending_exception (&error);
3818 method_nonpublic (MonoMethod* method, gboolean start_klass)
3820 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3821 case METHOD_ATTRIBUTE_ASSEM:
3822 return (start_klass || mono_defaults.generic_ilist_class);
3823 case METHOD_ATTRIBUTE_PRIVATE:
3825 case METHOD_ATTRIBUTE_PUBLIC:
3833 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3836 MonoClass *startklass;
3840 /*FIXME, use MonoBitSet*/
3841 guint32 method_slots_default [8];
3842 guint32 *method_slots = NULL;
3843 int (*compare_func) (const char *s1, const char *s2) = NULL;
3845 array = g_ptr_array_new ();
3850 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3852 /* An optimization for calls made from Delegate:CreateDelegate () */
3853 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3854 method = mono_get_delegate_invoke (klass);
3857 g_ptr_array_add (array, method);
3861 mono_class_setup_methods (klass);
3862 mono_class_setup_vtable (klass);
3863 if (mono_class_has_failure (klass))
3866 if (is_generic_parameter (&klass->byval_arg))
3867 nslots = mono_class_get_vtable_size (klass->parent);
3869 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3870 if (nslots >= sizeof (method_slots_default) * 8) {
3871 method_slots = g_new0 (guint32, nslots / 32 + 1);
3873 method_slots = method_slots_default;
3874 memset (method_slots, 0, sizeof (method_slots_default));
3877 mono_class_setup_methods (klass);
3878 mono_class_setup_vtable (klass);
3879 if (mono_class_has_failure (klass))
3883 while ((method = mono_class_get_methods (klass, &iter))) {
3885 if (method->slot != -1) {
3886 g_assert (method->slot < nslots);
3887 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3889 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3890 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3893 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3895 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3896 if (bflags & BFLAGS_Public)
3898 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3904 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3905 if (bflags & BFLAGS_Static)
3906 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3909 if (bflags & BFLAGS_Instance)
3917 if (compare_func (name, method->name))
3922 g_ptr_array_add (array, method);
3924 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3926 if (method_slots != method_slots_default)
3927 g_free (method_slots);
3932 if (method_slots != method_slots_default)
3933 g_free (method_slots);
3934 g_ptr_array_free (array, TRUE);
3936 if (mono_class_has_failure (klass)) {
3937 *ex = mono_class_get_exception_for_failure (klass);
3939 *ex = mono_get_exception_execution_engine ("Unknown error");
3944 ICALL_EXPORT MonoArray*
3945 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3947 static MonoClass *MethodInfo_array;
3951 MonoVTable *array_vtable;
3952 MonoException *ex = NULL;
3953 const char *mname = NULL;
3954 GPtrArray *method_array;
3955 MonoClass *klass, *refklass;
3958 mono_error_init (&error);
3960 if (!MethodInfo_array) {
3961 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3962 mono_memory_barrier ();
3963 MethodInfo_array = klass;
3966 klass = mono_class_from_mono_type (type->type);
3967 refklass = mono_class_from_mono_type (reftype->type);
3968 domain = ((MonoObject *)type)->vtable->domain;
3969 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3970 if (!is_ok (&error)) {
3971 mono_error_set_pending_exception (&error);
3974 if (type->type->byref) {
3975 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3976 mono_error_set_pending_exception (&error);
3982 mname = mono_string_to_utf8 (name);
3984 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3985 g_free ((char*)mname);
3987 mono_set_pending_exception (ex);
3991 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3992 if (!mono_error_ok (&error)) {
3993 mono_error_set_pending_exception (&error);
3997 for (i = 0; i < method_array->len; ++i) {
3998 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3999 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
4000 if (!mono_error_ok (&error))
4002 mono_array_setref (res, i, rm);
4006 g_ptr_array_free (method_array, TRUE);
4007 if (!mono_error_ok (&error))
4008 mono_set_pending_exception (mono_error_convert_to_exception (&error));
4012 ICALL_EXPORT MonoArray*
4013 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4016 MonoClass *startklass, *klass, *refklass;
4021 gpointer iter = NULL;
4022 MonoPtrArray tmp_array;
4025 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
4027 domain = ((MonoObject *)type)->vtable->domain;
4028 if (type->type->byref)
4029 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
4030 klass = startklass = mono_class_from_mono_type (type->type);
4031 refklass = mono_class_from_mono_type (reftype->type);
4033 mono_class_setup_methods (klass);
4034 if (mono_class_has_failure (klass)) {
4035 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
4040 while ((method = mono_class_get_methods (klass, &iter))) {
4042 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
4044 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4045 if (bflags & BFLAGS_Public)
4048 if (bflags & BFLAGS_NonPublic)
4054 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4055 if (bflags & BFLAGS_Static)
4056 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4059 if (bflags & BFLAGS_Instance)
4065 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
4066 if (!mono_error_ok (&error)) {
4067 mono_error_set_pending_exception (&error);
4071 mono_ptr_array_append (tmp_array, member);
4074 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
4076 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4077 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4079 mono_ptr_array_destroy (tmp_array);
4085 property_hash (gconstpointer data)
4087 MonoProperty *prop = (MonoProperty*)data;
4089 return g_str_hash (prop->name);
4093 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
4095 if (method1->is_inflated)
4096 method1 = ((MonoMethodInflated*) method1)->declaring;
4097 if (method2->is_inflated)
4098 method2 = ((MonoMethodInflated*) method2)->declaring;
4100 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4104 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4106 // Properties are hide-by-name-and-signature
4107 if (!g_str_equal (prop1->name, prop2->name))
4110 /* If we see a property in a generic method, we want to
4111 compare the generic signatures, not the inflated signatures
4112 because we might conflate two properties that were
4116 public T this[T t] { getter { return t; } } // method 1
4117 public U this[U u] { getter { return u; } } // method 2
4120 If we see int Foo<int,int>::Item[int] we need to know if
4121 the indexer came from method 1 or from method 2, and we
4122 shouldn't conflate them. (Bugzilla 36283)
4124 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
4127 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4134 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4139 return method_nonpublic (accessor, start_klass);
4142 ICALL_EXPORT MonoArray*
4143 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4147 MonoClass *startklass, *klass;
4153 gchar *propname = NULL;
4154 int (*compare_func) (const char *s1, const char *s2) = NULL;
4156 GHashTable *properties = NULL;
4157 MonoPtrArray tmp_array;
4159 mono_error_init (&error);
4161 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4163 domain = ((MonoObject *)type)->vtable->domain;
4164 if (type->type->byref)
4165 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
4166 klass = startklass = mono_class_from_mono_type (type->type);
4169 propname = mono_string_to_utf8 (name);
4170 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4173 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4175 mono_class_setup_methods (klass);
4176 mono_class_setup_vtable (klass);
4177 if (mono_class_has_failure (klass))
4181 while ((prop = mono_class_get_properties (klass, &iter))) {
4187 flags = method->flags;
4190 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4191 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4192 if (bflags & BFLAGS_Public)
4194 } else if (bflags & BFLAGS_NonPublic) {
4195 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4196 property_accessor_nonpublic(prop->set, startklass == klass)) {
4203 if (flags & METHOD_ATTRIBUTE_STATIC) {
4204 if (bflags & BFLAGS_Static)
4205 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4208 if (bflags & BFLAGS_Instance)
4217 if (compare_func (propname, prop->name))
4221 if (g_hash_table_lookup (properties, prop))
4224 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4227 mono_ptr_array_append (tmp_array, pr);
4229 g_hash_table_insert (properties, prop, prop);
4231 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4234 g_hash_table_destroy (properties);
4237 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4238 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4239 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4241 mono_ptr_array_destroy (tmp_array);
4248 if (mono_class_has_failure (klass)) {
4249 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4254 g_hash_table_destroy (properties);
4257 mono_ptr_array_destroy (tmp_array);
4259 mono_error_set_pending_exception (&error);
4265 event_hash (gconstpointer data)
4267 MonoEvent *event = (MonoEvent*)data;
4269 return g_str_hash (event->name);
4273 event_equal (MonoEvent *event1, MonoEvent *event2)
4275 // Events are hide-by-name
4276 return g_str_equal (event1->name, event2->name);
4279 ICALL_EXPORT MonoArray*
4280 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4284 MonoClass *startklass, *klass;
4290 char *utf8_name = NULL;
4291 int (*compare_func) (const char *s1, const char *s2) = NULL;
4292 GHashTable *events = NULL;
4293 MonoPtrArray tmp_array;
4295 mono_error_init (&error);
4297 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4299 domain = mono_object_domain (type);
4300 if (type->type->byref)
4301 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4302 klass = startklass = mono_class_from_mono_type (type->type);
4304 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4306 mono_class_setup_methods (klass);
4307 mono_class_setup_vtable (klass);
4308 if (mono_class_has_failure (klass))
4312 while ((event = mono_class_get_events (klass, &iter))) {
4314 method = event->add;
4316 method = event->remove;
4318 method = event->raise;
4320 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4321 if (bflags & BFLAGS_Public)
4323 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4324 if (bflags & BFLAGS_NonPublic)
4329 if (bflags & BFLAGS_NonPublic)
4335 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4336 if (bflags & BFLAGS_Static)
4337 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4340 if (bflags & BFLAGS_Instance)
4345 if (bflags & BFLAGS_Instance)
4351 if (utf8_name == NULL) {
4352 utf8_name = mono_string_to_utf8 (name);
4353 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4356 if (compare_func (event->name, utf8_name))
4360 if (g_hash_table_lookup (events, event))
4363 MonoReflectionEvent *ev_obj;
4364 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4367 mono_ptr_array_append (tmp_array, ev_obj);
4369 g_hash_table_insert (events, event, event);
4371 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4374 g_hash_table_destroy (events);
4376 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4378 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4379 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4381 mono_ptr_array_destroy (tmp_array);
4383 if (utf8_name != NULL)
4389 if (mono_class_has_failure (klass)) {
4390 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4396 g_hash_table_destroy (events);
4397 if (utf8_name != NULL)
4400 mono_ptr_array_destroy (tmp_array);
4402 mono_error_set_pending_exception (&error);
4406 ICALL_EXPORT MonoArray*
4407 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4410 MonoReflectionType *rt;
4413 MonoArray *res = NULL;
4418 MonoPtrArray tmp_array;
4420 mono_error_init (&error);
4422 domain = ((MonoObject *)type)->vtable->domain;
4423 if (type->type->byref)
4424 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4425 klass = mono_class_from_mono_type (type->type);
4428 * If a nested type is generic, return its generic type definition.
4429 * Note that this means that the return value is essentially the set
4430 * of nested types of the generic type definition of @klass.
4432 * A note in MSDN claims that a generic type definition can have
4433 * nested types that aren't generic. In any case, the container of that
4434 * nested type would be the generic type definition.
4436 if (klass->generic_class)
4437 klass = klass->generic_class->container_class;
4439 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4441 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4443 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4444 if (bflags & BFLAGS_Public)
4447 if (bflags & BFLAGS_NonPublic)
4455 str = mono_string_to_utf8 (name);
4456 mono_identifier_unescape_type_name_chars (str);
4459 if (strcmp (nested->name, str))
4463 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4464 if (!is_ok (&error))
4467 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4470 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4472 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4473 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4476 mono_ptr_array_destroy (tmp_array);
4480 mono_error_set_pending_exception (&error);
4484 ICALL_EXPORT MonoReflectionType*
4485 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4488 MonoReflectionType *ret;
4490 MonoType *type = NULL;
4491 MonoTypeNameParse info;
4492 gboolean type_resolve;
4494 /* On MS.NET, this does not fire a TypeResolve event */
4495 type_resolve = TRUE;
4496 str = mono_string_to_utf8 (name);
4497 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4498 if (!mono_reflection_parse_type (str, &info)) {
4500 mono_reflection_free_type_info (&info);
4502 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4505 /*g_print ("failed parse\n");*/
4509 if (info.assembly.name) {
4511 mono_reflection_free_type_info (&info);
4513 /* 1.0 and 2.0 throw different exceptions */
4514 if (mono_defaults.generic_ilist_class)
4515 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4517 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4523 if (module != NULL) {
4524 if (module->image) {
4525 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4526 if (!is_ok (&error)) {
4528 mono_reflection_free_type_info (&info);
4529 mono_error_set_pending_exception (&error);
4536 if (assembly_is_dynamic (assembly->assembly)) {
4537 /* Enumerate all modules */
4538 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4542 if (abuilder->modules) {
4543 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4544 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4545 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4546 if (!is_ok (&error)) {
4548 mono_reflection_free_type_info (&info);
4549 mono_error_set_pending_exception (&error);
4557 if (!type && abuilder->loaded_modules) {
4558 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4559 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4560 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4561 if (!is_ok (&error)) {
4563 mono_reflection_free_type_info (&info);
4564 mono_error_set_pending_exception (&error);
4573 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4574 if (!is_ok (&error)) {
4576 mono_reflection_free_type_info (&info);
4577 mono_error_set_pending_exception (&error);
4582 mono_reflection_free_type_info (&info);
4584 MonoException *e = NULL;
4587 e = mono_get_exception_type_load (name, NULL);
4590 mono_set_pending_exception (e);
4594 if (type->type == MONO_TYPE_CLASS) {
4595 MonoClass *klass = mono_type_get_class (type);
4597 /* need to report exceptions ? */
4598 if (throwOnError && mono_class_has_failure (klass)) {
4599 /* report SecurityException (or others) that occured when loading the assembly */
4600 MonoException *exc = mono_class_get_exception_for_failure (klass);
4601 mono_set_pending_exception (exc);
4606 /* g_print ("got it\n"); */
4607 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4608 mono_error_set_pending_exception (&error);
4614 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4617 gchar *shadow_ini_file;
4620 /* Check for shadow-copied assembly */
4621 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4622 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4624 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4625 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4631 g_free (shadow_ini_file);
4632 if (content != NULL) {
4635 *filename = content;
4642 ICALL_EXPORT MonoString *
4643 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4645 MonoDomain *domain = mono_object_domain (assembly);
4646 MonoAssembly *mass = assembly->assembly;
4647 MonoString *res = NULL;
4652 if (g_path_is_absolute (mass->image->name)) {
4653 absolute = g_strdup (mass->image->name);
4654 dirname = g_path_get_dirname (absolute);
4656 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4657 dirname = g_strdup (mass->basedir);
4660 replace_shadow_path (domain, dirname, &absolute);
4665 for (i = strlen (absolute) - 1; i >= 0; i--)
4666 if (absolute [i] == '\\')
4671 uri = g_filename_to_uri (absolute, NULL, NULL);
4673 const char *prepend = "file://";
4675 if (*absolute == '/' && *(absolute + 1) == '/') {
4678 prepend = "file:///";
4681 uri = g_strconcat (prepend, absolute, NULL);
4685 res = mono_string_new (domain, uri);
4692 ICALL_EXPORT MonoBoolean
4693 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4695 MonoAssembly *mass = assembly->assembly;
4697 return mass->in_gac;
4700 ICALL_EXPORT MonoReflectionAssembly*
4701 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4706 MonoImageOpenStatus status;
4707 MonoReflectionAssembly* result = NULL;
4709 name = mono_string_to_utf8 (mname);
4710 res = mono_assembly_load_with_partial_name (name, &status);
4716 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4718 mono_error_set_pending_exception (&error);
4722 ICALL_EXPORT MonoString *
4723 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4725 MonoDomain *domain = mono_object_domain (assembly);
4728 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4733 ICALL_EXPORT MonoBoolean
4734 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4736 return assembly->assembly->ref_only;
4739 ICALL_EXPORT MonoString *
4740 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4742 MonoDomain *domain = mono_object_domain (assembly);
4744 return mono_string_new (domain, assembly->assembly->image->version);
4747 ICALL_EXPORT MonoReflectionMethod*
4748 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4751 MonoReflectionMethod *res = NULL;
4754 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4758 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4759 if (!mono_error_ok (&error))
4762 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4765 if (!mono_error_ok (&error))
4766 mono_error_set_pending_exception (&error);
4770 ICALL_EXPORT MonoReflectionModule*
4771 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4774 MonoReflectionModule *result = NULL;
4775 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4776 if (!mono_error_ok (&error))
4777 mono_error_set_pending_exception (&error);
4781 ICALL_EXPORT MonoArray*
4782 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4784 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4785 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4789 for (i = 0; i < table->rows; ++i) {
4790 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4791 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4797 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4799 static MonoMethod *create_version = NULL;
4803 mono_error_init (error);
4806 if (!create_version) {
4807 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4808 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4809 g_assert (create_version);
4810 mono_method_desc_free (desc);
4816 args [3] = &revision;
4817 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4818 return_val_if_nok (error, NULL);
4820 mono_runtime_invoke_checked (create_version, result, args, error);
4821 return_val_if_nok (error, NULL);
4826 ICALL_EXPORT MonoArray*
4827 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4831 MonoDomain *domain = mono_object_domain (assembly);
4833 static MonoMethod *create_culture = NULL;
4834 MonoImage *image = assembly->assembly->image;
4838 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4841 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4843 if (count > 0 && !create_culture) {
4844 MonoMethodDesc *desc = mono_method_desc_new (
4845 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4846 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4847 g_assert (create_culture);
4848 mono_method_desc_free (desc);
4851 for (i = 0; i < count; i++) {
4852 MonoObject *version;
4853 MonoReflectionAssemblyName *aname;
4854 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4856 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4858 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4859 domain, mono_class_get_assembly_name_class (), &error);
4860 if (mono_error_set_pending_exception (&error))
4863 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4865 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4866 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4867 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4868 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4869 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4870 aname->versioncompat = 1; /* SameMachine (default) */
4871 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4873 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4874 if (mono_error_set_pending_exception (&error))
4877 MONO_OBJECT_SETREF (aname, version, version);
4879 if (create_culture) {
4881 MonoBoolean assembly_ref = 1;
4882 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4883 args [1] = &assembly_ref;
4885 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4886 if (mono_error_set_pending_exception (&error))
4889 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4892 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4893 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4894 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4896 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4897 /* public key token isn't copied - the class library will
4898 automatically generate it from the public key if required */
4899 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4900 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4902 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4903 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4906 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4909 /* note: this function doesn't return the codebase on purpose (i.e. it can
4910 be used under partial trust as path information isn't present). */
4912 mono_array_setref (result, i, aname);
4917 /* move this in some file in mono/util/ */
4919 g_concat_dir_and_file (const char *dir, const char *file)
4921 g_return_val_if_fail (dir != NULL, NULL);
4922 g_return_val_if_fail (file != NULL, NULL);
4925 * If the directory name doesn't have a / on the end, we need
4926 * to add one so we get a proper path to the file
4928 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4929 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4931 return g_strconcat (dir, file, NULL);
4935 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4938 char *n = mono_string_to_utf8 (name);
4939 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4941 guint32 cols [MONO_MANIFEST_SIZE];
4942 guint32 impl, file_idx;
4946 for (i = 0; i < table->rows; ++i) {
4947 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4948 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4949 if (strcmp (val, n) == 0)
4953 if (i == table->rows)
4956 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4959 * this code should only be called after obtaining the
4960 * ResourceInfo and handling the other cases.
4962 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4963 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4965 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4970 module = assembly->assembly->image;
4973 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4974 if (mono_error_set_pending_exception (&error))
4976 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4978 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4981 ICALL_EXPORT gboolean
4982 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4985 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4987 guint32 cols [MONO_MANIFEST_SIZE];
4988 guint32 file_cols [MONO_FILE_SIZE];
4992 n = mono_string_to_utf8 (name);
4993 for (i = 0; i < table->rows; ++i) {
4994 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4995 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4996 if (strcmp (val, n) == 0)
5000 if (i == table->rows)
5003 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
5004 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
5007 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
5008 case MONO_IMPLEMENTATION_FILE:
5009 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5010 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5011 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
5012 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
5013 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
5014 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
5017 info->location = RESOURCE_LOCATION_EMBEDDED;
5020 case MONO_IMPLEMENTATION_ASSEMBLYREF:
5021 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5022 mono_assembly_load_reference (assembly->assembly->image, i - 1);
5023 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
5024 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
5025 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
5027 mono_set_pending_exception (ex);
5030 MonoReflectionAssembly *assm_obj;
5031 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5033 mono_error_set_pending_exception (&error);
5036 MONO_OBJECT_SETREF (info, assembly, assm_obj);
5038 /* Obtain info recursively */
5039 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5040 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5043 case MONO_IMPLEMENTATION_EXP_TYPE:
5044 g_assert_not_reached ();
5052 ICALL_EXPORT MonoObject*
5053 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
5055 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5056 MonoArray *result = NULL;
5061 /* check hash if needed */
5063 n = mono_string_to_utf8 (name);
5064 for (i = 0; i < table->rows; ++i) {
5065 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5066 if (strcmp (val, n) == 0) {
5069 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5070 fn = mono_string_new (mono_object_domain (assembly), n);
5072 return (MonoObject*)fn;
5080 for (i = 0; i < table->rows; ++i) {
5081 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5085 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
5088 for (i = 0; i < table->rows; ++i) {
5089 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5090 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5091 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5092 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5097 return (MonoObject*)result;
5100 ICALL_EXPORT MonoArray*
5101 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5104 MonoDomain *domain = mono_domain_get();
5107 int i, j, file_count = 0;
5108 MonoImage **modules;
5109 guint32 module_count, real_module_count;
5110 MonoTableInfo *table;
5111 guint32 cols [MONO_FILE_SIZE];
5112 MonoImage *image = assembly->assembly->image;
5114 g_assert (image != NULL);
5115 g_assert (!assembly_is_dynamic (assembly->assembly));
5117 table = &image->tables [MONO_TABLE_FILE];
5118 file_count = table->rows;
5120 modules = image->modules;
5121 module_count = image->module_count;
5123 real_module_count = 0;
5124 for (i = 0; i < module_count; ++i)
5126 real_module_count ++;
5128 klass = mono_class_get_module_class ();
5129 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
5131 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5132 if (mono_error_set_pending_exception (&error))
5135 mono_array_setref (res, 0, image_obj);
5137 for (i = 0; i < module_count; ++i)
5139 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5140 if (mono_error_set_pending_exception (&error))
5142 mono_array_setref (res, j, rm);
5146 for (i = 0; i < file_count; ++i, ++j) {
5147 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5148 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5149 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5150 if (mono_error_set_pending_exception (&error))
5152 mono_array_setref (res, j, rm);
5155 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5157 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5158 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5161 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5162 if (mono_error_set_pending_exception (&error))
5164 mono_array_setref (res, j, rm);
5171 ICALL_EXPORT MonoReflectionMethod*
5172 ves_icall_GetCurrentMethod (void)
5174 MonoReflectionMethod *res = NULL;
5177 MonoMethod *m = mono_method_get_last_managed ();
5180 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5184 while (m->is_inflated)
5185 m = ((MonoMethodInflated*)m)->declaring;
5187 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5188 mono_error_set_pending_exception (&error);
5194 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5197 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5200 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5201 //method is inflated, we should inflate it on the other class
5202 MonoGenericContext ctx;
5203 ctx.method_inst = inflated->context.method_inst;
5204 ctx.class_inst = inflated->context.class_inst;
5205 if (klass->generic_class)
5206 ctx.class_inst = klass->generic_class->context.class_inst;
5207 else if (klass->generic_container)
5208 ctx.class_inst = klass->generic_container->context.class_inst;
5209 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5210 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5214 mono_class_setup_methods (method->klass);
5215 if (mono_class_has_failure (method->klass))
5217 for (i = 0; i < method->klass->method.count; ++i) {
5218 if (method->klass->methods [i] == method) {
5223 mono_class_setup_methods (klass);
5224 if (mono_class_has_failure (klass))
5226 g_assert (offset >= 0 && offset < klass->method.count);
5227 return klass->methods [offset];
5230 ICALL_EXPORT MonoReflectionMethod*
5231 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5233 MonoReflectionMethod *res = NULL;
5237 klass = mono_class_from_mono_type (type);
5238 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5240 if (method->klass != klass) {
5241 method = mono_method_get_equivalent_method (method, klass);
5246 klass = method->klass;
5247 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5248 mono_error_set_pending_exception (&error);
5252 ICALL_EXPORT MonoReflectionMethodBody*
5253 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5256 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5257 mono_error_set_pending_exception (&error);
5261 ICALL_EXPORT MonoReflectionAssembly*
5262 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5265 MonoReflectionAssembly *result;
5266 MonoMethod *dest = NULL;
5268 mono_stack_walk_no_il (get_executing, &dest);
5270 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5272 mono_error_set_pending_exception (&error);
5277 ICALL_EXPORT MonoReflectionAssembly*
5278 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5281 MonoReflectionAssembly *result;
5282 MonoDomain* domain = mono_domain_get ();
5284 if (!domain->entry_assembly)
5287 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5289 mono_error_set_pending_exception (&error);
5293 ICALL_EXPORT MonoReflectionAssembly*
5294 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5299 MonoReflectionAssembly *result;
5302 mono_stack_walk_no_il (get_executing, &dest);
5304 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5308 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5311 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5313 mono_error_set_pending_exception (&error);
5317 ICALL_EXPORT MonoString *
5318 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5319 gboolean assembly_qualified)
5321 MonoDomain *domain = mono_object_domain (object);
5322 MonoTypeNameFormat format;
5327 format = assembly_qualified ?
5328 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5329 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5331 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5333 name = mono_type_get_name_full (object->type, format);
5337 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5342 res = mono_string_new (domain, name);
5349 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5352 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5354 mono_class_init_checked (klass, &error);
5355 mono_error_set_pending_exception (&error);
5356 return mono_security_core_clr_class_level (klass);
5360 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5362 MonoClassField *field = rfield->field;
5363 return mono_security_core_clr_field_level (field, TRUE);
5367 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5369 MonoMethod *method = rfield->method;
5370 return mono_security_core_clr_method_level (method, TRUE);
5374 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)
5376 static MonoMethod *create_culture = NULL;
5380 const char *pkey_ptr;
5382 MonoBoolean assembly_ref = 0;
5384 mono_error_init (error);
5386 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5387 aname->major = name->major;
5388 aname->minor = name->minor;
5389 aname->build = name->build;
5390 aname->flags = name->flags;
5391 aname->revision = name->revision;
5392 aname->hashalg = name->hash_alg;
5393 aname->versioncompat = 1; /* SameMachine (default) */
5394 aname->processor_architecture = name->arch;
5396 if (by_default_version) {
5397 MonoObject *version;
5399 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5400 return_if_nok (error);
5402 MONO_OBJECT_SETREF (aname, version, version);
5406 if (absolute != NULL && *absolute != '\0') {
5407 const gchar *prepend = "file://";
5410 codebase = g_strdup (absolute);
5415 for (i = strlen (codebase) - 1; i >= 0; i--)
5416 if (codebase [i] == '\\')
5419 if (*codebase == '/' && *(codebase + 1) == '/') {
5422 prepend = "file:///";
5426 result = g_strconcat (prepend, codebase, NULL);
5432 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5436 if (!create_culture) {
5437 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5438 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5439 g_assert (create_culture);
5440 mono_method_desc_free (desc);
5443 if (name->culture) {
5444 args [0] = mono_string_new (domain, name->culture);
5445 args [1] = &assembly_ref;
5447 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5448 return_if_nok (error);
5450 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5453 if (name->public_key) {
5454 pkey_ptr = (char*)name->public_key;
5455 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5457 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5458 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5459 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5460 } else if (default_publickey) {
5461 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5462 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5465 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5466 if (name->public_key_token [0]) {
5470 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5471 p = mono_array_addr (aname->keyToken, char, 0);
5473 for (i = 0, j = 0; i < 8; i++) {
5474 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5475 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5478 } else if (default_token) {
5479 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5483 ICALL_EXPORT MonoString *
5484 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5486 MonoDomain *domain = mono_object_domain (assembly);
5487 MonoAssembly *mass = assembly->assembly;
5491 name = mono_stringify_assembly_name (&mass->aname);
5492 res = mono_string_new (domain, name);
5499 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5503 MonoAssembly *mass = assembly->assembly;
5505 if (g_path_is_absolute (mass->image->name)) {
5506 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5507 mono_error_set_pending_exception (&error);
5510 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5512 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5513 mono_error_set_pending_exception (&error);
5519 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5523 MonoImageOpenStatus status = MONO_IMAGE_OK;
5526 MonoAssemblyName name;
5529 filename = mono_string_to_utf8 (fname);
5531 dirname = g_path_get_dirname (filename);
5532 replace_shadow_path (mono_domain_get (), dirname, &filename);
5535 image = mono_image_open (filename, &status);
5541 if (status == MONO_IMAGE_IMAGE_INVALID)
5542 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5544 exc = mono_get_exception_file_not_found2 (NULL, fname);
5545 mono_set_pending_exception (exc);
5549 res = mono_assembly_fill_assembly_name (image, &name);
5551 mono_image_close (image);
5553 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5557 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5558 mono_error_set_pending_exception (&error);
5560 mono_image_close (image);
5564 ICALL_EXPORT MonoBoolean
5565 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5566 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5568 MonoBoolean result = FALSE;
5569 MonoDeclSecurityEntry entry;
5571 /* SecurityAction.RequestMinimum */
5572 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5573 *minimum = entry.blob;
5574 *minLength = entry.size;
5577 /* SecurityAction.RequestOptional */
5578 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5579 *optional = entry.blob;
5580 *optLength = entry.size;
5583 /* SecurityAction.RequestRefuse */
5584 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5585 *refused = entry.blob;
5586 *refLength = entry.size;
5594 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5596 guint32 attrs, visibility;
5598 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5599 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5600 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5603 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5609 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5611 MonoReflectionType *rt;
5614 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5617 mono_error_init (error);
5619 /* we start the count from 1 because we skip the special type <Module> */
5622 for (i = 1; i < tdef->rows; ++i) {
5623 if (mono_module_type_is_visible (tdef, image, i + 1))
5627 count = tdef->rows - 1;
5629 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5630 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5632 for (i = 1; i < tdef->rows; ++i) {
5633 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5634 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5637 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5638 return_val_if_nok (error, NULL);
5640 mono_array_setref (res, count, rt);
5642 MonoException *ex = mono_error_convert_to_exception (error);
5643 mono_array_setref (*exceptions, count, ex);
5652 ICALL_EXPORT MonoArray*
5653 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5656 MonoArray *res = NULL;
5657 MonoArray *exceptions = NULL;
5658 MonoImage *image = NULL;
5659 MonoTableInfo *table = NULL;
5662 int i, len, ex_count;
5664 domain = mono_object_domain (assembly);
5666 g_assert (!assembly_is_dynamic (assembly->assembly));
5667 image = assembly->assembly->image;
5668 table = &image->tables [MONO_TABLE_FILE];
5669 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5670 if (mono_error_set_pending_exception (&error))
5673 /* Append data from all modules in the assembly */
5674 for (i = 0; i < table->rows; ++i) {
5675 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5676 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5681 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5682 if (mono_error_set_pending_exception (&error))
5686 /* Append the new types to the end of the array */
5687 if (mono_array_length (res2) > 0) {
5689 MonoArray *res3, *ex3;
5691 len1 = mono_array_length (res);
5692 len2 = mono_array_length (res2);
5694 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5695 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5696 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5699 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5700 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5701 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5708 /* the ReflectionTypeLoadException must have all the types (Types property),
5709 * NULL replacing types which throws an exception. The LoaderException must
5710 * contain all exceptions for NULL items.
5713 len = mono_array_length (res);
5716 for (i = 0; i < len; i++) {
5717 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5721 klass = mono_type_get_class (t->type);
5722 if ((klass != NULL) && mono_class_has_failure (klass)) {
5723 /* keep the class in the list */
5724 list = g_list_append (list, klass);
5725 /* and replace Type with NULL */
5726 mono_array_setref (res, i, NULL);
5733 if (list || ex_count) {
5735 MonoException *exc = NULL;
5736 MonoArray *exl = NULL;
5737 int j, length = g_list_length (list) + ex_count;
5739 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5740 /* Types for which mono_class_get_checked () succeeded */
5741 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5742 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5743 mono_array_setref (exl, i, exc);
5745 /* Types for which it don't */
5746 for (j = 0; j < mono_array_length (exceptions); ++j) {
5747 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5749 g_assert (i < length);
5750 mono_array_setref (exl, i, exc);
5757 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5758 if (!is_ok (&error)) {
5759 mono_error_set_pending_exception (&error);
5762 mono_set_pending_exception (exc);
5769 ICALL_EXPORT gboolean
5770 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5773 MonoAssemblyName aname;
5774 MonoDomain *domain = mono_object_domain (name);
5776 gboolean is_version_defined;
5777 gboolean is_token_defined;
5779 aname.public_key = NULL;
5780 val = mono_string_to_utf8 (assname);
5781 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5782 g_free ((guint8*) aname.public_key);
5787 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5788 mono_error_set_pending_exception (&error);
5790 mono_assembly_name_free (&aname);
5791 g_free ((guint8*) aname.public_key);
5797 ICALL_EXPORT MonoReflectionType*
5798 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5801 MonoReflectionType *ret;
5802 MonoDomain *domain = mono_object_domain (module);
5805 g_assert (module->image);
5807 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5808 /* These images do not have a global type */
5811 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5812 if (!mono_error_ok (&error)) {
5813 mono_error_set_pending_exception (&error);
5817 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5818 if (!mono_error_ok (&error)) {
5819 mono_error_set_pending_exception (&error);
5827 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5829 /*if (module->image)
5830 mono_image_close (module->image);*/
5833 ICALL_EXPORT MonoString*
5834 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5836 MonoDomain *domain = mono_object_domain (module);
5838 g_assert (module->image);
5839 return mono_string_new (domain, module->image->guid);
5842 ICALL_EXPORT gpointer
5843 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5846 if (module->image && module->image->is_module_handle)
5847 return module->image->raw_data;
5850 return (gpointer) (-1);
5854 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5856 if (image_is_dynamic (image)) {
5857 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5858 *pe_kind = dyn->pe_kind;
5859 *machine = dyn->machine;
5862 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5863 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5868 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5870 return (image->md_version_major << 16) | (image->md_version_minor);
5873 ICALL_EXPORT MonoArray*
5874 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5877 MonoArray *exceptions;
5881 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5885 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5886 if (mono_error_set_pending_exception (&error))
5889 for (i = 0; i < mono_array_length (exceptions); ++i) {
5890 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5892 mono_set_pending_exception (ex);
5901 mono_memberref_is_method (MonoImage *image, guint32 token)
5903 if (!image_is_dynamic (image)) {
5904 guint32 cols [MONO_MEMBERREF_SIZE];
5906 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5907 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5908 mono_metadata_decode_blob_size (sig, &sig);
5909 return (*sig != 0x6);
5912 MonoClass *handle_class;
5914 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5915 mono_error_cleanup (&error); /* just probing, ignore error */
5919 return mono_defaults.methodhandle_class == handle_class;
5924 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5927 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5928 mono_array_addr (type_args, MonoType*, 0));
5930 context->class_inst = NULL;
5932 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5933 mono_array_addr (method_args, MonoType*, 0));
5935 context->method_inst = NULL;
5938 ICALL_EXPORT MonoType*
5939 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5942 int table = mono_metadata_token_table (token);
5943 int index = mono_metadata_token_index (token);
5944 MonoGenericContext context;
5947 *resolve_error = ResolveTokenError_Other;
5949 /* Validate token */
5950 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5951 (table != MONO_TABLE_TYPESPEC)) {
5952 *resolve_error = ResolveTokenError_BadTable;
5956 if (image_is_dynamic (image)) {
5957 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5958 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5959 mono_error_cleanup (&error);
5960 return klass ? &klass->byval_arg : NULL;
5963 init_generic_context_from_args (&context, type_args, method_args);
5964 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5965 mono_error_cleanup (&error);
5966 return klass ? &klass->byval_arg : NULL;
5969 if ((index <= 0) || (index > image->tables [table].rows)) {
5970 *resolve_error = ResolveTokenError_OutOfRange;
5974 init_generic_context_from_args (&context, type_args, method_args);
5975 klass = mono_class_get_checked (image, token, &error);
5977 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5978 if (!mono_error_ok (&error)) {
5979 mono_error_set_pending_exception (&error);
5984 return &klass->byval_arg;
5989 ICALL_EXPORT MonoMethod*
5990 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5993 int table = mono_metadata_token_table (token);
5994 int index = mono_metadata_token_index (token);
5995 MonoGenericContext context;
5998 *resolve_error = ResolveTokenError_Other;
6000 /* Validate token */
6001 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
6002 (table != MONO_TABLE_MEMBERREF)) {
6003 *resolve_error = ResolveTokenError_BadTable;
6007 if (image_is_dynamic (image)) {
6008 if (table == MONO_TABLE_METHOD) {
6009 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6010 mono_error_cleanup (&error);
6014 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
6015 *resolve_error = ResolveTokenError_BadTable;
6019 init_generic_context_from_args (&context, type_args, method_args);
6020 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6021 mono_error_cleanup (&error);
6025 if ((index <= 0) || (index > image->tables [table].rows)) {
6026 *resolve_error = ResolveTokenError_OutOfRange;
6029 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6030 *resolve_error = ResolveTokenError_BadTable;
6034 init_generic_context_from_args (&context, type_args, method_args);
6035 method = mono_get_method_checked (image, token, NULL, &context, &error);
6036 mono_error_set_pending_exception (&error);
6041 ICALL_EXPORT MonoString*
6042 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6045 int index = mono_metadata_token_index (token);
6047 *resolve_error = ResolveTokenError_Other;
6049 /* Validate token */
6050 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6051 *resolve_error = ResolveTokenError_BadTable;
6055 if (image_is_dynamic (image)) {
6056 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6057 mono_error_cleanup (&error);
6061 if ((index <= 0) || (index >= image->heap_us.size)) {
6062 *resolve_error = ResolveTokenError_OutOfRange;
6066 /* FIXME: What to do if the index points into the middle of a string ? */
6068 return mono_ldstr (mono_domain_get (), image, index);
6071 ICALL_EXPORT MonoClassField*
6072 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6076 int table = mono_metadata_token_table (token);
6077 int index = mono_metadata_token_index (token);
6078 MonoGenericContext context;
6079 MonoClassField *field;
6081 *resolve_error = ResolveTokenError_Other;
6083 /* Validate token */
6084 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6085 *resolve_error = ResolveTokenError_BadTable;
6089 if (image_is_dynamic (image)) {
6090 if (table == MONO_TABLE_FIELD) {
6091 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6092 mono_error_cleanup (&error);
6096 if (mono_memberref_is_method (image, token)) {
6097 *resolve_error = ResolveTokenError_BadTable;
6101 init_generic_context_from_args (&context, type_args, method_args);
6102 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6103 mono_error_cleanup (&error);
6107 if ((index <= 0) || (index > image->tables [table].rows)) {
6108 *resolve_error = ResolveTokenError_OutOfRange;
6111 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6112 *resolve_error = ResolveTokenError_BadTable;
6116 init_generic_context_from_args (&context, type_args, method_args);
6117 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6118 mono_error_set_pending_exception (&error);
6124 ICALL_EXPORT MonoObject*
6125 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6129 int table = mono_metadata_token_table (token);
6131 *error = ResolveTokenError_Other;
6134 case MONO_TABLE_TYPEDEF:
6135 case MONO_TABLE_TYPEREF:
6136 case MONO_TABLE_TYPESPEC: {
6137 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6139 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6140 mono_error_set_pending_exception (&merror);
6147 case MONO_TABLE_METHOD:
6148 case MONO_TABLE_METHODSPEC: {
6149 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6151 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6152 mono_error_set_pending_exception (&merror);
6158 case MONO_TABLE_FIELD: {
6159 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6161 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6162 mono_error_set_pending_exception (&merror);
6168 case MONO_TABLE_MEMBERREF:
6169 if (mono_memberref_is_method (image, token)) {
6170 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6172 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6173 mono_error_set_pending_exception (&merror);
6180 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6182 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6183 mono_error_set_pending_exception (&merror);
6192 *error = ResolveTokenError_BadTable;
6198 ICALL_EXPORT MonoArray*
6199 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
6201 int table = mono_metadata_token_table (token);
6202 int idx = mono_metadata_token_index (token);
6203 MonoTableInfo *tables = image->tables;
6208 *error = ResolveTokenError_OutOfRange;
6210 /* FIXME: Support other tables ? */
6211 if (table != MONO_TABLE_STANDALONESIG)
6214 if (image_is_dynamic (image))
6217 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6220 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6222 ptr = mono_metadata_blob_heap (image, sig);
6223 len = mono_metadata_decode_blob_size (ptr, &ptr);
6225 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
6226 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6230 ICALL_EXPORT MonoReflectionType*
6231 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6234 MonoReflectionType *ret;
6236 int isbyref = 0, rank;
6237 char *str = mono_string_to_utf8 (smodifiers);
6240 klass = mono_class_from_mono_type (tb->type.type);
6242 /* logic taken from mono_reflection_parse_type(): keep in sync */
6246 if (isbyref) { /* only one level allowed by the spec */
6255 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6256 mono_error_set_pending_exception (&error);
6260 klass = mono_ptr_class_get (&klass->byval_arg);
6261 mono_class_init (klass);
6272 else if (*p != '*') { /* '*' means unknown lower bound */
6283 klass = mono_array_class_get (klass, rank);
6284 mono_class_init (klass);
6293 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6294 mono_error_set_pending_exception (&error);
6299 ICALL_EXPORT MonoBoolean
6300 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6306 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6312 check_for_invalid_type (MonoClass *klass, MonoError *error)
6317 mono_error_init (error);
6319 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6322 name = mono_type_get_full_name (klass);
6323 str = mono_string_new (mono_domain_get (), name);
6325 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6328 ICALL_EXPORT MonoReflectionType *
6329 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6332 MonoReflectionType *ret;
6333 MonoClass *klass, *aklass;
6335 klass = mono_class_from_mono_type (type->type);
6336 check_for_invalid_type (klass, &error);
6337 mono_error_set_pending_exception (&error);
6339 if (rank == 0) //single dimentional array
6340 aklass = mono_array_class_get (klass, 1);
6342 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6344 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6345 mono_error_set_pending_exception (&error);
6350 ICALL_EXPORT MonoReflectionType *
6351 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6354 MonoReflectionType *ret;
6357 klass = mono_class_from_mono_type (type->type);
6358 mono_class_init_checked (klass, &error);
6359 if (mono_error_set_pending_exception (&error))
6362 check_for_invalid_type (klass, &error);
6363 if (mono_error_set_pending_exception (&error))
6366 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6367 mono_error_set_pending_exception (&error);
6372 ICALL_EXPORT MonoReflectionType *
6373 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6376 MonoReflectionType *ret;
6377 MonoClass *klass, *pklass;
6379 klass = mono_class_from_mono_type (type->type);
6380 mono_class_init_checked (klass, &error);
6381 if (mono_error_set_pending_exception (&error))
6383 check_for_invalid_type (klass, &error);
6384 if (mono_error_set_pending_exception (&error))
6387 pklass = mono_ptr_class_get (type->type);
6389 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6390 mono_error_set_pending_exception (&error);
6395 ICALL_EXPORT MonoObject *
6396 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6397 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6400 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6401 MonoObject *delegate;
6403 MonoMethod *method = info->method;
6405 mono_class_init_checked (delegate_class, &error);
6406 if (mono_error_set_pending_exception (&error))
6409 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6410 /* FIXME improve this exception message */
6411 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6413 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6414 mono_error_set_pending_exception (&error);
6418 if (mono_security_core_clr_enabled ()) {
6419 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6420 if (throwOnBindFailure)
6421 mono_error_set_pending_exception (&error);
6423 mono_error_cleanup (&error);
6428 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6429 if (mono_error_set_pending_exception (&error))
6432 if (method_is_dynamic (method)) {
6433 /* Creating a trampoline would leak memory */
6434 func = mono_compile_method (method);
6436 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6437 method = mono_object_get_virtual_method (target, method);
6438 func = mono_create_ftnptr (mono_domain_get (),
6439 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6442 mono_delegate_ctor_with_method (delegate, target, func, method);
6447 ICALL_EXPORT MonoMulticastDelegate *
6448 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6451 MonoMulticastDelegate *ret;
6453 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6455 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6456 if (mono_error_set_pending_exception (&error))
6459 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6464 ICALL_EXPORT MonoReflectionMethod*
6465 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6467 MonoReflectionMethod *ret = NULL;
6469 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6470 mono_error_set_pending_exception (&error);
6476 static inline gint32
6477 mono_array_get_byte_length (MonoArray *array)
6483 klass = array->obj.vtable->klass;
6485 if (array->bounds == NULL)
6486 length = array->max_length;
6489 for (i = 0; i < klass->rank; ++ i)
6490 length *= array->bounds [i].length;
6493 switch (klass->element_class->byval_arg.type) {
6496 case MONO_TYPE_BOOLEAN:
6500 case MONO_TYPE_CHAR:
6508 return length * sizeof (gpointer);
6519 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6521 return mono_array_get_byte_length (array);
6525 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6527 return mono_array_get (array, gint8, idx);
6531 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6533 mono_array_set (array, gint8, idx, value);
6536 ICALL_EXPORT MonoBoolean
6537 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6539 guint8 *src_buf, *dest_buf;
6542 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6546 g_assert (count >= 0);
6548 /* This is called directly from the class libraries without going through the managed wrapper */
6549 MONO_CHECK_ARG_NULL (src, FALSE);
6550 MONO_CHECK_ARG_NULL (dest, FALSE);
6552 /* watch out for integer overflow */
6553 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6556 src_buf = (guint8 *)src->vector + src_offset;
6557 dest_buf = (guint8 *)dest->vector + dest_offset;
6560 memcpy (dest_buf, src_buf, count);
6562 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6567 #ifndef DISABLE_REMOTING
6568 ICALL_EXPORT MonoObject *
6569 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6572 MonoDomain *domain = mono_object_domain (this_obj);
6574 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6575 MonoTransparentProxy *tp;
6579 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6580 if (mono_error_set_pending_exception (&error))
6583 tp = (MonoTransparentProxy*) res;
6585 MONO_OBJECT_SETREF (tp, rp, rp);
6586 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6587 klass = mono_class_from_mono_type (type);
6589 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6590 mono_class_setup_vtable (klass);
6591 if (mono_class_has_failure (klass)) {
6592 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6596 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6597 if (!is_ok (&error)) {
6598 mono_error_set_pending_exception (&error);
6601 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6602 if (!is_ok (&error)) {
6603 mono_error_set_pending_exception (&error);
6607 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6611 ICALL_EXPORT MonoReflectionType *
6612 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6615 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6616 mono_error_set_pending_exception (&error);
6622 /* System.Environment */
6625 ves_icall_System_Environment_get_UserName (void)
6627 /* using glib is more portable */
6628 return mono_string_new (mono_domain_get (), g_get_user_name ());
6632 ICALL_EXPORT MonoString *
6633 ves_icall_System_Environment_get_MachineName (void)
6635 #if defined (HOST_WIN32)
6640 len = MAX_COMPUTERNAME_LENGTH + 1;
6641 buf = g_new (gunichar2, len);
6644 if (GetComputerName (buf, (PDWORD) &len)) {
6646 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6647 mono_error_set_pending_exception (&error);
6652 #elif !defined(DISABLE_SOCKETS)
6656 #if defined _SC_HOST_NAME_MAX
6657 n = sysconf (_SC_HOST_NAME_MAX);
6661 buf = g_malloc (n+1);
6663 if (gethostname (buf, n) == 0){
6665 result = mono_string_new (mono_domain_get (), buf);
6672 return mono_string_new (mono_domain_get (), "mono");
6677 ves_icall_System_Environment_get_Platform (void)
6679 #if defined (TARGET_WIN32)
6682 #elif defined(__MACH__)
6685 // Notice that the value is hidden from user code, and only exposed
6686 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6687 // define and making assumptions based on Unix/128/4 values before there
6688 // was a MacOS define. Lots of code would assume that not-Unix meant
6689 // Windows, but in this case, it would be OSX.
6698 ICALL_EXPORT MonoString *
6699 ves_icall_System_Environment_get_NewLine (void)
6701 #if defined (HOST_WIN32)
6702 return mono_string_new (mono_domain_get (), "\r\n");
6704 return mono_string_new (mono_domain_get (), "\n");
6708 ICALL_EXPORT MonoBoolean
6709 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6711 #if SIZEOF_VOID_P == 8
6715 gboolean isWow64Process = FALSE;
6716 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6717 return (MonoBoolean)isWow64Process;
6719 #elif defined(HAVE_SYS_UTSNAME_H)
6720 struct utsname name;
6722 if (uname (&name) >= 0) {
6723 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6730 ICALL_EXPORT MonoString *
6731 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6739 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6740 value = g_getenv (utf8_name);
6747 return mono_string_new (mono_domain_get (), value);
6751 * There is no standard way to get at environ.
6754 #ifndef __MINGW32_VERSION
6755 #if defined(__APPLE__)
6756 #if defined (TARGET_OSX)
6757 /* Apple defines this in crt_externs.h but doesn't provide that header for
6758 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6759 * in fact exist on all implementations (so far)
6761 gchar ***_NSGetEnviron(void);
6762 #define environ (*_NSGetEnviron())
6764 static char *mono_environ[1] = { NULL };
6765 #define environ mono_environ
6766 #endif /* defined (TARGET_OSX) */
6774 ICALL_EXPORT MonoArray *
6775 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6786 env_strings = GetEnvironmentStrings();
6789 env_string = env_strings;
6790 while (*env_string != '\0') {
6791 /* weird case that MS seems to skip */
6792 if (*env_string != '=')
6794 while (*env_string != '\0')
6800 domain = mono_domain_get ();
6801 names = mono_array_new (domain, mono_defaults.string_class, n);
6805 env_string = env_strings;
6806 while (*env_string != '\0') {
6807 /* weird case that MS seems to skip */
6808 if (*env_string != '=') {
6809 equal_str = wcschr(env_string, '=');
6810 g_assert(equal_str);
6812 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6813 if (mono_error_set_pending_exception (&error))
6816 mono_array_setref (names, n, str);
6819 while (*env_string != '\0')
6824 FreeEnvironmentStrings (env_strings);
6837 for (e = environ; *e != 0; ++ e)
6840 domain = mono_domain_get ();
6841 names = mono_array_new (domain, mono_defaults.string_class, n);
6844 for (e = environ; *e != 0; ++ e) {
6845 parts = g_strsplit (*e, "=", 2);
6847 str = mono_string_new (domain, *parts);
6848 mono_array_setref (names, n, str);
6861 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6863 #if !GLIB_CHECK_VERSION(2,4,0)
6864 #define g_setenv(a,b,c) setenv(a,b,c)
6865 #define g_unsetenv(a) unsetenv(a)
6869 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6872 gunichar2 *utf16_name, *utf16_value;
6874 gchar *utf8_name, *utf8_value;
6879 utf16_name = mono_string_to_utf16 (name);
6880 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6881 SetEnvironmentVariable (utf16_name, NULL);
6882 g_free (utf16_name);
6886 utf16_value = mono_string_to_utf16 (value);
6888 SetEnvironmentVariable (utf16_name, utf16_value);
6890 g_free (utf16_name);
6891 g_free (utf16_value);
6893 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6895 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6896 g_unsetenv (utf8_name);
6901 utf8_value = mono_string_to_utf8_checked (value, &error);
6902 if (!mono_error_ok (&error)) {
6904 mono_error_set_pending_exception (&error);
6907 g_setenv (utf8_name, utf8_value, TRUE);
6910 g_free (utf8_value);
6915 ves_icall_System_Environment_Exit (int result)
6917 mono_environment_exitcode_set (result);
6919 /* FIXME: There are some cleanup hangs that should be worked out, but
6920 * if the program is going to exit, everything will be cleaned up when
6921 * NaCl exits anyway.
6923 #ifndef __native_client__
6924 if (!mono_runtime_try_shutdown ())
6925 mono_thread_exit ();
6927 /* Suspend all managed threads since the runtime is going away */
6928 mono_thread_suspend_all_other_threads ();
6930 mono_runtime_quit ();
6933 /* we may need to do some cleanup here... */
6937 ICALL_EXPORT MonoString*
6938 ves_icall_System_Environment_GetGacPath (void)
6940 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6943 ICALL_EXPORT MonoString*
6944 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6946 #if defined (HOST_WIN32)
6947 #ifndef CSIDL_FLAG_CREATE
6948 #define CSIDL_FLAG_CREATE 0x8000
6951 WCHAR path [MAX_PATH];
6952 /* Create directory if no existing */
6953 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6958 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6959 mono_error_set_pending_exception (&error);
6963 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6965 return mono_string_new (mono_domain_get (), "");
6968 ICALL_EXPORT MonoArray *
6969 ves_icall_System_Environment_GetLogicalDrives (void)
6972 gunichar2 buf [256], *ptr, *dname;
6974 guint initial_size = 127, size = 128;
6977 MonoString *drivestr;
6978 MonoDomain *domain = mono_domain_get ();
6984 while (size > initial_size) {
6985 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6986 if (size > initial_size) {
6989 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6990 initial_size = size;
7004 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
7009 while (*u16) { u16++; len ++; }
7010 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7011 if (mono_error_set_pending_exception (&error))
7014 mono_array_setref (result, ndrives++, drivestr);
7024 ICALL_EXPORT MonoString *
7025 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7027 gunichar2 volume_name [MAX_PATH + 1];
7029 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7031 return mono_string_from_utf16 (volume_name);
7034 ICALL_EXPORT MonoString *
7035 ves_icall_System_Environment_InternalGetHome (void)
7037 return mono_string_new (mono_domain_get (), g_get_home_dir ());
7040 static const char *encodings [] = {
7042 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7043 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7044 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7046 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7047 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7048 "x_unicode_2_0_utf_7",
7050 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7051 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7053 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7056 "unicodefffe", "utf_16be",
7063 * Returns the internal codepage, if the value of "int_code_page" is
7064 * 1 at entry, and we can not compute a suitable code page number,
7065 * returns the code page as a string
7067 ICALL_EXPORT MonoString*
7068 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
7073 char *codepage = NULL;
7075 int want_name = *int_code_page;
7078 *int_code_page = -1;
7080 g_get_charset (&cset);
7081 c = codepage = strdup (cset);
7082 for (c = codepage; *c; c++){
7083 if (isascii (*c) && isalpha (*c))
7088 /* g_print ("charset: %s\n", cset); */
7090 /* handle some common aliases */
7093 for (i = 0; p != 0; ){
7096 p = encodings [++i];
7099 if (strcmp (p, codepage) == 0){
7100 *int_code_page = code;
7103 p = encodings [++i];
7106 if (strstr (codepage, "utf_8") != NULL)
7107 *int_code_page |= 0x10000000;
7110 if (want_name && *int_code_page == -1)
7111 return mono_string_new (mono_domain_get (), cset);
7116 ICALL_EXPORT MonoBoolean
7117 ves_icall_System_Environment_get_HasShutdownStarted (void)
7119 if (mono_runtime_is_shutting_down ())
7122 if (mono_domain_is_unloading (mono_domain_get ()))
7129 ves_icall_System_Environment_BroadcastSettingChange (void)
7132 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7137 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7143 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
7144 MonoReflectionMethod *method,
7145 MonoArray *out_args)
7147 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
7150 #ifndef DISABLE_REMOTING
7151 ICALL_EXPORT MonoBoolean
7152 ves_icall_IsTransparentProxy (MonoObject *proxy)
7157 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7163 ICALL_EXPORT MonoReflectionMethod *
7164 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7165 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7167 MonoReflectionMethod *ret = NULL;
7172 MonoMethod **vtable;
7173 MonoMethod *res = NULL;
7175 MONO_CHECK_ARG_NULL (rtype, NULL);
7176 MONO_CHECK_ARG_NULL (rmethod, NULL);
7178 method = rmethod->method;
7179 klass = mono_class_from_mono_type (rtype->type);
7180 mono_class_init_checked (klass, &error);
7181 if (mono_error_set_pending_exception (&error))
7184 if (MONO_CLASS_IS_INTERFACE (klass))
7187 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7190 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7191 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7197 mono_class_setup_vtable (klass);
7198 vtable = klass->vtable;
7200 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7201 gboolean variance_used = FALSE;
7202 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7203 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7205 res = vtable [offs + method->slot];
7207 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7210 if (method->slot != -1)
7211 res = vtable [method->slot];
7217 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7218 mono_error_set_pending_exception (&error);
7223 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7229 klass = mono_class_from_mono_type (type->type);
7230 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7231 if (!is_ok (&error)) {
7232 mono_error_set_pending_exception (&error);
7236 mono_vtable_set_is_remote (vtable, enable);
7239 #else /* DISABLE_REMOTING */
7242 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7244 g_assert_not_reached ();
7249 ICALL_EXPORT MonoObject *
7250 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7257 domain = mono_object_domain (type);
7258 klass = mono_class_from_mono_type (type->type);
7259 mono_class_init_checked (klass, &error);
7260 if (mono_error_set_pending_exception (&error))
7263 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7264 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7268 if (klass->rank >= 1) {
7269 g_assert (klass->rank == 1);
7270 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7272 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7273 if (!is_ok (&error)) {
7274 mono_error_set_pending_exception (&error);
7277 /* Bypass remoting object creation check */
7278 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7279 mono_error_set_pending_exception (&error);
7285 ICALL_EXPORT MonoString *
7286 ves_icall_System_IO_get_temp_path (void)
7288 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7291 #ifndef PLATFORM_NO_DRIVEINFO
7292 ICALL_EXPORT MonoBoolean
7293 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7294 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7298 ULARGE_INTEGER wapi_free_bytes_avail;
7299 ULARGE_INTEGER wapi_total_number_of_bytes;
7300 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7302 *error = ERROR_SUCCESS;
7303 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7304 &wapi_total_number_of_free_bytes);
7307 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7308 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7309 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7311 *free_bytes_avail = 0;
7312 *total_number_of_bytes = 0;
7313 *total_number_of_free_bytes = 0;
7314 *error = GetLastError ();
7320 ICALL_EXPORT guint32
7321 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7323 return GetDriveType (mono_string_chars (root_path_name));
7327 ICALL_EXPORT gpointer
7328 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7330 return mono_compile_method (method);
7333 ICALL_EXPORT MonoString *
7334 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7339 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7341 #if defined (HOST_WIN32)
7342 /* Avoid mixing '/' and '\\' */
7345 for (i = strlen (path) - 1; i >= 0; i--)
7346 if (path [i] == '/')
7350 mcpath = mono_string_new (mono_domain_get (), path);
7357 get_bundled_app_config (void)
7359 const gchar *app_config;
7362 gchar *config_file_name, *config_file_path;
7363 gsize len, config_file_path_length, config_ext_length;
7366 domain = mono_domain_get ();
7367 file = domain->setup->configuration_file;
7368 if (!file || file->length == 0)
7371 // Retrieve config file and remove the extension
7372 config_file_name = mono_string_to_utf8 (file);
7373 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7374 if (!config_file_path)
7375 config_file_path = config_file_name;
7377 config_file_path_length = strlen (config_file_path);
7378 config_ext_length = strlen (".config");
7379 if (config_file_path_length <= config_ext_length)
7382 len = config_file_path_length - config_ext_length;
7383 module = (gchar *)g_malloc0 (len + 1);
7384 memcpy (module, config_file_path, len);
7385 // Get the config file from the module name
7386 app_config = mono_config_string_for_assembly_file (module);
7389 if (config_file_name != config_file_path)
7390 g_free (config_file_name);
7391 g_free (config_file_path);
7396 return mono_string_new (mono_domain_get (), app_config);
7400 get_bundled_machine_config (void)
7402 const gchar *machine_config;
7404 machine_config = mono_get_machine_config ();
7406 if (!machine_config)
7409 return mono_string_new (mono_domain_get (), machine_config);
7412 ICALL_EXPORT MonoString *
7413 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7418 path = g_path_get_dirname (mono_get_config_dir ());
7420 #if defined (HOST_WIN32)
7421 /* Avoid mixing '/' and '\\' */
7424 for (i = strlen (path) - 1; i >= 0; i--)
7425 if (path [i] == '/')
7429 ipath = mono_string_new (mono_domain_get (), path);
7435 ICALL_EXPORT gboolean
7436 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7438 MonoPEResourceDataEntry *entry;
7441 if (!assembly || !result || !size)
7446 image = assembly->assembly->image;
7447 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7451 *result = mono_image_rva_map (image, entry->rde_data_offset);
7456 *size = entry->rde_size;
7461 ICALL_EXPORT MonoBoolean
7462 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7464 return mono_is_debugger_attached ();
7467 ICALL_EXPORT MonoBoolean
7468 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7470 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7471 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7477 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7479 if (mono_get_runtime_callbacks ()->debug_log)
7480 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7484 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7486 #if defined (HOST_WIN32)
7487 OutputDebugString (mono_string_chars (message));
7489 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7493 /* Only used for value types */
7494 ICALL_EXPORT MonoObject *
7495 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7502 domain = mono_object_domain (type);
7503 klass = mono_class_from_mono_type (type->type);
7504 mono_class_init_checked (klass, &error);
7505 if (mono_error_set_pending_exception (&error))
7508 if (mono_class_is_nullable (klass))
7509 /* No arguments -> null */
7512 result = mono_object_new_checked (domain, klass, &error);
7513 mono_error_set_pending_exception (&error);
7517 ICALL_EXPORT MonoReflectionMethod *
7518 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7520 MonoReflectionMethod *ret = NULL;
7523 MonoClass *klass, *parent;
7524 MonoGenericContext *generic_inst = NULL;
7525 MonoMethod *method = m->method;
7526 MonoMethod *result = NULL;
7529 if (method->klass == NULL)
7532 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7533 MONO_CLASS_IS_INTERFACE (method->klass) ||
7534 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7537 slot = mono_method_get_vtable_slot (method);
7541 klass = method->klass;
7542 if (klass->generic_class) {
7543 generic_inst = mono_class_get_context (klass);
7544 klass = klass->generic_class->container_class;
7548 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7549 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7550 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7551 or klass is the generic container class and generic_inst is the instantiation.
7553 when we go to the parent, if the parent is an open constructed type, we need to
7554 replace the type parameters by the definitions from the generic_inst, and then take it
7555 apart again into the klass and the generic_inst.
7557 For cases like this:
7558 class C<T> : B<T, int> {
7559 public override void Foo () { ... }
7561 class B<U,V> : A<HashMap<U,V>> {
7562 public override void Foo () { ... }
7565 public virtual void Foo () { ... }
7568 if at each iteration the parent isn't open, we can skip inflating it. if at some
7569 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7572 MonoGenericContext *parent_inst = NULL;
7573 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7574 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7575 if (!mono_error_ok (&error)) {
7576 mono_error_set_pending_exception (&error);
7580 if (parent->generic_class) {
7581 parent_inst = mono_class_get_context (parent);
7582 parent = parent->generic_class->container_class;
7585 mono_class_setup_vtable (parent);
7586 if (parent->vtable_size <= slot)
7589 generic_inst = parent_inst;
7592 klass = klass->parent;
7595 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7596 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7597 if (!mono_error_ok (&error)) {
7598 mono_error_set_pending_exception (&error);
7602 generic_inst = NULL;
7604 if (klass->generic_class) {
7605 generic_inst = mono_class_get_context (klass);
7606 klass = klass->generic_class->container_class;
7612 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7613 if (!mono_error_ok (&error)) {
7614 mono_error_set_pending_exception (&error);
7619 if (klass == method->klass)
7622 /*This is possible if definition == FALSE.
7623 * Do it here to be really sure we don't read invalid memory.
7625 if (slot >= klass->vtable_size)
7628 mono_class_setup_vtable (klass);
7630 result = klass->vtable [slot];
7631 if (result == NULL) {
7632 /* It is an abstract method */
7633 gpointer iter = NULL;
7634 while ((result = mono_class_get_methods (klass, &iter)))
7635 if (result->slot == slot)
7642 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7643 mono_error_set_pending_exception (&error);
7647 ICALL_EXPORT MonoString*
7648 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7650 MonoMethod *method = m->method;
7652 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7657 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7659 iter->sig = *(MonoMethodSignature**)argsp;
7661 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7662 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7665 /* FIXME: it's not documented what start is exactly... */
7669 iter->args = argsp + sizeof (gpointer);
7671 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7673 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7676 ICALL_EXPORT MonoTypedRef
7677 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7679 guint32 i, arg_size;
7683 i = iter->sig->sentinelpos + iter->next_arg;
7685 g_assert (i < iter->sig->param_count);
7687 res.type = iter->sig->params [i];
7688 res.klass = mono_class_from_mono_type (res.type);
7689 arg_size = mono_type_stack_size (res.type, &align);
7690 #if defined(__arm__) || defined(__mips__)
7691 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7693 res.value = iter->args;
7694 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7695 /* Values are stored as 8 byte register sized objects, but 'value'
7696 * is dereferenced as a pointer in other routines.
7698 res.value = (char*)res.value + 4;
7700 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7701 if (arg_size <= sizeof (gpointer)) {
7703 int padding = arg_size - mono_type_size (res.type, &dummy);
7704 res.value = (guint8*)res.value + padding;
7707 iter->args = (char*)iter->args + arg_size;
7710 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7715 ICALL_EXPORT MonoTypedRef
7716 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7718 guint32 i, arg_size;
7722 i = iter->sig->sentinelpos + iter->next_arg;
7724 g_assert (i < iter->sig->param_count);
7726 while (i < iter->sig->param_count) {
7727 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7729 res.type = iter->sig->params [i];
7730 res.klass = mono_class_from_mono_type (res.type);
7731 /* FIXME: endianess issue... */
7732 arg_size = mono_type_stack_size (res.type, &align);
7733 #if defined(__arm__) || defined(__mips__)
7734 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7736 res.value = iter->args;
7737 iter->args = (char*)iter->args + arg_size;
7739 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7742 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7750 ICALL_EXPORT MonoType*
7751 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7755 i = iter->sig->sentinelpos + iter->next_arg;
7757 g_assert (i < iter->sig->param_count);
7759 return iter->sig->params [i];
7762 ICALL_EXPORT MonoObject*
7763 mono_TypedReference_ToObject (MonoTypedRef* tref)
7766 MonoObject *result = NULL;
7767 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7768 MonoObject** objp = (MonoObject **)tref->value;
7772 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7773 mono_error_set_pending_exception (&error);
7777 ICALL_EXPORT MonoTypedRef
7778 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7781 MonoReflectionField *f;
7783 MonoType *ftype = NULL;
7787 memset (&res, 0, sizeof (res));
7790 g_assert (mono_array_length (fields) > 0);
7792 klass = target->vtable->klass;
7794 for (i = 0; i < mono_array_length (fields); ++i) {
7795 f = mono_array_get (fields, MonoReflectionField*, i);
7797 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7800 if (f->field->parent != klass) {
7801 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7805 p = (guint8*)target + f->field->offset;
7807 p += f->field->offset - sizeof (MonoObject);
7808 klass = mono_class_from_mono_type (f->field->type);
7809 ftype = f->field->type;
7813 res.klass = mono_class_from_mono_type (ftype);
7820 prelink_method (MonoMethod *method, MonoError *error)
7822 const char *exc_class, *exc_arg;
7824 mono_error_init (error);
7825 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7827 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7829 mono_error_set_exception_instance (error,
7830 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7833 /* create the wrapper, too? */
7837 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7841 prelink_method (method->method, &error);
7842 mono_error_set_pending_exception (&error);
7846 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7849 MonoClass *klass = mono_class_from_mono_type (type->type);
7851 gpointer iter = NULL;
7853 mono_class_init_checked (klass, &error);
7854 if (mono_error_set_pending_exception (&error))
7857 while ((m = mono_class_get_methods (klass, &iter))) {
7858 prelink_method (m, &error);
7859 if (mono_error_set_pending_exception (&error))
7864 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7866 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7867 gint32 const **exponents,
7868 gunichar2 const **digitLowerTable,
7869 gunichar2 const **digitUpperTable,
7870 gint64 const **tenPowersList,
7871 gint32 const **decHexDigits)
7873 *mantissas = Formatter_MantissaBitsTable;
7874 *exponents = Formatter_TensExponentTable;
7875 *digitLowerTable = Formatter_DigitLowerTable;
7876 *digitUpperTable = Formatter_DigitUpperTable;
7877 *tenPowersList = Formatter_TenPowersList;
7878 *decHexDigits = Formatter_DecHexDigits;
7882 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7883 * and avoid useless allocations.
7886 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7888 MonoReflectionType *rt;
7892 mono_error_init (error);
7893 for (i = 0; i < type->num_mods; ++i) {
7894 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7899 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7901 for (i = 0; i < type->num_mods; ++i) {
7902 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7903 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7904 return_val_if_nok (error, NULL);
7906 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7907 return_val_if_nok (error, NULL);
7909 mono_array_setref (res, count, rt);
7916 ICALL_EXPORT MonoArray*
7917 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7920 MonoType *type = param->ClassImpl->type;
7921 MonoClass *member_class = mono_object_class (param->MemberImpl);
7922 MonoMethod *method = NULL;
7925 MonoMethodSignature *sig;
7928 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7929 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7930 method = rmethod->method;
7931 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7932 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7933 if (!(method = prop->property->get))
7934 method = prop->property->set;
7937 char *type_name = mono_type_get_full_name (member_class);
7938 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7939 MonoException *ex = mono_get_exception_not_supported (msg);
7942 mono_set_pending_exception (ex);
7946 image = method->klass->image;
7947 pos = param->PositionImpl;
7948 sig = mono_method_signature (method);
7952 type = sig->params [pos];
7954 res = type_array_from_modifiers (image, type, optional, &error);
7955 mono_error_set_pending_exception (&error);
7960 get_property_type (MonoProperty *prop)
7962 MonoMethodSignature *sig;
7964 sig = mono_method_signature (prop->get);
7966 } else if (prop->set) {
7967 sig = mono_method_signature (prop->set);
7968 return sig->params [sig->param_count - 1];
7973 ICALL_EXPORT MonoArray*
7974 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7977 MonoType *type = get_property_type (property->property);
7978 MonoImage *image = property->klass->image;
7983 res = type_array_from_modifiers (image, type, optional, &error);
7984 mono_error_set_pending_exception (&error);
7989 *Construct a MonoType suited to be used to decode a constant blob object.
7991 * @type is the target type which will be constructed
7992 * @blob_type is the blob type, for example, that comes from the constant table
7993 * @real_type is the expected constructed type.
7996 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7998 type->type = blob_type;
7999 type->data.klass = NULL;
8000 if (blob_type == MONO_TYPE_CLASS)
8001 type->data.klass = mono_defaults.object_class;
8002 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8003 /* For enums, we need to use the base type */
8004 type->type = MONO_TYPE_VALUETYPE;
8005 type->data.klass = mono_class_from_mono_type (real_type);
8007 type->data.klass = mono_class_from_mono_type (real_type);
8010 ICALL_EXPORT MonoObject*
8011 property_info_get_default_value (MonoReflectionProperty *property)
8015 MonoProperty *prop = property->property;
8016 MonoType *type = get_property_type (prop);
8017 MonoDomain *domain = mono_object_domain (property);
8018 MonoTypeEnum def_type;
8019 const char *def_value;
8022 mono_class_init (prop->parent);
8024 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8025 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8029 def_value = mono_class_get_property_default_value (prop, &def_type);
8031 mono_type_from_blob_type (&blob_type, def_type, type);
8032 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8034 mono_error_set_pending_exception (&error);
8038 ICALL_EXPORT MonoBoolean
8039 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8042 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8043 MonoCustomAttrInfo *cinfo;
8046 mono_class_init_checked (attr_class, &error);
8047 if (mono_error_set_pending_exception (&error))
8050 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8051 if (!is_ok (&error)) {
8052 mono_error_set_pending_exception (&error);
8057 found = mono_custom_attrs_has_attr (cinfo, attr_class);
8059 mono_custom_attrs_free (cinfo);
8063 ICALL_EXPORT MonoArray*
8064 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8066 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8071 mono_class_init_checked (attr_class, &error);
8072 if (mono_error_set_pending_exception (&error))
8076 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8077 if (!mono_error_ok (&error)) {
8078 mono_error_set_pending_exception (&error);
8085 ICALL_EXPORT MonoArray*
8086 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8090 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8091 mono_error_set_pending_exception (&error);
8096 ICALL_EXPORT MonoString*
8097 ves_icall_Mono_Runtime_GetDisplayName (void)
8100 MonoString *display_name;
8102 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8103 display_name = mono_string_new (mono_domain_get (), info);
8105 return display_name;
8108 ICALL_EXPORT MonoString*
8109 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8112 MonoString *message;
8116 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8117 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8120 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8122 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8123 if (mono_error_set_pending_exception (&error))
8130 ICALL_EXPORT gpointer
8131 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8133 return GetCurrentProcess ();
8136 ICALL_EXPORT MonoBoolean
8137 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8139 return GetExitCodeProcess (handle, (guint32*) exitcode);
8142 ICALL_EXPORT MonoBoolean
8143 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8145 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8146 return CloseHandle (handle);
8148 return CloseProcess (handle);
8152 ICALL_EXPORT MonoBoolean
8153 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8155 return TerminateProcess (handle, exitcode);
8159 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8161 return WaitForInputIdle (handle, milliseconds);
8164 ICALL_EXPORT MonoBoolean
8165 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8167 return GetProcessWorkingSetSize (handle, min, max);
8170 ICALL_EXPORT MonoBoolean
8171 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8173 return SetProcessWorkingSetSize (handle, min, max);
8176 ICALL_EXPORT MonoBoolean
8177 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8179 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8183 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8185 return mono_process_current_pid ();
8189 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8191 return GetPriorityClass (handle);
8194 ICALL_EXPORT MonoBoolean
8195 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8197 return SetPriorityClass (handle, priorityClass);
8200 #ifndef DISABLE_ICALL_TABLES
8202 #define ICALL_TYPE(id,name,first)
8203 #define ICALL(id,name,func) Icall_ ## id,
8206 #include "metadata/icall-def.h"
8212 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8213 #define ICALL(id,name,func)
8215 #include "metadata/icall-def.h"
8221 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8222 #define ICALL(id,name,func)
8224 guint16 first_icall;
8227 static const IcallTypeDesc
8228 icall_type_descs [] = {
8229 #include "metadata/icall-def.h"
8233 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8236 #define ICALL_TYPE(id,name,first)
8239 #ifdef HAVE_ARRAY_ELEM_INIT
8240 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8241 #define MSGSTRFIELD1(line) str##line
8243 static const struct msgstrtn_t {
8244 #define ICALL(id,name,func)
8246 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8247 #include "metadata/icall-def.h"
8249 } icall_type_names_str = {
8250 #define ICALL_TYPE(id,name,first) (name),
8251 #include "metadata/icall-def.h"
8254 static const guint16 icall_type_names_idx [] = {
8255 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8256 #include "metadata/icall-def.h"
8259 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8261 static const struct msgstr_t {
8263 #define ICALL_TYPE(id,name,first)
8264 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8265 #include "metadata/icall-def.h"
8267 } icall_names_str = {
8268 #define ICALL(id,name,func) (name),
8269 #include "metadata/icall-def.h"
8272 static const guint16 icall_names_idx [] = {
8273 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8274 #include "metadata/icall-def.h"
8277 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8283 #define ICALL_TYPE(id,name,first) name,
8284 #define ICALL(id,name,func)
8285 static const char* const
8286 icall_type_names [] = {
8287 #include "metadata/icall-def.h"
8291 #define icall_type_name_get(id) (icall_type_names [(id)])
8295 #define ICALL_TYPE(id,name,first)
8296 #define ICALL(id,name,func) name,
8297 static const char* const
8299 #include "metadata/icall-def.h"
8302 #define icall_name_get(id) icall_names [(id)]
8304 #endif /* !HAVE_ARRAY_ELEM_INIT */
8308 #define ICALL_TYPE(id,name,first)
8309 #define ICALL(id,name,func) func,
8310 static const gconstpointer
8311 icall_functions [] = {
8312 #include "metadata/icall-def.h"
8316 #ifdef ENABLE_ICALL_SYMBOL_MAP
8319 #define ICALL_TYPE(id,name,first)
8320 #define ICALL(id,name,func) #func,
8321 static const gconstpointer
8322 icall_symbols [] = {
8323 #include "metadata/icall-def.h"
8328 #endif /* DISABLE_ICALL_TABLES */
8330 static mono_mutex_t icall_mutex;
8331 static GHashTable *icall_hash = NULL;
8332 static GHashTable *jit_icall_hash_name = NULL;
8333 static GHashTable *jit_icall_hash_addr = NULL;
8336 mono_icall_init (void)
8338 #ifndef DISABLE_ICALL_TABLES
8341 /* check that tables are sorted: disable in release */
8344 const char *prev_class = NULL;
8345 const char *prev_method;
8347 for (i = 0; i < Icall_type_num; ++i) {
8348 const IcallTypeDesc *desc;
8351 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8352 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8353 prev_class = icall_type_name_get (i);
8354 desc = &icall_type_descs [i];
8355 num_icalls = icall_desc_num_icalls (desc);
8356 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8357 for (j = 0; j < num_icalls; ++j) {
8358 const char *methodn = icall_name_get (desc->first_icall + j);
8359 if (prev_method && strcmp (prev_method, methodn) >= 0)
8360 g_print ("method %s should come before method %s\n", methodn, prev_method);
8361 prev_method = methodn;
8367 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8368 mono_os_mutex_init (&icall_mutex);
8372 mono_icall_lock (void)
8374 mono_locks_os_acquire (&icall_mutex, IcallLock);
8378 mono_icall_unlock (void)
8380 mono_locks_os_release (&icall_mutex, IcallLock);
8384 mono_icall_cleanup (void)
8386 g_hash_table_destroy (icall_hash);
8387 g_hash_table_destroy (jit_icall_hash_name);
8388 g_hash_table_destroy (jit_icall_hash_addr);
8389 mono_os_mutex_destroy (&icall_mutex);
8393 * mono_add_internal_call:
8394 * @name: method specification to surface to the managed world
8395 * @method: pointer to a C method to invoke when the method is called
8397 * This method surfaces the C function pointed by @method as a method
8398 * that has been surfaced in managed code with the method specified in
8399 * @name as an internal call.
8401 * Internal calls are surfaced to all app domains loaded and they are
8402 * accessibly by a type with the specified name.
8404 * You must provide a fully qualified type name, that is namespaces
8405 * and type name, followed by a colon and the method name, with an
8406 * optional signature to bind.
8408 * For example, the following are all valid declarations:
8410 * "MyApp.Services.ScriptService:Accelerate"
8411 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8413 * You use method parameters in cases where there might be more than
8414 * one surface method to managed code. That way you can register different
8415 * internal calls for different method overloads.
8417 * The internal calls are invoked with no marshalling. This means that .NET
8418 * types like System.String are exposed as `MonoString *` parameters. This is
8419 * different than the way that strings are surfaced in P/Invoke.
8421 * For more information on how the parameters are marshalled, see the
8422 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8425 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8426 * reference for more information on the format of method descriptions.
8429 mono_add_internal_call (const char *name, gconstpointer method)
8433 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8435 mono_icall_unlock ();
8438 #ifndef DISABLE_ICALL_TABLES
8440 #ifdef HAVE_ARRAY_ELEM_INIT
8442 compare_method_imap (const void *key, const void *elem)
8444 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8445 return strcmp (key, method_name);
8449 find_method_icall (const IcallTypeDesc *imap, const char *name)
8451 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);
8454 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8458 compare_class_imap (const void *key, const void *elem)
8460 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8461 return strcmp (key, class_name);
8464 static const IcallTypeDesc*
8465 find_class_icalls (const char *name)
8467 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);
8470 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8473 #else /* HAVE_ARRAY_ELEM_INIT */
8476 compare_method_imap (const void *key, const void *elem)
8478 const char** method_name = (const char**)elem;
8479 return strcmp (key, *method_name);
8483 find_method_icall (const IcallTypeDesc *imap, const char *name)
8485 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8488 return (gpointer)icall_functions [(nameslot - icall_names)];
8492 compare_class_imap (const void *key, const void *elem)
8494 const char** class_name = (const char**)elem;
8495 return strcmp (key, *class_name);
8498 static const IcallTypeDesc*
8499 find_class_icalls (const char *name)
8501 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8504 return &icall_type_descs [nameslot - icall_type_names];
8507 #endif /* HAVE_ARRAY_ELEM_INIT */
8509 #endif /* DISABLE_ICALL_TABLES */
8512 * we should probably export this as an helper (handle nested types).
8513 * Returns the number of chars written in buf.
8516 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8518 int nspacelen, cnamelen;
8519 nspacelen = strlen (klass->name_space);
8520 cnamelen = strlen (klass->name);
8521 if (nspacelen + cnamelen + 2 > bufsize)
8524 memcpy (buf, klass->name_space, nspacelen);
8525 buf [nspacelen ++] = '.';
8527 memcpy (buf + nspacelen, klass->name, cnamelen);
8528 buf [nspacelen + cnamelen] = 0;
8529 return nspacelen + cnamelen;
8532 #ifdef DISABLE_ICALL_TABLES
8534 no_icall_table (void)
8536 g_assert_not_reached ();
8541 mono_lookup_internal_call (MonoMethod *method)
8546 int typelen = 0, mlen, siglen;
8548 #ifndef DISABLE_ICALL_TABLES
8549 const IcallTypeDesc *imap = NULL;
8552 g_assert (method != NULL);
8554 if (method->is_inflated)
8555 method = ((MonoMethodInflated *) method)->declaring;
8557 if (method->klass->nested_in) {
8558 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8562 mname [pos++] = '/';
8565 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8571 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8576 #ifndef DISABLE_ICALL_TABLES
8577 imap = find_class_icalls (mname);
8580 mname [typelen] = ':';
8581 mname [typelen + 1] = ':';
8583 mlen = strlen (method->name);
8584 memcpy (mname + typelen + 2, method->name, mlen);
8585 sigstart = mname + typelen + 2 + mlen;
8588 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8589 siglen = strlen (tmpsig);
8590 if (typelen + mlen + siglen + 6 > sizeof (mname))
8593 memcpy (sigstart + 1, tmpsig, siglen);
8594 sigstart [siglen + 1] = ')';
8595 sigstart [siglen + 2] = 0;
8600 res = g_hash_table_lookup (icall_hash, mname);
8602 mono_icall_unlock ();;
8605 /* try without signature */
8607 res = g_hash_table_lookup (icall_hash, mname);
8609 mono_icall_unlock ();
8613 #ifdef DISABLE_ICALL_TABLES
8614 mono_icall_unlock ();
8615 /* Fail only when the result is actually used */
8616 /* mono_marshal_get_native_wrapper () depends on this */
8617 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8618 return ves_icall_System_String_ctor_RedirectToCreateString;
8620 return no_icall_table;
8622 /* it wasn't found in the static call tables */
8624 mono_icall_unlock ();
8627 res = find_method_icall (imap, sigstart - mlen);
8629 mono_icall_unlock ();
8632 /* try _with_ signature */
8634 res = find_method_icall (imap, sigstart - mlen);
8636 mono_icall_unlock ();
8640 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8641 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8642 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8643 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8644 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");
8645 g_print ("If you see other errors or faults after this message they are probably related\n");
8646 g_print ("and you need to fix your mono install first.\n");
8648 mono_icall_unlock ();
8654 #ifdef ENABLE_ICALL_SYMBOL_MAP
8656 func_cmp (gconstpointer key, gconstpointer p)
8658 return (gsize)key - (gsize)*(gsize*)p;
8663 * mono_lookup_icall_symbol:
8665 * Given the icall METHOD, returns its C symbol.
8668 mono_lookup_icall_symbol (MonoMethod *m)
8670 #ifdef DISABLE_ICALL_TABLES
8671 g_assert_not_reached ();
8674 #ifdef ENABLE_ICALL_SYMBOL_MAP
8678 static gconstpointer *functions_sorted;
8679 static const char**symbols_sorted;
8680 static gboolean inited;
8685 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8686 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8687 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8688 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8689 /* Bubble sort the two arrays */
8693 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8694 if (functions_sorted [i] > functions_sorted [i + 1]) {
8697 tmp = functions_sorted [i];
8698 functions_sorted [i] = functions_sorted [i + 1];
8699 functions_sorted [i + 1] = tmp;
8700 tmp = symbols_sorted [i];
8701 symbols_sorted [i] = symbols_sorted [i + 1];
8702 symbols_sorted [i + 1] = tmp;
8709 func = mono_lookup_internal_call (m);
8712 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8716 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8718 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8719 g_assert_not_reached ();
8726 type_from_typename (char *type_name)
8728 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8730 if (!strcmp (type_name, "int"))
8731 klass = mono_defaults.int_class;
8732 else if (!strcmp (type_name, "ptr"))
8733 klass = mono_defaults.int_class;
8734 else if (!strcmp (type_name, "void"))
8735 klass = mono_defaults.void_class;
8736 else if (!strcmp (type_name, "int32"))
8737 klass = mono_defaults.int32_class;
8738 else if (!strcmp (type_name, "uint32"))
8739 klass = mono_defaults.uint32_class;
8740 else if (!strcmp (type_name, "int8"))
8741 klass = mono_defaults.sbyte_class;
8742 else if (!strcmp (type_name, "uint8"))
8743 klass = mono_defaults.byte_class;
8744 else if (!strcmp (type_name, "int16"))
8745 klass = mono_defaults.int16_class;
8746 else if (!strcmp (type_name, "uint16"))
8747 klass = mono_defaults.uint16_class;
8748 else if (!strcmp (type_name, "long"))
8749 klass = mono_defaults.int64_class;
8750 else if (!strcmp (type_name, "ulong"))
8751 klass = mono_defaults.uint64_class;
8752 else if (!strcmp (type_name, "float"))
8753 klass = mono_defaults.single_class;
8754 else if (!strcmp (type_name, "double"))
8755 klass = mono_defaults.double_class;
8756 else if (!strcmp (type_name, "object"))
8757 klass = mono_defaults.object_class;
8758 else if (!strcmp (type_name, "obj"))
8759 klass = mono_defaults.object_class;
8760 else if (!strcmp (type_name, "string"))
8761 klass = mono_defaults.string_class;
8762 else if (!strcmp (type_name, "bool"))
8763 klass = mono_defaults.boolean_class;
8764 else if (!strcmp (type_name, "boolean"))
8765 klass = mono_defaults.boolean_class;
8767 g_error ("%s", type_name);
8768 g_assert_not_reached ();
8770 return &klass->byval_arg;
8774 * LOCKING: Take the corlib image lock.
8776 MonoMethodSignature*
8777 mono_create_icall_signature (const char *sigstr)
8782 MonoMethodSignature *res, *res2;
8783 MonoImage *corlib = mono_defaults.corlib;
8785 mono_image_lock (corlib);
8786 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8787 mono_image_unlock (corlib);
8792 parts = g_strsplit (sigstr, " ", 256);
8801 res = mono_metadata_signature_alloc (corlib, len - 1);
8806 * Under windows, the default pinvoke calling convention is STDCALL but
8809 res->call_convention = MONO_CALL_C;
8812 res->ret = type_from_typename (parts [0]);
8813 for (i = 1; i < len; ++i) {
8814 res->params [i - 1] = type_from_typename (parts [i]);
8819 mono_image_lock (corlib);
8820 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8822 res = res2; /*Value is allocated in the image pool*/
8824 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8825 mono_image_unlock (corlib);
8831 mono_find_jit_icall_by_name (const char *name)
8833 MonoJitICallInfo *info;
8834 g_assert (jit_icall_hash_name);
8837 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8838 mono_icall_unlock ();
8843 mono_find_jit_icall_by_addr (gconstpointer addr)
8845 MonoJitICallInfo *info;
8846 g_assert (jit_icall_hash_addr);
8849 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8850 mono_icall_unlock ();
8856 * mono_get_jit_icall_info:
8858 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8859 * caller should access it while holding the icall lock.
8862 mono_get_jit_icall_info (void)
8864 return jit_icall_hash_name;
8868 * mono_lookup_jit_icall_symbol:
8870 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8873 mono_lookup_jit_icall_symbol (const char *name)
8875 MonoJitICallInfo *info;
8876 const char *res = NULL;
8879 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8881 res = info->c_symbol;
8882 mono_icall_unlock ();
8887 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8890 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8891 mono_icall_unlock ();
8895 * 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
8896 * icalls without wrappers in some cases.
8899 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8901 MonoJitICallInfo *info;
8908 if (!jit_icall_hash_name) {
8909 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8910 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8913 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8914 g_warning ("jit icall already defined \"%s\"\n", name);
8915 g_assert_not_reached ();
8918 info = g_new0 (MonoJitICallInfo, 1);
8923 info->c_symbol = c_symbol;
8924 info->no_raise = no_raise;
8927 info->wrapper = func;
8929 info->wrapper = NULL;
8932 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8933 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8935 mono_icall_unlock ();
8940 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8942 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);