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 ICALL_EXPORT MonoArray*
1289 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
1292 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
1293 mono_error_set_pending_exception (&error);
1298 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1300 MonoMethod **dest = (MonoMethod **)data;
1302 /* skip unmanaged frames */
1307 if (!strcmp (m->klass->name_space, "System.Reflection"))
1316 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1318 MonoMethod **dest = (MonoMethod **)data;
1320 /* skip unmanaged frames */
1324 if (m->wrapper_type != MONO_WRAPPER_NONE)
1332 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1343 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1345 MonoMethod **dest = (MonoMethod **)data;
1347 /* skip unmanaged frames */
1351 if (m->wrapper_type != MONO_WRAPPER_NONE)
1359 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1360 || (!strcmp (m->klass->name_space, "System"))))
1370 static MonoReflectionType *
1371 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1373 MonoMethod *m, *dest;
1375 MonoType *type = NULL;
1376 MonoAssembly *assembly = NULL;
1377 gboolean type_resolve = FALSE;
1378 MonoImage *rootimage = NULL;
1380 mono_error_init (error);
1383 * We must compute the calling assembly as type loading must happen under a metadata context.
1384 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1385 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1387 m = mono_method_get_last_managed ();
1389 if (m && m->klass->image != mono_defaults.corlib) {
1390 /* Happens with inlining */
1392 /* Ugly hack: type_from_parsed_name is called from
1393 * System.Type.internal_from_name, which is called most
1394 * directly from System.Type.GetType(string,bool,bool) but
1395 * also indirectly from places such as
1396 * System.Type.GetType(string,func,func) (via
1397 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1398 * so we need to skip over all of those to find the true caller.
1400 * It would be nice if we had stack marks.
1402 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1408 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1409 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1410 * to crash. This only seems to happen in some strange remoting
1411 * scenarios and I was unable to figure out what's happening there.
1412 * Dec 10, 2005 - Martin.
1416 assembly = dest->klass->image->assembly;
1417 type_resolve = TRUE;
1418 rootimage = assembly->image;
1420 g_warning (G_STRLOC);
1423 if (info->assembly.name)
1424 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1427 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1428 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1429 return_val_if_nok (error, NULL);
1433 // Say we're looking for System.Generic.Dict<int, Local>
1434 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1435 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1436 // is messed up when we go to construct the Local as the type arg...
1438 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1439 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1440 if (!info->assembly.name && !type) {
1442 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1443 return_val_if_nok (error, NULL);
1445 if (assembly && !type && type_resolve) {
1446 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1447 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1448 return_val_if_nok (error, NULL);
1454 return mono_type_get_object_checked (mono_domain_get (), type, error);
1457 ICALL_EXPORT MonoReflectionType*
1458 ves_icall_System_Type_internal_from_name (MonoString *name,
1459 MonoBoolean throwOnError,
1460 MonoBoolean ignoreCase)
1463 char *str = mono_string_to_utf8 (name);
1464 MonoTypeNameParse info;
1465 MonoReflectionType *type;
1468 parsedOk = mono_reflection_parse_type (str, &info);
1470 /* mono_reflection_parse_type() mangles the string */
1472 mono_reflection_free_type_info (&info);
1474 mono_error_init (&error);
1475 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1476 mono_error_set_pending_exception (&error);
1482 type = type_from_parsed_name (&info, ignoreCase, &error);
1484 mono_reflection_free_type_info (&info);
1487 if (!mono_error_ok (&error)) {
1489 mono_error_set_pending_exception (&error);
1491 mono_error_cleanup (&error);
1496 MonoException *e = NULL;
1499 e = mono_get_exception_type_load (name, NULL);
1502 mono_set_pending_exception (e);
1511 ICALL_EXPORT MonoReflectionType*
1512 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1515 MonoReflectionType *ret;
1516 MonoDomain *domain = mono_domain_get ();
1518 ret = mono_type_get_object_checked (domain, handle, &error);
1519 mono_error_set_pending_exception (&error);
1524 /* System.TypeCode */
1543 TYPECODE_STRING = 18
1546 ICALL_EXPORT guint32
1547 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1549 int t = type->type->type;
1551 if (type->type->byref)
1552 return TYPECODE_OBJECT;
1556 case MONO_TYPE_VOID:
1557 return TYPECODE_OBJECT;
1558 case MONO_TYPE_BOOLEAN:
1559 return TYPECODE_BOOLEAN;
1561 return TYPECODE_BYTE;
1563 return TYPECODE_SBYTE;
1565 return TYPECODE_UINT16;
1567 return TYPECODE_INT16;
1568 case MONO_TYPE_CHAR:
1569 return TYPECODE_CHAR;
1573 return TYPECODE_OBJECT;
1575 return TYPECODE_UINT32;
1577 return TYPECODE_INT32;
1579 return TYPECODE_UINT64;
1581 return TYPECODE_INT64;
1583 return TYPECODE_SINGLE;
1585 return TYPECODE_DOUBLE;
1586 case MONO_TYPE_VALUETYPE: {
1587 MonoClass *klass = type->type->data.klass;
1589 if (klass->enumtype) {
1590 t = mono_class_enum_basetype (klass)->type;
1592 } else if (mono_is_corlib_image (klass->image)) {
1593 if (strcmp (klass->name_space, "System") == 0) {
1594 if (strcmp (klass->name, "Decimal") == 0)
1595 return TYPECODE_DECIMAL;
1596 else if (strcmp (klass->name, "DateTime") == 0)
1597 return TYPECODE_DATETIME;
1600 return TYPECODE_OBJECT;
1602 case MONO_TYPE_STRING:
1603 return TYPECODE_STRING;
1604 case MONO_TYPE_SZARRAY:
1605 case MONO_TYPE_ARRAY:
1606 case MONO_TYPE_OBJECT:
1608 case MONO_TYPE_MVAR:
1609 case MONO_TYPE_TYPEDBYREF:
1610 return TYPECODE_OBJECT;
1611 case MONO_TYPE_CLASS:
1613 MonoClass *klass = type->type->data.klass;
1614 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1615 if (strcmp (klass->name, "DBNull") == 0)
1616 return TYPECODE_DBNULL;
1619 return TYPECODE_OBJECT;
1620 case MONO_TYPE_GENERICINST:
1621 return TYPECODE_OBJECT;
1623 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1629 mono_type_is_primitive (MonoType *type)
1631 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1632 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1636 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1638 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1639 return mono_class_enum_basetype (type->data.klass);
1640 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1641 return mono_class_enum_basetype (type->data.generic_class->container_class);
1645 ICALL_EXPORT guint32
1646 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1651 g_assert (type != NULL);
1653 klass = mono_class_from_mono_type (type->type);
1654 klassc = mono_class_from_mono_type (c->type);
1656 if (type->type->byref ^ c->type->byref)
1659 if (type->type->byref) {
1660 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1661 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1663 klass = mono_class_from_mono_type (t);
1664 klassc = mono_class_from_mono_type (ot);
1666 if (mono_type_is_primitive (t)) {
1667 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1668 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1669 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1670 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1671 return t->type == ot->type;
1673 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1676 if (klass->valuetype)
1677 return klass == klassc;
1678 return klass->valuetype == klassc->valuetype;
1681 return mono_class_is_assignable_from (klass, klassc);
1684 ICALL_EXPORT guint32
1685 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1688 MonoClass *klass = mono_class_from_mono_type (type->type);
1689 mono_class_init_checked (klass, &error);
1690 if (!is_ok (&error)) {
1691 mono_error_set_pending_exception (&error);
1694 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1695 mono_error_set_pending_exception (&error);
1699 ICALL_EXPORT guint32
1700 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1702 MonoClass *klass = mono_class_from_mono_type (type->type);
1703 return klass->flags;
1706 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1707 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1710 MonoClass *klass = field->field->parent;
1711 MonoMarshalType *info;
1715 if (klass->generic_container ||
1716 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1719 ftype = mono_field_get_type (field->field);
1720 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1723 info = mono_marshal_load_type_info (klass);
1725 for (i = 0; i < info->num_fields; ++i) {
1726 if (info->fields [i].field == field->field) {
1727 if (!info->fields [i].mspec)
1730 MonoReflectionMarshalAsAttribute* obj;
1731 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1732 if (!mono_error_ok (&error))
1733 mono_error_set_pending_exception (&error);
1742 ICALL_EXPORT MonoReflectionField*
1743 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1746 gboolean found = FALSE;
1753 klass = handle->parent;
1755 klass = mono_class_from_mono_type (type);
1757 /* Check that the field belongs to the class */
1758 for (k = klass; k; k = k->parent) {
1759 if (k == handle->parent) {
1766 /* The managed code will throw the exception */
1770 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1771 mono_error_set_pending_exception (&error);
1775 ICALL_EXPORT MonoArray*
1776 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1779 MonoType *type = mono_field_get_type_checked (field->field, &error);
1782 if (!mono_error_ok (&error)) {
1783 mono_error_set_pending_exception (&error);
1787 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1788 mono_error_set_pending_exception (&error);
1793 vell_icall_get_method_attributes (MonoMethod *method)
1795 return method->flags;
1799 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1802 MonoReflectionType *rt;
1803 MonoDomain *domain = mono_domain_get ();
1804 MonoMethodSignature* sig;
1806 sig = mono_method_signature_checked (method, &error);
1807 if (!mono_error_ok (&error)) {
1808 mono_error_set_pending_exception (&error);
1812 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1813 if (!mono_error_ok (&error)) {
1814 mono_error_set_pending_exception (&error);
1818 MONO_STRUCT_SETREF (info, parent, rt);
1820 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1821 if (!mono_error_ok (&error)) {
1822 mono_error_set_pending_exception (&error);
1826 MONO_STRUCT_SETREF (info, ret, rt);
1828 info->attrs = method->flags;
1829 info->implattrs = method->iflags;
1830 if (sig->call_convention == MONO_CALL_DEFAULT)
1831 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1833 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1838 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1841 ICALL_EXPORT MonoArray*
1842 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1845 MonoDomain *domain = mono_domain_get ();
1847 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1848 mono_error_set_pending_exception (&error);
1852 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1853 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1856 MonoDomain *domain = mono_domain_get ();
1857 MonoReflectionMarshalAsAttribute* res = NULL;
1858 MonoMarshalSpec **mspecs;
1861 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1862 mono_method_get_marshal_info (method, mspecs);
1865 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1866 if (!mono_error_ok (&error)) {
1867 mono_error_set_pending_exception (&error);
1872 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1874 mono_metadata_free_marshal_spec (mspecs [i]);
1881 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1883 MonoClass *parent = field->field->parent;
1884 if (!parent->size_inited)
1885 mono_class_init (parent);
1886 mono_class_setup_fields_locking (parent);
1888 return field->field->offset - sizeof (MonoObject);
1891 ICALL_EXPORT MonoReflectionType*
1892 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1895 MonoReflectionType *ret;
1898 parent = declaring? field->field->parent: field->klass;
1900 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1901 mono_error_set_pending_exception (&error);
1907 ICALL_EXPORT MonoObject *
1908 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1911 MonoClass *fklass = field->klass;
1912 MonoClassField *cf = field->field;
1913 MonoDomain *domain = mono_object_domain (field);
1915 if (fklass->image->assembly->ref_only) {
1916 mono_set_pending_exception (mono_get_exception_invalid_operation (
1917 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1921 if (mono_security_core_clr_enabled () &&
1922 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1923 mono_error_set_pending_exception (&error);
1927 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1928 mono_error_set_pending_exception (&error);
1933 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1936 MonoClassField *cf = field->field;
1940 if (field->klass->image->assembly->ref_only) {
1941 mono_set_pending_exception (mono_get_exception_invalid_operation (
1942 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1946 if (mono_security_core_clr_enabled () &&
1947 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1948 mono_error_set_pending_exception (&error);
1952 type = mono_field_get_type_checked (cf, &error);
1953 if (!mono_error_ok (&error)) {
1954 mono_error_set_pending_exception (&error);
1958 v = (gchar *) value;
1960 switch (type->type) {
1963 case MONO_TYPE_BOOLEAN:
1966 case MONO_TYPE_CHAR:
1975 case MONO_TYPE_VALUETYPE:
1978 v += sizeof (MonoObject);
1980 case MONO_TYPE_STRING:
1981 case MONO_TYPE_OBJECT:
1982 case MONO_TYPE_CLASS:
1983 case MONO_TYPE_ARRAY:
1984 case MONO_TYPE_SZARRAY:
1987 case MONO_TYPE_GENERICINST: {
1988 MonoGenericClass *gclass = type->data.generic_class;
1989 g_assert (!gclass->context.class_inst->is_open);
1991 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1992 MonoClass *nklass = mono_class_from_mono_type (type);
1993 MonoObject *nullable;
1996 * Convert the boxed vtype into a Nullable structure.
1997 * This is complicated by the fact that Nullables have
1998 * a variable structure.
2000 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2001 if (!mono_error_ok (&error)) {
2002 mono_error_set_pending_exception (&error);
2006 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2008 v = (gchar *)mono_object_unbox (nullable);
2011 if (gclass->container_class->valuetype && (v != NULL))
2012 v += sizeof (MonoObject);
2016 g_error ("type 0x%x not handled in "
2017 "ves_icall_FieldInfo_SetValueInternal", type->type);
2022 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2023 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2024 if (!is_ok (&error)) {
2025 mono_error_set_pending_exception (&error);
2028 if (!vtable->initialized) {
2029 if (!mono_runtime_class_init_full (vtable, &error)) {
2030 mono_error_set_pending_exception (&error);
2034 mono_field_static_set_value (vtable, cf, v);
2036 mono_field_set_value (obj, cf, v);
2041 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2050 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2051 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2055 if (MONO_TYPE_IS_REFERENCE (f->type))
2056 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2058 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2061 ICALL_EXPORT MonoObject *
2062 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2064 MonoObject *o = NULL;
2065 MonoClassField *field = rfield->field;
2067 MonoDomain *domain = mono_object_domain (rfield);
2069 MonoTypeEnum def_type;
2070 const char *def_value;
2074 mono_class_init (field->parent);
2076 t = mono_field_get_type_checked (field, &error);
2077 if (!mono_error_ok (&error)) {
2078 mono_error_set_pending_exception (&error);
2082 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2083 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2087 if (image_is_dynamic (field->parent->image)) {
2088 MonoClass *klass = field->parent;
2089 int fidx = field - klass->fields;
2091 g_assert (fidx >= 0 && fidx < klass->field.count);
2092 g_assert (klass->ext);
2093 g_assert (klass->ext->field_def_values);
2094 def_type = klass->ext->field_def_values [fidx].def_type;
2095 def_value = klass->ext->field_def_values [fidx].data;
2096 if (def_type == MONO_TYPE_END) {
2097 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2101 def_value = mono_class_get_field_default_value (field, &def_type);
2102 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2104 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2109 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2113 case MONO_TYPE_BOOLEAN:
2116 case MONO_TYPE_CHAR:
2124 case MONO_TYPE_R8: {
2127 /* boxed value type */
2128 t = g_new0 (MonoType, 1);
2130 klass = mono_class_from_mono_type (t);
2132 o = mono_object_new_checked (domain, klass, &error);
2133 if (!mono_error_ok (&error)) {
2134 mono_error_set_pending_exception (&error);
2137 v = ((gchar *) o) + sizeof (MonoObject);
2138 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2141 case MONO_TYPE_STRING:
2142 case MONO_TYPE_CLASS:
2143 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2146 g_assert_not_reached ();
2152 ICALL_EXPORT MonoReflectionType*
2153 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2156 MonoReflectionType *ret;
2159 type = mono_field_get_type_checked (ref_field->field, &error);
2160 if (!mono_error_ok (&error)) {
2161 mono_error_set_pending_exception (&error);
2165 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2166 if (!mono_error_ok (&error)) {
2167 mono_error_set_pending_exception (&error);
2174 /* From MonoProperty.cs */
2176 PInfo_Attributes = 1,
2177 PInfo_GetMethod = 1 << 1,
2178 PInfo_SetMethod = 1 << 2,
2179 PInfo_ReflectedType = 1 << 3,
2180 PInfo_DeclaringType = 1 << 4,
2185 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2188 MonoReflectionType *rt;
2189 MonoReflectionMethod *rm;
2190 MonoDomain *domain = mono_object_domain (property);
2191 const MonoProperty *pproperty = property->property;
2193 if ((req_info & PInfo_ReflectedType) != 0) {
2194 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2195 if (mono_error_set_pending_exception (&error))
2198 MONO_STRUCT_SETREF (info, parent, rt);
2200 if ((req_info & PInfo_DeclaringType) != 0) {
2201 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2202 if (mono_error_set_pending_exception (&error))
2205 MONO_STRUCT_SETREF (info, declaring_type, rt);
2208 if ((req_info & PInfo_Name) != 0)
2209 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2211 if ((req_info & PInfo_Attributes) != 0)
2212 info->attrs = pproperty->attrs;
2214 if ((req_info & PInfo_GetMethod) != 0) {
2215 if (pproperty->get &&
2216 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2217 pproperty->get->klass == property->klass)) {
2218 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2219 if (mono_error_set_pending_exception (&error))
2225 MONO_STRUCT_SETREF (info, get, rm);
2227 if ((req_info & PInfo_SetMethod) != 0) {
2228 if (pproperty->set &&
2229 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2230 pproperty->set->klass == property->klass)) {
2231 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2232 if (mono_error_set_pending_exception (&error))
2238 MONO_STRUCT_SETREF (info, set, rm);
2241 * There may be other methods defined for properties, though, it seems they are not exposed
2242 * in the reflection API
2247 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2250 MonoReflectionType *rt;
2251 MonoReflectionMethod *rm;
2252 MonoDomain *domain = mono_object_domain (event);
2254 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2255 if (mono_error_set_pending_exception (&error))
2258 MONO_STRUCT_SETREF (info, reflected_type, rt);
2260 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2261 if (mono_error_set_pending_exception (&error))
2264 MONO_STRUCT_SETREF (info, declaring_type, rt);
2266 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2267 info->attrs = event->event->attrs;
2269 if (event->event->add) {
2270 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2271 if (mono_error_set_pending_exception (&error))
2277 MONO_STRUCT_SETREF (info, add_method, rm);
2279 if (event->event->remove) {
2280 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2281 if (mono_error_set_pending_exception (&error))
2287 MONO_STRUCT_SETREF (info, remove_method, rm);
2289 if (event->event->raise) {
2290 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2291 if (mono_error_set_pending_exception (&error))
2297 MONO_STRUCT_SETREF (info, raise_method, rm);
2299 #ifndef MONO_SMALL_CONFIG
2300 if (event->event->other) {
2302 while (event->event->other [n])
2304 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2306 for (i = 0; i < n; i++) {
2307 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2308 if (mono_error_set_pending_exception (&error))
2310 mono_array_setref (info->other_methods, i, rm);
2317 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2322 mono_class_setup_interfaces (klass, error);
2323 if (!mono_error_ok (error))
2326 for (i = 0; i < klass->interface_count; i++) {
2327 ic = klass->interfaces [i];
2328 g_hash_table_insert (ifaces, ic, ic);
2330 collect_interfaces (ic, ifaces, error);
2331 if (!mono_error_ok (error))
2337 MonoArray *iface_array;
2338 MonoGenericContext *context;
2342 } FillIfaceArrayData;
2345 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2347 MonoReflectionType *rt;
2348 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2349 MonoClass *ic = (MonoClass *)key;
2350 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2352 if (!mono_error_ok (data->error))
2355 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2356 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2357 if (!mono_error_ok (data->error))
2361 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2362 if (!mono_error_ok (data->error))
2365 mono_array_setref (data->iface_array, data->next_idx++, rt);
2368 mono_metadata_free_type (inflated);
2372 get_interfaces_hash (gconstpointer v1)
2374 MonoClass *k = (MonoClass*)v1;
2376 return k->type_token;
2379 ICALL_EXPORT MonoArray*
2380 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2383 MonoClass *klass = mono_class_from_mono_type (type->type);
2385 FillIfaceArrayData data = { 0 };
2388 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2390 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2391 data.context = mono_class_get_context (klass);
2392 klass = klass->generic_class->container_class;
2395 for (parent = klass; parent; parent = parent->parent) {
2396 mono_class_setup_interfaces (parent, &error);
2397 if (!mono_error_ok (&error))
2399 collect_interfaces (parent, iface_hash, &error);
2400 if (!mono_error_ok (&error))
2404 data.error = &error;
2405 data.domain = mono_object_domain (type);
2407 len = g_hash_table_size (iface_hash);
2409 g_hash_table_destroy (iface_hash);
2410 if (!data.domain->empty_types)
2411 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2412 return data.domain->empty_types;
2415 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2416 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2417 if (!mono_error_ok (&error))
2420 g_hash_table_destroy (iface_hash);
2421 return data.iface_array;
2424 g_hash_table_destroy (iface_hash);
2425 mono_error_set_pending_exception (&error);
2430 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2432 gboolean variance_used;
2433 MonoClass *klass = mono_class_from_mono_type (type->type);
2434 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2435 MonoReflectionMethod *member;
2438 int i = 0, len, ioffset;
2442 mono_class_init_checked (klass, &error);
2443 if (mono_error_set_pending_exception (&error))
2445 mono_class_init_checked (iclass, &error);
2446 if (mono_error_set_pending_exception (&error))
2449 mono_class_setup_vtable (klass);
2451 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2455 len = mono_class_num_methods (iclass);
2456 domain = mono_object_domain (type);
2457 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2458 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2460 while ((method = mono_class_get_methods (iclass, &iter))) {
2461 member = mono_method_get_object_checked (domain, method, iclass, &error);
2462 if (mono_error_set_pending_exception (&error))
2464 mono_array_setref (*methods, i, member);
2465 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2466 if (mono_error_set_pending_exception (&error))
2468 mono_array_setref (*targets, i, member);
2475 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2478 MonoClass *klass = mono_class_from_mono_type (type->type);
2480 mono_class_init_checked (klass, &error);
2481 if (mono_error_set_pending_exception (&error))
2484 if (image_is_dynamic (klass->image)) {
2485 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2486 *packing = tb->packing_size;
2487 *size = tb->class_size;
2489 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2493 ICALL_EXPORT MonoReflectionType*
2494 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2497 MonoReflectionType *ret;
2500 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2501 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2502 mono_error_set_pending_exception (&error);
2506 klass = mono_class_from_mono_type (type->type);
2507 mono_class_init_checked (klass, &error);
2508 if (mono_error_set_pending_exception (&error))
2512 // GetElementType should only return a type for:
2513 // Array Pointer PassedByRef
2514 if (type->type->byref)
2515 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2516 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2517 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2518 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2519 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2523 mono_error_set_pending_exception (&error);
2528 ICALL_EXPORT MonoReflectionType*
2529 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2532 MonoReflectionType *ret;
2534 if (type->type->byref)
2537 MonoClass *klass = mono_class_from_mono_type (type->type);
2541 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2542 mono_error_set_pending_exception (&error);
2547 ICALL_EXPORT MonoBoolean
2548 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2550 return type->type->type == MONO_TYPE_PTR;
2553 ICALL_EXPORT MonoBoolean
2554 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2556 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)));
2559 ICALL_EXPORT MonoBoolean
2560 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2562 return type->type->byref;
2565 ICALL_EXPORT MonoBoolean
2566 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2569 MonoClass *klass = mono_class_from_mono_type (type->type);
2570 mono_class_init_checked (klass, &error);
2571 if (mono_error_set_pending_exception (&error))
2574 return mono_class_is_com_object (klass);
2577 ICALL_EXPORT guint32
2578 ves_icall_reflection_get_token (MonoObject* obj)
2581 guint32 result = mono_reflection_get_token_checked (obj, &error);
2582 mono_error_set_pending_exception (&error);
2586 ICALL_EXPORT MonoReflectionModule*
2587 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2590 MonoReflectionModule *result = NULL;
2591 MonoClass *klass = mono_class_from_mono_type (type->type);
2592 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2593 mono_error_set_pending_exception (&error);
2597 ICALL_EXPORT MonoReflectionAssembly*
2598 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2601 MonoDomain *domain = mono_domain_get ();
2602 MonoClass *klass = mono_class_from_mono_type (type->type);
2603 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2604 mono_error_set_pending_exception (&error);
2608 ICALL_EXPORT MonoReflectionType*
2609 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2612 MonoReflectionType *ret;
2613 MonoDomain *domain = mono_domain_get ();
2616 if (type->type->byref)
2618 if (type->type->type == MONO_TYPE_VAR) {
2619 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2620 klass = param ? param->owner.klass : NULL;
2621 } else if (type->type->type == MONO_TYPE_MVAR) {
2622 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2623 klass = param ? param->owner.method->klass : NULL;
2625 klass = mono_class_from_mono_type (type->type)->nested_in;
2631 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2632 mono_error_set_pending_exception (&error);
2637 ICALL_EXPORT MonoString*
2638 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2640 MonoDomain *domain = mono_domain_get ();
2641 MonoClass *klass = mono_class_from_mono_type (type->type);
2643 if (type->type->byref) {
2644 char *n = g_strdup_printf ("%s&", klass->name);
2645 MonoString *res = mono_string_new (domain, n);
2651 return mono_string_new (domain, klass->name);
2655 ICALL_EXPORT MonoString*
2656 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2658 MonoDomain *domain = mono_domain_get ();
2659 MonoClass *klass = mono_class_from_mono_type (type->type);
2661 while (klass->nested_in)
2662 klass = klass->nested_in;
2664 if (klass->name_space [0] == '\0')
2667 return mono_string_new (domain, klass->name_space);
2671 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2675 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2676 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2680 klass = mono_class_from_mono_type (type->type);
2686 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2689 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2693 ICALL_EXPORT MonoArray*
2694 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2697 MonoReflectionType *rt;
2699 MonoClass *klass, *pklass;
2700 MonoDomain *domain = mono_object_domain (type);
2703 klass = mono_class_from_mono_type (type->type);
2705 if (klass->generic_container) {
2706 MonoGenericContainer *container = klass->generic_container;
2707 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2708 for (i = 0; i < container->type_argc; ++i) {
2709 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2711 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2712 if (mono_error_set_pending_exception (&error))
2715 mono_array_setref (res, i, rt);
2717 } else if (klass->generic_class) {
2718 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2719 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2720 for (i = 0; i < inst->type_argc; ++i) {
2721 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2722 if (mono_error_set_pending_exception (&error))
2725 mono_array_setref (res, i, rt);
2733 ICALL_EXPORT gboolean
2734 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2738 if (!IS_MONOTYPE (type))
2741 if (type->type->byref)
2744 klass = mono_class_from_mono_type (type->type);
2745 return klass->generic_container != NULL;
2748 ICALL_EXPORT MonoReflectionType*
2749 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2752 MonoReflectionType *ret;
2755 if (type->type->byref)
2758 klass = mono_class_from_mono_type (type->type);
2760 if (klass->generic_container) {
2761 return type; /* check this one */
2763 if (klass->generic_class) {
2764 MonoClass *generic_class = klass->generic_class->container_class;
2767 tb = mono_class_get_ref_info (generic_class);
2769 if (generic_class->wastypebuilder && tb)
2770 return (MonoReflectionType *)tb;
2772 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2773 mono_error_set_pending_exception (&error);
2781 ICALL_EXPORT MonoReflectionType*
2782 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2785 MonoReflectionType *ret;
2787 MonoType *geninst, **types;
2790 g_assert (IS_MONOTYPE (type));
2791 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2792 if (mono_error_set_pending_exception (&error))
2795 count = mono_array_length (type_array);
2796 types = g_new0 (MonoType *, count);
2798 for (i = 0; i < count; i++) {
2799 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2800 types [i] = t->type;
2803 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2806 mono_error_set_pending_exception (&error);
2810 klass = mono_class_from_mono_type (geninst);
2812 /*we might inflate to the GTD*/
2813 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2814 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2818 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2819 mono_error_set_pending_exception (&error);
2824 ICALL_EXPORT gboolean
2825 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2829 if (!IS_MONOTYPE (type))
2832 if (type->type->byref)
2835 klass = mono_class_from_mono_type (type->type);
2836 return klass->generic_class != NULL || klass->generic_container != NULL;
2840 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2842 if (!IS_MONOTYPE (type))
2845 if (is_generic_parameter (type->type))
2846 return mono_type_get_generic_param_num (type->type);
2850 ICALL_EXPORT GenericParameterAttributes
2851 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2853 g_assert (IS_MONOTYPE (type));
2854 g_assert (is_generic_parameter (type->type));
2855 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2858 ICALL_EXPORT MonoArray *
2859 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2862 MonoReflectionType *rt;
2863 MonoGenericParamInfo *param_info;
2869 g_assert (IS_MONOTYPE (type));
2871 domain = mono_object_domain (type);
2872 param_info = mono_generic_param_info (type->type->data.generic_param);
2873 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2876 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2877 for (i = 0; i < count; i++) {
2878 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2879 if (mono_error_set_pending_exception (&error))
2882 mono_array_setref (res, i, rt);
2889 ICALL_EXPORT MonoBoolean
2890 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2892 return is_generic_parameter (type->type);
2895 ICALL_EXPORT MonoBoolean
2896 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2898 return is_generic_parameter (tb->type.type);
2902 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2903 MonoReflectionType *t)
2905 enumtype->type = t->type;
2908 ICALL_EXPORT MonoReflectionMethod*
2909 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2910 MonoReflectionMethod* generic)
2917 MonoReflectionMethod *ret = NULL;
2919 domain = ((MonoObject *)type)->vtable->domain;
2921 klass = mono_class_from_mono_type (type->type);
2922 mono_class_init_checked (klass, &error);
2923 if (mono_error_set_pending_exception (&error))
2927 while ((method = mono_class_get_methods (klass, &iter))) {
2928 if (method->token == generic->method->token) {
2929 ret = mono_method_get_object_checked (domain, method, klass, &error);
2930 if (mono_error_set_pending_exception (&error))
2938 ICALL_EXPORT MonoReflectionMethod *
2939 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2942 MonoType *type = ref_type->type;
2944 MonoReflectionMethod *ret = NULL;
2946 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2947 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2950 if (type->type == MONO_TYPE_VAR)
2953 method = mono_type_get_generic_param_owner (type)->owner.method;
2956 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2957 if (!mono_error_ok (&error))
2958 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2962 ICALL_EXPORT MonoBoolean
2963 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2965 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2969 ICALL_EXPORT MonoBoolean
2970 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2972 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2977 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2979 MonoDomain *domain = mono_domain_get ();
2980 MonoImage *image = method->method->klass->image;
2981 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2982 MonoTableInfo *tables = image->tables;
2983 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2984 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2985 guint32 im_cols [MONO_IMPLMAP_SIZE];
2986 guint32 scope_token;
2987 const char *import = NULL;
2988 const char *scope = NULL;
2990 if (image_is_dynamic (image)) {
2991 MonoReflectionMethodAux *method_aux =
2992 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2994 import = method_aux->dllentry;
2995 scope = method_aux->dll;
2998 if (!import || !scope) {
2999 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
3004 if (piinfo->implmap_idx) {
3005 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
3007 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
3008 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
3009 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
3010 scope = mono_metadata_string_heap (image, scope_token);
3014 *flags = piinfo->piflags;
3015 *entry_point = mono_string_new (domain, import);
3016 *dll_name = mono_string_new (domain, scope);
3019 ICALL_EXPORT MonoReflectionMethod *
3020 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3022 MonoMethodInflated *imethod;
3024 MonoReflectionMethod *ret = NULL;
3027 if (method->method->is_generic)
3030 if (!method->method->is_inflated)
3033 imethod = (MonoMethodInflated *) method->method;
3035 result = imethod->declaring;
3036 /* Not a generic method. */
3037 if (!result->is_generic)
3040 if (image_is_dynamic (method->method->klass->image)) {
3041 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3042 MonoReflectionMethod *res;
3045 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3046 * the dynamic case as well ?
3048 mono_image_lock ((MonoImage*)image);
3049 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3050 mono_image_unlock ((MonoImage*)image);
3056 if (imethod->context.class_inst) {
3057 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3058 /*Generic methods gets the context of the GTD.*/
3059 if (mono_class_get_context (klass)) {
3060 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3061 if (!mono_error_ok (&error))
3066 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3068 if (!mono_error_ok (&error))
3069 mono_error_set_pending_exception (&error);
3073 ICALL_EXPORT gboolean
3074 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3076 return mono_method_signature (method->method)->generic_param_count != 0;
3079 ICALL_EXPORT gboolean
3080 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3082 return method->method->is_generic;
3085 ICALL_EXPORT MonoArray*
3086 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3089 MonoReflectionType *rt;
3094 domain = mono_object_domain (method);
3096 if (method->method->is_inflated) {
3097 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3100 count = inst->type_argc;
3101 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3103 for (i = 0; i < count; i++) {
3104 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3105 if (mono_error_set_pending_exception (&error))
3108 mono_array_setref (res, i, rt);
3115 count = mono_method_signature (method->method)->generic_param_count;
3116 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3118 for (i = 0; i < count; i++) {
3119 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3120 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3121 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3123 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3124 if (mono_error_set_pending_exception (&error))
3127 mono_array_setref (res, i, rt);
3133 ICALL_EXPORT MonoObject *
3134 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3138 * Invoke from reflection is supposed to always be a virtual call (the API
3139 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3140 * greater flexibility.
3142 MonoMethod *m = method->method;
3143 MonoMethodSignature *sig = mono_method_signature (m);
3146 void *obj = this_arg;
3150 if (mono_security_core_clr_enabled () &&
3151 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3152 mono_error_set_pending_exception (&error);
3156 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3157 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3158 mono_error_cleanup (&error); /* FIXME does this make sense? */
3159 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3164 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3165 if (!is_ok (&error)) {
3166 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3169 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3170 char *target_name = mono_type_get_full_name (m->klass);
3171 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3172 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3174 g_free (target_name);
3178 m = mono_object_get_virtual_method (this_arg, m);
3179 /* must pass the pointer to the value for valuetype methods */
3180 if (m->klass->valuetype)
3181 obj = mono_object_unbox (this_arg);
3182 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3183 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3188 if (sig->ret->byref) {
3189 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"));
3193 pcount = params? mono_array_length (params): 0;
3194 if (pcount != sig->param_count) {
3195 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3199 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3200 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."));
3204 image = m->klass->image;
3205 if (image->assembly->ref_only) {
3206 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."));
3210 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3211 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3215 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3219 intptr_t *lower_bounds;
3220 pcount = mono_array_length (params);
3221 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3222 /* Note: the synthetized array .ctors have int32 as argument type */
3223 for (i = 0; i < pcount; ++i)
3224 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3226 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3227 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3228 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3229 if (!mono_error_ok (&error)) {
3230 mono_error_set_pending_exception (&error);
3234 for (i = 0; i < mono_array_length (arr); ++i) {
3235 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3236 if (!mono_error_ok (&error)) {
3237 mono_error_set_pending_exception (&error);
3240 mono_array_setref_fast (arr, i, subarray);
3242 return (MonoObject*)arr;
3245 if (m->klass->rank == pcount) {
3246 /* Only lengths provided. */
3247 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3248 if (!mono_error_ok (&error)) {
3249 mono_error_set_pending_exception (&error);
3253 return (MonoObject*)arr;
3255 g_assert (pcount == (m->klass->rank * 2));
3256 /* The arguments are lower-bound-length pairs */
3257 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3259 for (i = 0; i < pcount / 2; ++i) {
3260 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3261 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3264 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3265 if (!mono_error_ok (&error)) {
3266 mono_error_set_pending_exception (&error);
3270 return (MonoObject*)arr;
3273 return mono_runtime_invoke_array (m, obj, params, NULL);
3276 #ifndef DISABLE_REMOTING
3277 ICALL_EXPORT MonoObject *
3278 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3281 MonoDomain *domain = mono_object_domain (method);
3282 MonoMethod *m = method->method;
3283 MonoMethodSignature *sig = mono_method_signature (m);
3284 MonoArray *out_args;
3286 int i, j, outarg_count = 0;
3288 if (m->klass == mono_defaults.object_class) {
3289 if (!strcmp (m->name, "FieldGetter")) {
3290 MonoClass *k = this_arg->vtable->klass;
3294 /* If this is a proxy, then it must be a CBO */
3295 if (k == mono_defaults.transparent_proxy_class) {
3296 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3297 this_arg = tp->rp->unwrapped_server;
3298 g_assert (this_arg);
3299 k = this_arg->vtable->klass;
3302 name = mono_array_get (params, MonoString *, 1);
3303 str = mono_string_to_utf8 (name);
3306 MonoClassField* field = mono_class_get_field_from_name (k, str);
3308 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3309 if (field_klass->valuetype) {
3310 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3311 mono_error_set_pending_exception (&error);
3312 /* fallthru to cleanup */
3314 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3316 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3317 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3318 mono_array_setref (out_args, 0, result);
3326 g_assert_not_reached ();
3328 } else if (!strcmp (m->name, "FieldSetter")) {
3329 MonoClass *k = this_arg->vtable->klass;
3335 /* If this is a proxy, then it must be a CBO */
3336 if (k == mono_defaults.transparent_proxy_class) {
3337 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3338 this_arg = tp->rp->unwrapped_server;
3339 g_assert (this_arg);
3340 k = this_arg->vtable->klass;
3343 name = mono_array_get (params, MonoString *, 1);
3344 str = mono_string_to_utf8 (name);
3347 MonoClassField* field = mono_class_get_field_from_name (k, str);
3349 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3350 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3352 if (field_klass->valuetype) {
3353 size = mono_type_size (field->type, &align);
3354 g_assert (size == mono_class_value_size (field_klass, NULL));
3355 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3357 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3360 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3361 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3371 g_assert_not_reached ();
3376 for (i = 0; i < mono_array_length (params); i++) {
3377 if (sig->params [i]->byref)
3381 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3383 /* handle constructors only for objects already allocated */
3384 if (!strcmp (method->method->name, ".ctor"))
3385 g_assert (this_arg);
3387 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3388 g_assert (!method->method->klass->valuetype);
3389 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3391 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3392 if (sig->params [i]->byref) {
3394 arg = mono_array_get (params, gpointer, i);
3395 mono_array_setref (out_args, j, arg);
3400 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3407 read_enum_value (const char *mem, int type)
3410 case MONO_TYPE_BOOLEAN:
3412 return *(guint8*)mem;
3414 return *(gint8*)mem;
3415 case MONO_TYPE_CHAR:
3417 return read16 (mem);
3419 return (gint16) read16 (mem);
3421 return read32 (mem);
3423 return (gint32) read32 (mem);
3426 return read64 (mem);
3428 g_assert_not_reached ();
3434 write_enum_value (char *mem, int type, guint64 value)
3438 case MONO_TYPE_I1: {
3439 guint8 *p = (guint8*)mem;
3444 case MONO_TYPE_I2: {
3445 guint16 *p = (guint16 *)mem;
3450 case MONO_TYPE_I4: {
3451 guint32 *p = (guint32 *)mem;
3456 case MONO_TYPE_I8: {
3457 guint64 *p = (guint64 *)mem;
3462 g_assert_not_reached ();
3467 ICALL_EXPORT MonoObject *
3468 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3476 domain = mono_object_domain (enumType);
3477 enumc = mono_class_from_mono_type (enumType->type);
3479 mono_class_init_checked (enumc, &error);
3480 if (mono_error_set_pending_exception (&error))
3483 etype = mono_class_enum_basetype (enumc);
3485 res = mono_object_new_checked (domain, enumc, &error);
3486 if (mono_error_set_pending_exception (&error))
3488 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3493 ICALL_EXPORT MonoBoolean
3494 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3496 int size = mono_class_value_size (a->vtable->klass, NULL);
3497 guint64 a_val = 0, b_val = 0;
3499 memcpy (&a_val, mono_object_unbox (a), size);
3500 memcpy (&b_val, mono_object_unbox (b), size);
3502 return (a_val & b_val) == b_val;
3505 ICALL_EXPORT MonoObject *
3506 ves_icall_System_Enum_get_value (MonoObject *eobj)
3518 g_assert (eobj->vtable->klass->enumtype);
3520 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3521 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3522 if (mono_error_set_pending_exception (&error))
3524 dst = (char *)res + sizeof (MonoObject);
3525 src = (char *)eobj + sizeof (MonoObject);
3526 size = mono_class_value_size (enumc, NULL);
3528 memcpy (dst, src, size);
3533 ICALL_EXPORT MonoReflectionType *
3534 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3537 MonoReflectionType *ret;
3541 klass = mono_class_from_mono_type (type->type);
3542 mono_class_init_checked (klass, &error);
3543 if (mono_error_set_pending_exception (&error))
3546 etype = mono_class_enum_basetype (klass);
3548 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3552 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3553 mono_error_set_pending_exception (&error);
3559 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3561 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3562 gpointer odata = (char *)other + sizeof (MonoObject);
3563 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3564 g_assert (basetype);
3569 if (eobj->vtable->klass != other->vtable->klass)
3572 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3573 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3574 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3577 return me > other ? 1 : -1; \
3580 switch (basetype->type) {
3582 COMPARE_ENUM_VALUES (guint8);
3584 COMPARE_ENUM_VALUES (gint8);
3585 case MONO_TYPE_CHAR:
3587 COMPARE_ENUM_VALUES (guint16);
3589 COMPARE_ENUM_VALUES (gint16);
3591 COMPARE_ENUM_VALUES (guint32);
3593 COMPARE_ENUM_VALUES (gint32);
3595 COMPARE_ENUM_VALUES (guint64);
3597 COMPARE_ENUM_VALUES (gint64);
3601 #undef COMPARE_ENUM_VALUES
3602 /* indicates that the enum was of an unsupported unerlying type */
3607 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3609 gpointer data = (char *)eobj + sizeof (MonoObject);
3610 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3611 g_assert (basetype);
3613 switch (basetype->type) {
3614 case MONO_TYPE_I1: {
3615 gint8 value = *((gint8*)data);
3616 return ((int)value ^ (int)value << 8);
3619 return *((guint8*)data);
3620 case MONO_TYPE_CHAR:
3622 return *((guint16*)data);
3624 case MONO_TYPE_I2: {
3625 gint16 value = *((gint16*)data);
3626 return ((int)(guint16)value | (((int)value) << 16));
3629 return *((guint32*)data);
3631 return *((gint32*)data);
3633 case MONO_TYPE_I8: {
3634 gint64 value = *((gint64*)data);
3635 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3638 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3643 ICALL_EXPORT MonoBoolean
3644 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3647 MonoDomain *domain = mono_object_domain (type);
3648 MonoClass *enumc = mono_class_from_mono_type (type->type);
3649 guint j = 0, nvalues;
3651 MonoClassField *field;
3653 guint64 field_value, previous_value = 0;
3654 gboolean sorted = TRUE;
3656 mono_class_init_checked (enumc, &error);
3657 if (mono_error_set_pending_exception (&error))
3661 if (!enumc->enumtype) {
3662 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3666 base_type = mono_class_enum_basetype (enumc)->type;
3668 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3669 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3670 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3673 while ((field = mono_class_get_fields (enumc, &iter))) {
3675 MonoTypeEnum def_type;
3677 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3679 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3681 if (mono_field_is_deleted (field))
3683 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3685 p = mono_class_get_field_default_value (field, &def_type);
3686 /* len = */ mono_metadata_decode_blob_size (p, &p);
3688 field_value = read_enum_value (p, base_type);
3689 mono_array_set (*values, guint64, j, field_value);
3691 if (previous_value > field_value)
3694 previous_value = field_value;
3702 BFLAGS_IgnoreCase = 1,
3703 BFLAGS_DeclaredOnly = 2,
3704 BFLAGS_Instance = 4,
3706 BFLAGS_Public = 0x10,
3707 BFLAGS_NonPublic = 0x20,
3708 BFLAGS_FlattenHierarchy = 0x40,
3709 BFLAGS_InvokeMethod = 0x100,
3710 BFLAGS_CreateInstance = 0x200,
3711 BFLAGS_GetField = 0x400,
3712 BFLAGS_SetField = 0x800,
3713 BFLAGS_GetProperty = 0x1000,
3714 BFLAGS_SetProperty = 0x2000,
3715 BFLAGS_ExactBinding = 0x10000,
3716 BFLAGS_SuppressChangeType = 0x20000,
3717 BFLAGS_OptionalParamBinding = 0x40000
3720 ICALL_EXPORT MonoArray*
3721 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3725 MonoClass *startklass, *klass, *refklass;
3730 char *utf8_name = NULL;
3731 int (*compare_func) (const char *s1, const char *s2) = NULL;
3732 MonoClassField *field;
3733 MonoPtrArray tmp_array;
3735 domain = ((MonoObject *)type)->vtable->domain;
3736 if (type->type->byref)
3737 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3739 klass = startklass = mono_class_from_mono_type (type->type);
3740 refklass = mono_class_from_mono_type (reftype->type);
3742 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3745 if (mono_class_has_failure (klass)) {
3746 mono_ptr_array_destroy (tmp_array);
3747 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3752 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3753 guint32 flags = mono_field_get_flags (field);
3755 if (mono_field_is_deleted_with_flags (field, flags))
3757 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3758 if (bflags & BFLAGS_Public)
3760 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3761 if (bflags & BFLAGS_NonPublic) {
3768 if (flags & FIELD_ATTRIBUTE_STATIC) {
3769 if (bflags & BFLAGS_Static)
3770 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3773 if (bflags & BFLAGS_Instance)
3781 if (utf8_name == NULL) {
3782 utf8_name = mono_string_to_utf8 (name);
3783 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3786 if (compare_func (mono_field_get_name (field), utf8_name))
3790 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3791 if (!mono_error_ok (&error))
3793 mono_ptr_array_append (tmp_array, member);
3795 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3798 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3800 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3801 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3803 mono_ptr_array_destroy (tmp_array);
3805 if (utf8_name != NULL)
3810 mono_ptr_array_destroy (tmp_array);
3811 mono_error_set_pending_exception (&error);
3816 method_nonpublic (MonoMethod* method, gboolean start_klass)
3818 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3819 case METHOD_ATTRIBUTE_ASSEM:
3820 return (start_klass || mono_defaults.generic_ilist_class);
3821 case METHOD_ATTRIBUTE_PRIVATE:
3823 case METHOD_ATTRIBUTE_PUBLIC:
3831 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3834 MonoClass *startklass;
3838 /*FIXME, use MonoBitSet*/
3839 guint32 method_slots_default [8];
3840 guint32 *method_slots = NULL;
3841 int (*compare_func) (const char *s1, const char *s2) = NULL;
3843 array = g_ptr_array_new ();
3848 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3850 /* An optimization for calls made from Delegate:CreateDelegate () */
3851 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3852 method = mono_get_delegate_invoke (klass);
3855 g_ptr_array_add (array, method);
3859 mono_class_setup_methods (klass);
3860 mono_class_setup_vtable (klass);
3861 if (mono_class_has_failure (klass))
3864 if (is_generic_parameter (&klass->byval_arg))
3865 nslots = mono_class_get_vtable_size (klass->parent);
3867 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3868 if (nslots >= sizeof (method_slots_default) * 8) {
3869 method_slots = g_new0 (guint32, nslots / 32 + 1);
3871 method_slots = method_slots_default;
3872 memset (method_slots, 0, sizeof (method_slots_default));
3875 mono_class_setup_methods (klass);
3876 mono_class_setup_vtable (klass);
3877 if (mono_class_has_failure (klass))
3881 while ((method = mono_class_get_methods (klass, &iter))) {
3883 if (method->slot != -1) {
3884 g_assert (method->slot < nslots);
3885 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3887 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3888 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3891 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3893 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3894 if (bflags & BFLAGS_Public)
3896 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3902 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3903 if (bflags & BFLAGS_Static)
3904 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3907 if (bflags & BFLAGS_Instance)
3915 if (compare_func (name, method->name))
3920 g_ptr_array_add (array, method);
3922 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3924 if (method_slots != method_slots_default)
3925 g_free (method_slots);
3930 if (method_slots != method_slots_default)
3931 g_free (method_slots);
3932 g_ptr_array_free (array, TRUE);
3934 if (mono_class_has_failure (klass)) {
3935 *ex = mono_class_get_exception_for_failure (klass);
3937 *ex = mono_get_exception_execution_engine ("Unknown error");
3942 ICALL_EXPORT MonoArray*
3943 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3945 static MonoClass *MethodInfo_array;
3949 MonoVTable *array_vtable;
3950 MonoException *ex = NULL;
3951 const char *mname = NULL;
3952 GPtrArray *method_array;
3953 MonoClass *klass, *refklass;
3956 mono_error_init (&error);
3958 if (!MethodInfo_array) {
3959 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3960 mono_memory_barrier ();
3961 MethodInfo_array = klass;
3964 klass = mono_class_from_mono_type (type->type);
3965 refklass = mono_class_from_mono_type (reftype->type);
3966 domain = ((MonoObject *)type)->vtable->domain;
3967 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3968 if (!is_ok (&error)) {
3969 mono_error_set_pending_exception (&error);
3972 if (type->type->byref) {
3973 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3974 mono_error_set_pending_exception (&error);
3980 mname = mono_string_to_utf8 (name);
3982 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3983 g_free ((char*)mname);
3985 mono_set_pending_exception (ex);
3989 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3990 if (!mono_error_ok (&error)) {
3991 mono_error_set_pending_exception (&error);
3995 for (i = 0; i < method_array->len; ++i) {
3996 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3997 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3998 if (!mono_error_ok (&error))
4000 mono_array_setref (res, i, rm);
4004 g_ptr_array_free (method_array, TRUE);
4005 if (!mono_error_ok (&error))
4006 mono_set_pending_exception (mono_error_convert_to_exception (&error));
4010 ICALL_EXPORT MonoArray*
4011 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4014 MonoClass *startklass, *klass, *refklass;
4019 gpointer iter = NULL;
4020 MonoPtrArray tmp_array;
4023 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
4025 domain = ((MonoObject *)type)->vtable->domain;
4026 if (type->type->byref)
4027 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
4028 klass = startklass = mono_class_from_mono_type (type->type);
4029 refklass = mono_class_from_mono_type (reftype->type);
4031 mono_class_setup_methods (klass);
4032 if (mono_class_has_failure (klass)) {
4033 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
4038 while ((method = mono_class_get_methods (klass, &iter))) {
4040 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
4042 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4043 if (bflags & BFLAGS_Public)
4046 if (bflags & BFLAGS_NonPublic)
4052 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4053 if (bflags & BFLAGS_Static)
4054 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4057 if (bflags & BFLAGS_Instance)
4063 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
4064 if (!mono_error_ok (&error)) {
4065 mono_error_set_pending_exception (&error);
4069 mono_ptr_array_append (tmp_array, member);
4072 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
4074 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4075 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4077 mono_ptr_array_destroy (tmp_array);
4083 property_hash (gconstpointer data)
4085 MonoProperty *prop = (MonoProperty*)data;
4087 return g_str_hash (prop->name);
4091 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
4093 if (method1->is_inflated)
4094 method1 = ((MonoMethodInflated*) method1)->declaring;
4095 if (method2->is_inflated)
4096 method2 = ((MonoMethodInflated*) method2)->declaring;
4098 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4102 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4104 // Properties are hide-by-name-and-signature
4105 if (!g_str_equal (prop1->name, prop2->name))
4108 /* If we see a property in a generic method, we want to
4109 compare the generic signatures, not the inflated signatures
4110 because we might conflate two properties that were
4114 public T this[T t] { getter { return t; } } // method 1
4115 public U this[U u] { getter { return u; } } // method 2
4118 If we see int Foo<int,int>::Item[int] we need to know if
4119 the indexer came from method 1 or from method 2, and we
4120 shouldn't conflate them. (Bugzilla 36283)
4122 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
4125 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4132 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4137 return method_nonpublic (accessor, start_klass);
4140 ICALL_EXPORT MonoArray*
4141 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4145 MonoClass *startklass, *klass;
4151 gchar *propname = NULL;
4152 int (*compare_func) (const char *s1, const char *s2) = NULL;
4154 GHashTable *properties = NULL;
4155 MonoPtrArray tmp_array;
4157 mono_error_init (&error);
4159 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4161 domain = ((MonoObject *)type)->vtable->domain;
4162 if (type->type->byref)
4163 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
4164 klass = startklass = mono_class_from_mono_type (type->type);
4167 propname = mono_string_to_utf8 (name);
4168 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4171 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4173 mono_class_setup_methods (klass);
4174 mono_class_setup_vtable (klass);
4175 if (mono_class_has_failure (klass))
4179 while ((prop = mono_class_get_properties (klass, &iter))) {
4185 flags = method->flags;
4188 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4189 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4190 if (bflags & BFLAGS_Public)
4192 } else if (bflags & BFLAGS_NonPublic) {
4193 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4194 property_accessor_nonpublic(prop->set, startklass == klass)) {
4201 if (flags & METHOD_ATTRIBUTE_STATIC) {
4202 if (bflags & BFLAGS_Static)
4203 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4206 if (bflags & BFLAGS_Instance)
4215 if (compare_func (propname, prop->name))
4219 if (g_hash_table_lookup (properties, prop))
4222 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4225 mono_ptr_array_append (tmp_array, pr);
4227 g_hash_table_insert (properties, prop, prop);
4229 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4232 g_hash_table_destroy (properties);
4235 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4236 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4237 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4239 mono_ptr_array_destroy (tmp_array);
4246 if (mono_class_has_failure (klass)) {
4247 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4252 g_hash_table_destroy (properties);
4255 mono_ptr_array_destroy (tmp_array);
4257 mono_error_set_pending_exception (&error);
4263 event_hash (gconstpointer data)
4265 MonoEvent *event = (MonoEvent*)data;
4267 return g_str_hash (event->name);
4271 event_equal (MonoEvent *event1, MonoEvent *event2)
4273 // Events are hide-by-name
4274 return g_str_equal (event1->name, event2->name);
4277 ICALL_EXPORT MonoArray*
4278 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4282 MonoClass *startklass, *klass;
4288 char *utf8_name = NULL;
4289 int (*compare_func) (const char *s1, const char *s2) = NULL;
4290 GHashTable *events = NULL;
4291 MonoPtrArray tmp_array;
4293 mono_error_init (&error);
4295 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4297 domain = mono_object_domain (type);
4298 if (type->type->byref)
4299 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4300 klass = startklass = mono_class_from_mono_type (type->type);
4302 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4304 mono_class_setup_methods (klass);
4305 mono_class_setup_vtable (klass);
4306 if (mono_class_has_failure (klass))
4310 while ((event = mono_class_get_events (klass, &iter))) {
4312 method = event->add;
4314 method = event->remove;
4316 method = event->raise;
4318 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4319 if (bflags & BFLAGS_Public)
4321 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4322 if (bflags & BFLAGS_NonPublic)
4327 if (bflags & BFLAGS_NonPublic)
4333 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4334 if (bflags & BFLAGS_Static)
4335 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4338 if (bflags & BFLAGS_Instance)
4343 if (bflags & BFLAGS_Instance)
4349 if (utf8_name == NULL) {
4350 utf8_name = mono_string_to_utf8 (name);
4351 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4354 if (compare_func (event->name, utf8_name))
4358 if (g_hash_table_lookup (events, event))
4361 MonoReflectionEvent *ev_obj;
4362 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4365 mono_ptr_array_append (tmp_array, ev_obj);
4367 g_hash_table_insert (events, event, event);
4369 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4372 g_hash_table_destroy (events);
4374 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4376 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4377 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4379 mono_ptr_array_destroy (tmp_array);
4381 if (utf8_name != NULL)
4387 if (mono_class_has_failure (klass)) {
4388 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4394 g_hash_table_destroy (events);
4395 if (utf8_name != NULL)
4398 mono_ptr_array_destroy (tmp_array);
4400 mono_error_set_pending_exception (&error);
4404 ICALL_EXPORT MonoArray*
4405 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4408 MonoReflectionType *rt;
4411 MonoArray *res = NULL;
4416 MonoPtrArray tmp_array;
4418 mono_error_init (&error);
4420 domain = ((MonoObject *)type)->vtable->domain;
4421 if (type->type->byref)
4422 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4423 klass = mono_class_from_mono_type (type->type);
4426 * If a nested type is generic, return its generic type definition.
4427 * Note that this means that the return value is essentially the set
4428 * of nested types of the generic type definition of @klass.
4430 * A note in MSDN claims that a generic type definition can have
4431 * nested types that aren't generic. In any case, the container of that
4432 * nested type would be the generic type definition.
4434 if (klass->generic_class)
4435 klass = klass->generic_class->container_class;
4437 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4439 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4441 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4442 if (bflags & BFLAGS_Public)
4445 if (bflags & BFLAGS_NonPublic)
4453 str = mono_string_to_utf8 (name);
4454 mono_identifier_unescape_type_name_chars (str);
4457 if (strcmp (nested->name, str))
4461 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4462 if (!is_ok (&error))
4465 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4468 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4470 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4471 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4474 mono_ptr_array_destroy (tmp_array);
4478 mono_error_set_pending_exception (&error);
4482 ICALL_EXPORT MonoReflectionType*
4483 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4486 MonoReflectionType *ret;
4488 MonoType *type = NULL;
4489 MonoTypeNameParse info;
4490 gboolean type_resolve;
4492 /* On MS.NET, this does not fire a TypeResolve event */
4493 type_resolve = TRUE;
4494 str = mono_string_to_utf8 (name);
4495 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4496 if (!mono_reflection_parse_type (str, &info)) {
4498 mono_reflection_free_type_info (&info);
4500 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4503 /*g_print ("failed parse\n");*/
4507 if (info.assembly.name) {
4509 mono_reflection_free_type_info (&info);
4511 /* 1.0 and 2.0 throw different exceptions */
4512 if (mono_defaults.generic_ilist_class)
4513 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4515 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4521 if (module != NULL) {
4522 if (module->image) {
4523 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4524 if (!is_ok (&error)) {
4526 mono_reflection_free_type_info (&info);
4527 mono_error_set_pending_exception (&error);
4534 if (assembly_is_dynamic (assembly->assembly)) {
4535 /* Enumerate all modules */
4536 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4540 if (abuilder->modules) {
4541 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4542 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4543 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4544 if (!is_ok (&error)) {
4546 mono_reflection_free_type_info (&info);
4547 mono_error_set_pending_exception (&error);
4555 if (!type && abuilder->loaded_modules) {
4556 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4557 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4558 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4559 if (!is_ok (&error)) {
4561 mono_reflection_free_type_info (&info);
4562 mono_error_set_pending_exception (&error);
4571 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4572 if (!is_ok (&error)) {
4574 mono_reflection_free_type_info (&info);
4575 mono_error_set_pending_exception (&error);
4580 mono_reflection_free_type_info (&info);
4582 MonoException *e = NULL;
4585 e = mono_get_exception_type_load (name, NULL);
4588 mono_set_pending_exception (e);
4592 if (type->type == MONO_TYPE_CLASS) {
4593 MonoClass *klass = mono_type_get_class (type);
4595 /* need to report exceptions ? */
4596 if (throwOnError && mono_class_has_failure (klass)) {
4597 /* report SecurityException (or others) that occured when loading the assembly */
4598 MonoException *exc = mono_class_get_exception_for_failure (klass);
4599 mono_set_pending_exception (exc);
4604 /* g_print ("got it\n"); */
4605 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4606 mono_error_set_pending_exception (&error);
4612 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4615 gchar *shadow_ini_file;
4618 /* Check for shadow-copied assembly */
4619 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4620 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4622 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4623 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4629 g_free (shadow_ini_file);
4630 if (content != NULL) {
4633 *filename = content;
4640 ICALL_EXPORT MonoString *
4641 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4643 MonoDomain *domain = mono_object_domain (assembly);
4644 MonoAssembly *mass = assembly->assembly;
4645 MonoString *res = NULL;
4650 if (g_path_is_absolute (mass->image->name)) {
4651 absolute = g_strdup (mass->image->name);
4652 dirname = g_path_get_dirname (absolute);
4654 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4655 dirname = g_strdup (mass->basedir);
4658 replace_shadow_path (domain, dirname, &absolute);
4663 for (i = strlen (absolute) - 1; i >= 0; i--)
4664 if (absolute [i] == '\\')
4669 uri = g_filename_to_uri (absolute, NULL, NULL);
4671 const char *prepend = "file://";
4673 if (*absolute == '/' && *(absolute + 1) == '/') {
4676 prepend = "file:///";
4679 uri = g_strconcat (prepend, absolute, NULL);
4683 res = mono_string_new (domain, uri);
4690 ICALL_EXPORT MonoBoolean
4691 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4693 MonoAssembly *mass = assembly->assembly;
4695 return mass->in_gac;
4698 ICALL_EXPORT MonoReflectionAssembly*
4699 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4704 MonoImageOpenStatus status;
4705 MonoReflectionAssembly* result = NULL;
4707 name = mono_string_to_utf8 (mname);
4708 res = mono_assembly_load_with_partial_name (name, &status);
4714 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4716 mono_error_set_pending_exception (&error);
4720 ICALL_EXPORT MonoString *
4721 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4723 MonoDomain *domain = mono_object_domain (assembly);
4726 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4731 ICALL_EXPORT MonoBoolean
4732 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4734 return assembly->assembly->ref_only;
4737 ICALL_EXPORT MonoString *
4738 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4740 MonoDomain *domain = mono_object_domain (assembly);
4742 return mono_string_new (domain, assembly->assembly->image->version);
4745 ICALL_EXPORT MonoReflectionMethod*
4746 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4749 MonoReflectionMethod *res = NULL;
4752 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4756 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4757 if (!mono_error_ok (&error))
4760 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4763 if (!mono_error_ok (&error))
4764 mono_error_set_pending_exception (&error);
4768 ICALL_EXPORT MonoReflectionModule*
4769 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4772 MonoReflectionModule *result = NULL;
4773 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4774 if (!mono_error_ok (&error))
4775 mono_error_set_pending_exception (&error);
4779 ICALL_EXPORT MonoArray*
4780 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4782 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4783 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4787 for (i = 0; i < table->rows; ++i) {
4788 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4789 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4795 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4797 static MonoMethod *create_version = NULL;
4801 mono_error_init (error);
4804 if (!create_version) {
4805 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4806 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4807 g_assert (create_version);
4808 mono_method_desc_free (desc);
4814 args [3] = &revision;
4815 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4816 return_val_if_nok (error, NULL);
4818 mono_runtime_invoke_checked (create_version, result, args, error);
4819 return_val_if_nok (error, NULL);
4824 ICALL_EXPORT MonoArray*
4825 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4829 MonoDomain *domain = mono_object_domain (assembly);
4831 static MonoMethod *create_culture = NULL;
4832 MonoImage *image = assembly->assembly->image;
4836 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4839 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4841 if (count > 0 && !create_culture) {
4842 MonoMethodDesc *desc = mono_method_desc_new (
4843 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4844 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4845 g_assert (create_culture);
4846 mono_method_desc_free (desc);
4849 for (i = 0; i < count; i++) {
4850 MonoObject *version;
4851 MonoReflectionAssemblyName *aname;
4852 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4854 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4856 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4857 domain, mono_class_get_assembly_name_class (), &error);
4858 if (mono_error_set_pending_exception (&error))
4861 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4863 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4864 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4865 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4866 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4867 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4868 aname->versioncompat = 1; /* SameMachine (default) */
4869 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4871 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4872 if (mono_error_set_pending_exception (&error))
4875 MONO_OBJECT_SETREF (aname, version, version);
4877 if (create_culture) {
4879 MonoBoolean assembly_ref = 1;
4880 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4881 args [1] = &assembly_ref;
4883 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4884 if (mono_error_set_pending_exception (&error))
4887 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4890 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4891 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4892 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4894 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4895 /* public key token isn't copied - the class library will
4896 automatically generate it from the public key if required */
4897 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4898 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4900 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4901 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4904 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4907 /* note: this function doesn't return the codebase on purpose (i.e. it can
4908 be used under partial trust as path information isn't present). */
4910 mono_array_setref (result, i, aname);
4915 /* move this in some file in mono/util/ */
4917 g_concat_dir_and_file (const char *dir, const char *file)
4919 g_return_val_if_fail (dir != NULL, NULL);
4920 g_return_val_if_fail (file != NULL, NULL);
4923 * If the directory name doesn't have a / on the end, we need
4924 * to add one so we get a proper path to the file
4926 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4927 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4929 return g_strconcat (dir, file, NULL);
4933 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4936 char *n = mono_string_to_utf8 (name);
4937 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4939 guint32 cols [MONO_MANIFEST_SIZE];
4940 guint32 impl, file_idx;
4944 for (i = 0; i < table->rows; ++i) {
4945 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4946 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4947 if (strcmp (val, n) == 0)
4951 if (i == table->rows)
4954 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4957 * this code should only be called after obtaining the
4958 * ResourceInfo and handling the other cases.
4960 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4961 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4963 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4968 module = assembly->assembly->image;
4971 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4972 if (mono_error_set_pending_exception (&error))
4974 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4976 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4979 ICALL_EXPORT gboolean
4980 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4983 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4985 guint32 cols [MONO_MANIFEST_SIZE];
4986 guint32 file_cols [MONO_FILE_SIZE];
4990 n = mono_string_to_utf8 (name);
4991 for (i = 0; i < table->rows; ++i) {
4992 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4993 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4994 if (strcmp (val, n) == 0)
4998 if (i == table->rows)
5001 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
5002 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
5005 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
5006 case MONO_IMPLEMENTATION_FILE:
5007 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5008 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5009 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
5010 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
5011 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
5012 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
5015 info->location = RESOURCE_LOCATION_EMBEDDED;
5018 case MONO_IMPLEMENTATION_ASSEMBLYREF:
5019 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5020 mono_assembly_load_reference (assembly->assembly->image, i - 1);
5021 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
5022 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
5023 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
5025 mono_set_pending_exception (ex);
5028 MonoReflectionAssembly *assm_obj;
5029 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5031 mono_error_set_pending_exception (&error);
5034 MONO_OBJECT_SETREF (info, assembly, assm_obj);
5036 /* Obtain info recursively */
5037 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5038 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5041 case MONO_IMPLEMENTATION_EXP_TYPE:
5042 g_assert_not_reached ();
5050 ICALL_EXPORT MonoObject*
5051 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
5053 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5054 MonoArray *result = NULL;
5059 /* check hash if needed */
5061 n = mono_string_to_utf8 (name);
5062 for (i = 0; i < table->rows; ++i) {
5063 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5064 if (strcmp (val, n) == 0) {
5067 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5068 fn = mono_string_new (mono_object_domain (assembly), n);
5070 return (MonoObject*)fn;
5078 for (i = 0; i < table->rows; ++i) {
5079 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5083 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
5086 for (i = 0; i < table->rows; ++i) {
5087 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5088 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5089 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5090 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5095 return (MonoObject*)result;
5098 ICALL_EXPORT MonoArray*
5099 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5102 MonoDomain *domain = mono_domain_get();
5105 int i, j, file_count = 0;
5106 MonoImage **modules;
5107 guint32 module_count, real_module_count;
5108 MonoTableInfo *table;
5109 guint32 cols [MONO_FILE_SIZE];
5110 MonoImage *image = assembly->assembly->image;
5112 g_assert (image != NULL);
5113 g_assert (!assembly_is_dynamic (assembly->assembly));
5115 table = &image->tables [MONO_TABLE_FILE];
5116 file_count = table->rows;
5118 modules = image->modules;
5119 module_count = image->module_count;
5121 real_module_count = 0;
5122 for (i = 0; i < module_count; ++i)
5124 real_module_count ++;
5126 klass = mono_class_get_module_class ();
5127 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
5129 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5130 if (mono_error_set_pending_exception (&error))
5133 mono_array_setref (res, 0, image_obj);
5135 for (i = 0; i < module_count; ++i)
5137 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5138 if (mono_error_set_pending_exception (&error))
5140 mono_array_setref (res, j, rm);
5144 for (i = 0; i < file_count; ++i, ++j) {
5145 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5146 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5147 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5148 if (mono_error_set_pending_exception (&error))
5150 mono_array_setref (res, j, rm);
5153 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5155 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5156 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5159 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5160 if (mono_error_set_pending_exception (&error))
5162 mono_array_setref (res, j, rm);
5169 ICALL_EXPORT MonoReflectionMethod*
5170 ves_icall_GetCurrentMethod (void)
5172 MonoReflectionMethod *res = NULL;
5175 MonoMethod *m = mono_method_get_last_managed ();
5178 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5182 while (m->is_inflated)
5183 m = ((MonoMethodInflated*)m)->declaring;
5185 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5186 mono_error_set_pending_exception (&error);
5192 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5195 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5198 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5199 //method is inflated, we should inflate it on the other class
5200 MonoGenericContext ctx;
5201 ctx.method_inst = inflated->context.method_inst;
5202 ctx.class_inst = inflated->context.class_inst;
5203 if (klass->generic_class)
5204 ctx.class_inst = klass->generic_class->context.class_inst;
5205 else if (klass->generic_container)
5206 ctx.class_inst = klass->generic_container->context.class_inst;
5207 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5208 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5212 mono_class_setup_methods (method->klass);
5213 if (mono_class_has_failure (method->klass))
5215 for (i = 0; i < method->klass->method.count; ++i) {
5216 if (method->klass->methods [i] == method) {
5221 mono_class_setup_methods (klass);
5222 if (mono_class_has_failure (klass))
5224 g_assert (offset >= 0 && offset < klass->method.count);
5225 return klass->methods [offset];
5228 ICALL_EXPORT MonoReflectionMethod*
5229 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5231 MonoReflectionMethod *res = NULL;
5235 klass = mono_class_from_mono_type (type);
5236 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5238 if (method->klass != klass) {
5239 method = mono_method_get_equivalent_method (method, klass);
5244 klass = method->klass;
5245 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5246 mono_error_set_pending_exception (&error);
5250 ICALL_EXPORT MonoReflectionMethodBody*
5251 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5254 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5255 mono_error_set_pending_exception (&error);
5259 ICALL_EXPORT MonoReflectionAssembly*
5260 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5263 MonoReflectionAssembly *result;
5264 MonoMethod *dest = NULL;
5266 mono_stack_walk_no_il (get_executing, &dest);
5268 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5270 mono_error_set_pending_exception (&error);
5275 ICALL_EXPORT MonoReflectionAssembly*
5276 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5279 MonoReflectionAssembly *result;
5280 MonoDomain* domain = mono_domain_get ();
5282 if (!domain->entry_assembly)
5285 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5287 mono_error_set_pending_exception (&error);
5291 ICALL_EXPORT MonoReflectionAssembly*
5292 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5297 MonoReflectionAssembly *result;
5300 mono_stack_walk_no_il (get_executing, &dest);
5302 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5306 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5309 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5311 mono_error_set_pending_exception (&error);
5315 ICALL_EXPORT MonoString *
5316 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5317 gboolean assembly_qualified)
5319 MonoDomain *domain = mono_object_domain (object);
5320 MonoTypeNameFormat format;
5325 format = assembly_qualified ?
5326 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5327 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5329 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5331 name = mono_type_get_name_full (object->type, format);
5335 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5340 res = mono_string_new (domain, name);
5347 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5350 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5352 mono_class_init_checked (klass, &error);
5353 mono_error_set_pending_exception (&error);
5354 return mono_security_core_clr_class_level (klass);
5358 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5360 MonoClassField *field = rfield->field;
5361 return mono_security_core_clr_field_level (field, TRUE);
5365 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5367 MonoMethod *method = rfield->method;
5368 return mono_security_core_clr_method_level (method, TRUE);
5372 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)
5374 static MonoMethod *create_culture = NULL;
5378 const char *pkey_ptr;
5380 MonoBoolean assembly_ref = 0;
5382 mono_error_init (error);
5384 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5385 aname->major = name->major;
5386 aname->minor = name->minor;
5387 aname->build = name->build;
5388 aname->flags = name->flags;
5389 aname->revision = name->revision;
5390 aname->hashalg = name->hash_alg;
5391 aname->versioncompat = 1; /* SameMachine (default) */
5392 aname->processor_architecture = name->arch;
5394 if (by_default_version) {
5395 MonoObject *version;
5397 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5398 return_if_nok (error);
5400 MONO_OBJECT_SETREF (aname, version, version);
5404 if (absolute != NULL && *absolute != '\0') {
5405 const gchar *prepend = "file://";
5408 codebase = g_strdup (absolute);
5413 for (i = strlen (codebase) - 1; i >= 0; i--)
5414 if (codebase [i] == '\\')
5417 if (*codebase == '/' && *(codebase + 1) == '/') {
5420 prepend = "file:///";
5424 result = g_strconcat (prepend, codebase, NULL);
5430 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5434 if (!create_culture) {
5435 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5436 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5437 g_assert (create_culture);
5438 mono_method_desc_free (desc);
5441 if (name->culture) {
5442 args [0] = mono_string_new (domain, name->culture);
5443 args [1] = &assembly_ref;
5445 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5446 return_if_nok (error);
5448 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5451 if (name->public_key) {
5452 pkey_ptr = (char*)name->public_key;
5453 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5455 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5456 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5457 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5458 } else if (default_publickey) {
5459 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5460 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5463 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5464 if (name->public_key_token [0]) {
5468 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5469 p = mono_array_addr (aname->keyToken, char, 0);
5471 for (i = 0, j = 0; i < 8; i++) {
5472 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5473 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5476 } else if (default_token) {
5477 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5481 ICALL_EXPORT MonoString *
5482 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5484 MonoDomain *domain = mono_object_domain (assembly);
5485 MonoAssembly *mass = assembly->assembly;
5489 name = mono_stringify_assembly_name (&mass->aname);
5490 res = mono_string_new (domain, name);
5497 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5501 MonoAssembly *mass = assembly->assembly;
5503 if (g_path_is_absolute (mass->image->name)) {
5504 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5505 mono_error_set_pending_exception (&error);
5508 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5510 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5511 mono_error_set_pending_exception (&error);
5517 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5521 MonoImageOpenStatus status = MONO_IMAGE_OK;
5524 MonoAssemblyName name;
5527 filename = mono_string_to_utf8 (fname);
5529 dirname = g_path_get_dirname (filename);
5530 replace_shadow_path (mono_domain_get (), dirname, &filename);
5533 image = mono_image_open (filename, &status);
5539 if (status == MONO_IMAGE_IMAGE_INVALID)
5540 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5542 exc = mono_get_exception_file_not_found2 (NULL, fname);
5543 mono_set_pending_exception (exc);
5547 res = mono_assembly_fill_assembly_name (image, &name);
5549 mono_image_close (image);
5551 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5555 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5556 mono_error_set_pending_exception (&error);
5558 mono_image_close (image);
5562 ICALL_EXPORT MonoBoolean
5563 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5564 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5566 MonoBoolean result = FALSE;
5567 MonoDeclSecurityEntry entry;
5569 /* SecurityAction.RequestMinimum */
5570 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5571 *minimum = entry.blob;
5572 *minLength = entry.size;
5575 /* SecurityAction.RequestOptional */
5576 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5577 *optional = entry.blob;
5578 *optLength = entry.size;
5581 /* SecurityAction.RequestRefuse */
5582 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5583 *refused = entry.blob;
5584 *refLength = entry.size;
5592 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5594 guint32 attrs, visibility;
5596 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5597 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5598 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5601 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5607 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5609 MonoReflectionType *rt;
5612 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5615 mono_error_init (error);
5617 /* we start the count from 1 because we skip the special type <Module> */
5620 for (i = 1; i < tdef->rows; ++i) {
5621 if (mono_module_type_is_visible (tdef, image, i + 1))
5625 count = tdef->rows - 1;
5627 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5628 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5630 for (i = 1; i < tdef->rows; ++i) {
5631 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5632 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5635 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5636 return_val_if_nok (error, NULL);
5638 mono_array_setref (res, count, rt);
5640 MonoException *ex = mono_error_convert_to_exception (error);
5641 mono_array_setref (*exceptions, count, ex);
5650 ICALL_EXPORT MonoArray*
5651 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5654 MonoArray *res = NULL;
5655 MonoArray *exceptions = NULL;
5656 MonoImage *image = NULL;
5657 MonoTableInfo *table = NULL;
5660 int i, len, ex_count;
5662 domain = mono_object_domain (assembly);
5664 g_assert (!assembly_is_dynamic (assembly->assembly));
5665 image = assembly->assembly->image;
5666 table = &image->tables [MONO_TABLE_FILE];
5667 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5668 if (mono_error_set_pending_exception (&error))
5671 /* Append data from all modules in the assembly */
5672 for (i = 0; i < table->rows; ++i) {
5673 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5674 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5679 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5680 if (mono_error_set_pending_exception (&error))
5684 /* Append the new types to the end of the array */
5685 if (mono_array_length (res2) > 0) {
5687 MonoArray *res3, *ex3;
5689 len1 = mono_array_length (res);
5690 len2 = mono_array_length (res2);
5692 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5693 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5694 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5697 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5698 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5699 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5706 /* the ReflectionTypeLoadException must have all the types (Types property),
5707 * NULL replacing types which throws an exception. The LoaderException must
5708 * contain all exceptions for NULL items.
5711 len = mono_array_length (res);
5714 for (i = 0; i < len; i++) {
5715 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5719 klass = mono_type_get_class (t->type);
5720 if ((klass != NULL) && mono_class_has_failure (klass)) {
5721 /* keep the class in the list */
5722 list = g_list_append (list, klass);
5723 /* and replace Type with NULL */
5724 mono_array_setref (res, i, NULL);
5731 if (list || ex_count) {
5733 MonoException *exc = NULL;
5734 MonoArray *exl = NULL;
5735 int j, length = g_list_length (list) + ex_count;
5737 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5738 /* Types for which mono_class_get_checked () succeeded */
5739 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5740 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5741 mono_array_setref (exl, i, exc);
5743 /* Types for which it don't */
5744 for (j = 0; j < mono_array_length (exceptions); ++j) {
5745 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5747 g_assert (i < length);
5748 mono_array_setref (exl, i, exc);
5755 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5756 if (!is_ok (&error)) {
5757 mono_error_set_pending_exception (&error);
5760 mono_set_pending_exception (exc);
5767 ICALL_EXPORT gboolean
5768 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5771 MonoAssemblyName aname;
5772 MonoDomain *domain = mono_object_domain (name);
5774 gboolean is_version_defined;
5775 gboolean is_token_defined;
5777 aname.public_key = NULL;
5778 val = mono_string_to_utf8 (assname);
5779 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5780 g_free ((guint8*) aname.public_key);
5785 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5786 mono_error_set_pending_exception (&error);
5788 mono_assembly_name_free (&aname);
5789 g_free ((guint8*) aname.public_key);
5795 ICALL_EXPORT MonoReflectionType*
5796 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5799 MonoReflectionType *ret;
5800 MonoDomain *domain = mono_object_domain (module);
5803 g_assert (module->image);
5805 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5806 /* These images do not have a global type */
5809 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5810 if (!mono_error_ok (&error)) {
5811 mono_error_set_pending_exception (&error);
5815 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5816 if (!mono_error_ok (&error)) {
5817 mono_error_set_pending_exception (&error);
5825 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5827 /*if (module->image)
5828 mono_image_close (module->image);*/
5831 ICALL_EXPORT MonoString*
5832 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5834 MonoDomain *domain = mono_object_domain (module);
5836 g_assert (module->image);
5837 return mono_string_new (domain, module->image->guid);
5840 ICALL_EXPORT gpointer
5841 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5844 if (module->image && module->image->is_module_handle)
5845 return module->image->raw_data;
5848 return (gpointer) (-1);
5852 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5854 if (image_is_dynamic (image)) {
5855 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5856 *pe_kind = dyn->pe_kind;
5857 *machine = dyn->machine;
5860 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5861 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5866 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5868 return (image->md_version_major << 16) | (image->md_version_minor);
5871 ICALL_EXPORT MonoArray*
5872 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5875 MonoArray *exceptions;
5879 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5883 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5884 if (mono_error_set_pending_exception (&error))
5887 for (i = 0; i < mono_array_length (exceptions); ++i) {
5888 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5890 mono_set_pending_exception (ex);
5899 mono_memberref_is_method (MonoImage *image, guint32 token)
5901 if (!image_is_dynamic (image)) {
5902 guint32 cols [MONO_MEMBERREF_SIZE];
5904 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5905 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5906 mono_metadata_decode_blob_size (sig, &sig);
5907 return (*sig != 0x6);
5910 MonoClass *handle_class;
5912 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5913 mono_error_cleanup (&error); /* just probing, ignore error */
5917 return mono_defaults.methodhandle_class == handle_class;
5922 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5925 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5926 mono_array_addr (type_args, MonoType*, 0));
5928 context->class_inst = NULL;
5930 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5931 mono_array_addr (method_args, MonoType*, 0));
5933 context->method_inst = NULL;
5936 ICALL_EXPORT MonoType*
5937 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5940 int table = mono_metadata_token_table (token);
5941 int index = mono_metadata_token_index (token);
5942 MonoGenericContext context;
5945 *resolve_error = ResolveTokenError_Other;
5947 /* Validate token */
5948 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5949 (table != MONO_TABLE_TYPESPEC)) {
5950 *resolve_error = ResolveTokenError_BadTable;
5954 if (image_is_dynamic (image)) {
5955 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5956 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5957 mono_error_cleanup (&error);
5958 return klass ? &klass->byval_arg : NULL;
5961 init_generic_context_from_args (&context, type_args, method_args);
5962 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5963 mono_error_cleanup (&error);
5964 return klass ? &klass->byval_arg : NULL;
5967 if ((index <= 0) || (index > image->tables [table].rows)) {
5968 *resolve_error = ResolveTokenError_OutOfRange;
5972 init_generic_context_from_args (&context, type_args, method_args);
5973 klass = mono_class_get_checked (image, token, &error);
5975 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5976 if (!mono_error_ok (&error)) {
5977 mono_error_set_pending_exception (&error);
5982 return &klass->byval_arg;
5987 ICALL_EXPORT MonoMethod*
5988 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5991 int table = mono_metadata_token_table (token);
5992 int index = mono_metadata_token_index (token);
5993 MonoGenericContext context;
5996 *resolve_error = ResolveTokenError_Other;
5998 /* Validate token */
5999 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
6000 (table != MONO_TABLE_MEMBERREF)) {
6001 *resolve_error = ResolveTokenError_BadTable;
6005 if (image_is_dynamic (image)) {
6006 if (table == MONO_TABLE_METHOD) {
6007 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6008 mono_error_cleanup (&error);
6012 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
6013 *resolve_error = ResolveTokenError_BadTable;
6017 init_generic_context_from_args (&context, type_args, method_args);
6018 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6019 mono_error_cleanup (&error);
6023 if ((index <= 0) || (index > image->tables [table].rows)) {
6024 *resolve_error = ResolveTokenError_OutOfRange;
6027 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6028 *resolve_error = ResolveTokenError_BadTable;
6032 init_generic_context_from_args (&context, type_args, method_args);
6033 method = mono_get_method_checked (image, token, NULL, &context, &error);
6034 mono_error_set_pending_exception (&error);
6039 ICALL_EXPORT MonoString*
6040 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6043 int index = mono_metadata_token_index (token);
6045 *resolve_error = ResolveTokenError_Other;
6047 /* Validate token */
6048 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6049 *resolve_error = ResolveTokenError_BadTable;
6053 if (image_is_dynamic (image)) {
6054 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6055 mono_error_cleanup (&error);
6059 if ((index <= 0) || (index >= image->heap_us.size)) {
6060 *resolve_error = ResolveTokenError_OutOfRange;
6064 /* FIXME: What to do if the index points into the middle of a string ? */
6066 return mono_ldstr (mono_domain_get (), image, index);
6069 ICALL_EXPORT MonoClassField*
6070 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6074 int table = mono_metadata_token_table (token);
6075 int index = mono_metadata_token_index (token);
6076 MonoGenericContext context;
6077 MonoClassField *field;
6079 *resolve_error = ResolveTokenError_Other;
6081 /* Validate token */
6082 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6083 *resolve_error = ResolveTokenError_BadTable;
6087 if (image_is_dynamic (image)) {
6088 if (table == MONO_TABLE_FIELD) {
6089 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6090 mono_error_cleanup (&error);
6094 if (mono_memberref_is_method (image, token)) {
6095 *resolve_error = ResolveTokenError_BadTable;
6099 init_generic_context_from_args (&context, type_args, method_args);
6100 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6101 mono_error_cleanup (&error);
6105 if ((index <= 0) || (index > image->tables [table].rows)) {
6106 *resolve_error = ResolveTokenError_OutOfRange;
6109 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6110 *resolve_error = ResolveTokenError_BadTable;
6114 init_generic_context_from_args (&context, type_args, method_args);
6115 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6116 mono_error_set_pending_exception (&error);
6122 ICALL_EXPORT MonoObject*
6123 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6127 int table = mono_metadata_token_table (token);
6129 *error = ResolveTokenError_Other;
6132 case MONO_TABLE_TYPEDEF:
6133 case MONO_TABLE_TYPEREF:
6134 case MONO_TABLE_TYPESPEC: {
6135 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6137 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6138 mono_error_set_pending_exception (&merror);
6145 case MONO_TABLE_METHOD:
6146 case MONO_TABLE_METHODSPEC: {
6147 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6149 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6150 mono_error_set_pending_exception (&merror);
6156 case MONO_TABLE_FIELD: {
6157 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6159 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6160 mono_error_set_pending_exception (&merror);
6166 case MONO_TABLE_MEMBERREF:
6167 if (mono_memberref_is_method (image, token)) {
6168 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6170 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6171 mono_error_set_pending_exception (&merror);
6178 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6180 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6181 mono_error_set_pending_exception (&merror);
6190 *error = ResolveTokenError_BadTable;
6196 ICALL_EXPORT MonoArray*
6197 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
6199 int table = mono_metadata_token_table (token);
6200 int idx = mono_metadata_token_index (token);
6201 MonoTableInfo *tables = image->tables;
6206 *error = ResolveTokenError_OutOfRange;
6208 /* FIXME: Support other tables ? */
6209 if (table != MONO_TABLE_STANDALONESIG)
6212 if (image_is_dynamic (image))
6215 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6218 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6220 ptr = mono_metadata_blob_heap (image, sig);
6221 len = mono_metadata_decode_blob_size (ptr, &ptr);
6223 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
6224 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6228 ICALL_EXPORT MonoReflectionType*
6229 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6232 MonoReflectionType *ret;
6234 int isbyref = 0, rank;
6235 char *str = mono_string_to_utf8 (smodifiers);
6238 klass = mono_class_from_mono_type (tb->type.type);
6240 /* logic taken from mono_reflection_parse_type(): keep in sync */
6244 if (isbyref) { /* only one level allowed by the spec */
6253 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6254 mono_error_set_pending_exception (&error);
6258 klass = mono_ptr_class_get (&klass->byval_arg);
6259 mono_class_init (klass);
6270 else if (*p != '*') { /* '*' means unknown lower bound */
6281 klass = mono_array_class_get (klass, rank);
6282 mono_class_init (klass);
6291 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6292 mono_error_set_pending_exception (&error);
6297 ICALL_EXPORT MonoBoolean
6298 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6304 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6310 check_for_invalid_type (MonoClass *klass, MonoError *error)
6315 mono_error_init (error);
6317 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6320 name = mono_type_get_full_name (klass);
6321 str = mono_string_new (mono_domain_get (), name);
6323 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6326 ICALL_EXPORT MonoReflectionType *
6327 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6330 MonoReflectionType *ret;
6331 MonoClass *klass, *aklass;
6333 klass = mono_class_from_mono_type (type->type);
6334 check_for_invalid_type (klass, &error);
6335 mono_error_set_pending_exception (&error);
6337 if (rank == 0) //single dimentional array
6338 aklass = mono_array_class_get (klass, 1);
6340 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6342 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6343 mono_error_set_pending_exception (&error);
6348 ICALL_EXPORT MonoReflectionType *
6349 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6352 MonoReflectionType *ret;
6355 klass = mono_class_from_mono_type (type->type);
6356 mono_class_init_checked (klass, &error);
6357 if (mono_error_set_pending_exception (&error))
6360 check_for_invalid_type (klass, &error);
6361 if (mono_error_set_pending_exception (&error))
6364 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6365 mono_error_set_pending_exception (&error);
6370 ICALL_EXPORT MonoReflectionType *
6371 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6374 MonoReflectionType *ret;
6375 MonoClass *klass, *pklass;
6377 klass = mono_class_from_mono_type (type->type);
6378 mono_class_init_checked (klass, &error);
6379 if (mono_error_set_pending_exception (&error))
6381 check_for_invalid_type (klass, &error);
6382 if (mono_error_set_pending_exception (&error))
6385 pklass = mono_ptr_class_get (type->type);
6387 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6388 mono_error_set_pending_exception (&error);
6393 ICALL_EXPORT MonoObject *
6394 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6395 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6398 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6399 MonoObject *delegate;
6401 MonoMethod *method = info->method;
6403 mono_class_init_checked (delegate_class, &error);
6404 if (mono_error_set_pending_exception (&error))
6407 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6408 /* FIXME improve this exception message */
6409 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6411 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6412 mono_error_set_pending_exception (&error);
6416 if (mono_security_core_clr_enabled ()) {
6417 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6418 if (throwOnBindFailure)
6419 mono_error_set_pending_exception (&error);
6421 mono_error_cleanup (&error);
6426 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6427 if (mono_error_set_pending_exception (&error))
6430 if (method_is_dynamic (method)) {
6431 /* Creating a trampoline would leak memory */
6432 func = mono_compile_method (method);
6434 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6435 method = mono_object_get_virtual_method (target, method);
6436 func = mono_create_ftnptr (mono_domain_get (),
6437 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6440 mono_delegate_ctor_with_method (delegate, target, func, method);
6445 ICALL_EXPORT MonoMulticastDelegate *
6446 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6449 MonoMulticastDelegate *ret;
6451 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6453 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6454 if (mono_error_set_pending_exception (&error))
6457 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6462 ICALL_EXPORT MonoReflectionMethod*
6463 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6465 MonoReflectionMethod *ret = NULL;
6467 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6468 mono_error_set_pending_exception (&error);
6474 static inline gint32
6475 mono_array_get_byte_length (MonoArray *array)
6481 klass = array->obj.vtable->klass;
6483 if (array->bounds == NULL)
6484 length = array->max_length;
6487 for (i = 0; i < klass->rank; ++ i)
6488 length *= array->bounds [i].length;
6491 switch (klass->element_class->byval_arg.type) {
6494 case MONO_TYPE_BOOLEAN:
6498 case MONO_TYPE_CHAR:
6506 return length * sizeof (gpointer);
6517 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6519 return mono_array_get_byte_length (array);
6523 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6525 return mono_array_get (array, gint8, idx);
6529 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6531 mono_array_set (array, gint8, idx, value);
6534 ICALL_EXPORT MonoBoolean
6535 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6537 guint8 *src_buf, *dest_buf;
6540 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6544 g_assert (count >= 0);
6546 /* This is called directly from the class libraries without going through the managed wrapper */
6547 MONO_CHECK_ARG_NULL (src, FALSE);
6548 MONO_CHECK_ARG_NULL (dest, FALSE);
6550 /* watch out for integer overflow */
6551 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6554 src_buf = (guint8 *)src->vector + src_offset;
6555 dest_buf = (guint8 *)dest->vector + dest_offset;
6558 memcpy (dest_buf, src_buf, count);
6560 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6565 #ifndef DISABLE_REMOTING
6566 ICALL_EXPORT MonoObject *
6567 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6570 MonoDomain *domain = mono_object_domain (this_obj);
6572 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6573 MonoTransparentProxy *tp;
6577 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6578 if (mono_error_set_pending_exception (&error))
6581 tp = (MonoTransparentProxy*) res;
6583 MONO_OBJECT_SETREF (tp, rp, rp);
6584 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6585 klass = mono_class_from_mono_type (type);
6587 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6588 mono_class_setup_vtable (klass);
6589 if (mono_class_has_failure (klass)) {
6590 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6594 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6595 if (!is_ok (&error)) {
6596 mono_error_set_pending_exception (&error);
6599 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6600 if (!is_ok (&error)) {
6601 mono_error_set_pending_exception (&error);
6605 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6609 ICALL_EXPORT MonoReflectionType *
6610 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6613 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6614 mono_error_set_pending_exception (&error);
6620 /* System.Environment */
6623 ves_icall_System_Environment_get_UserName (void)
6625 /* using glib is more portable */
6626 return mono_string_new (mono_domain_get (), g_get_user_name ());
6630 ICALL_EXPORT MonoString *
6631 ves_icall_System_Environment_get_MachineName (void)
6633 #if defined (HOST_WIN32)
6638 len = MAX_COMPUTERNAME_LENGTH + 1;
6639 buf = g_new (gunichar2, len);
6642 if (GetComputerName (buf, (PDWORD) &len)) {
6644 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6645 mono_error_set_pending_exception (&error);
6650 #elif !defined(DISABLE_SOCKETS)
6654 #if defined _SC_HOST_NAME_MAX
6655 n = sysconf (_SC_HOST_NAME_MAX);
6659 buf = g_malloc (n+1);
6661 if (gethostname (buf, n) == 0){
6663 result = mono_string_new (mono_domain_get (), buf);
6670 return mono_string_new (mono_domain_get (), "mono");
6675 ves_icall_System_Environment_get_Platform (void)
6677 #if defined (TARGET_WIN32)
6680 #elif defined(__MACH__)
6683 // Notice that the value is hidden from user code, and only exposed
6684 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6685 // define and making assumptions based on Unix/128/4 values before there
6686 // was a MacOS define. Lots of code would assume that not-Unix meant
6687 // Windows, but in this case, it would be OSX.
6696 ICALL_EXPORT MonoString *
6697 ves_icall_System_Environment_get_NewLine (void)
6699 #if defined (HOST_WIN32)
6700 return mono_string_new (mono_domain_get (), "\r\n");
6702 return mono_string_new (mono_domain_get (), "\n");
6706 ICALL_EXPORT MonoBoolean
6707 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6709 #if SIZEOF_VOID_P == 8
6713 gboolean isWow64Process = FALSE;
6714 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6715 return (MonoBoolean)isWow64Process;
6717 #elif defined(HAVE_SYS_UTSNAME_H)
6718 struct utsname name;
6720 if (uname (&name) >= 0) {
6721 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6728 ICALL_EXPORT MonoString *
6729 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6737 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6738 value = g_getenv (utf8_name);
6745 return mono_string_new (mono_domain_get (), value);
6749 * There is no standard way to get at environ.
6752 #ifndef __MINGW32_VERSION
6753 #if defined(__APPLE__)
6754 #if defined (TARGET_OSX)
6755 /* Apple defines this in crt_externs.h but doesn't provide that header for
6756 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6757 * in fact exist on all implementations (so far)
6759 gchar ***_NSGetEnviron(void);
6760 #define environ (*_NSGetEnviron())
6762 static char *mono_environ[1] = { NULL };
6763 #define environ mono_environ
6764 #endif /* defined (TARGET_OSX) */
6772 ICALL_EXPORT MonoArray *
6773 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6784 env_strings = GetEnvironmentStrings();
6787 env_string = env_strings;
6788 while (*env_string != '\0') {
6789 /* weird case that MS seems to skip */
6790 if (*env_string != '=')
6792 while (*env_string != '\0')
6798 domain = mono_domain_get ();
6799 names = mono_array_new (domain, mono_defaults.string_class, n);
6803 env_string = env_strings;
6804 while (*env_string != '\0') {
6805 /* weird case that MS seems to skip */
6806 if (*env_string != '=') {
6807 equal_str = wcschr(env_string, '=');
6808 g_assert(equal_str);
6810 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6811 if (mono_error_set_pending_exception (&error))
6814 mono_array_setref (names, n, str);
6817 while (*env_string != '\0')
6822 FreeEnvironmentStrings (env_strings);
6835 for (e = environ; *e != 0; ++ e)
6838 domain = mono_domain_get ();
6839 names = mono_array_new (domain, mono_defaults.string_class, n);
6842 for (e = environ; *e != 0; ++ e) {
6843 parts = g_strsplit (*e, "=", 2);
6845 str = mono_string_new (domain, *parts);
6846 mono_array_setref (names, n, str);
6859 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6861 #if !GLIB_CHECK_VERSION(2,4,0)
6862 #define g_setenv(a,b,c) setenv(a,b,c)
6863 #define g_unsetenv(a) unsetenv(a)
6867 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6870 gunichar2 *utf16_name, *utf16_value;
6872 gchar *utf8_name, *utf8_value;
6877 utf16_name = mono_string_to_utf16 (name);
6878 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6879 SetEnvironmentVariable (utf16_name, NULL);
6880 g_free (utf16_name);
6884 utf16_value = mono_string_to_utf16 (value);
6886 SetEnvironmentVariable (utf16_name, utf16_value);
6888 g_free (utf16_name);
6889 g_free (utf16_value);
6891 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6893 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6894 g_unsetenv (utf8_name);
6899 utf8_value = mono_string_to_utf8_checked (value, &error);
6900 if (!mono_error_ok (&error)) {
6902 mono_error_set_pending_exception (&error);
6905 g_setenv (utf8_name, utf8_value, TRUE);
6908 g_free (utf8_value);
6913 ves_icall_System_Environment_Exit (int result)
6915 mono_environment_exitcode_set (result);
6917 /* FIXME: There are some cleanup hangs that should be worked out, but
6918 * if the program is going to exit, everything will be cleaned up when
6919 * NaCl exits anyway.
6921 #ifndef __native_client__
6922 if (!mono_runtime_try_shutdown ())
6923 mono_thread_exit ();
6925 /* Suspend all managed threads since the runtime is going away */
6926 mono_thread_suspend_all_other_threads ();
6928 mono_runtime_quit ();
6931 /* we may need to do some cleanup here... */
6935 ICALL_EXPORT MonoString*
6936 ves_icall_System_Environment_GetGacPath (void)
6938 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6941 ICALL_EXPORT MonoString*
6942 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6944 #if defined (HOST_WIN32)
6945 #ifndef CSIDL_FLAG_CREATE
6946 #define CSIDL_FLAG_CREATE 0x8000
6949 WCHAR path [MAX_PATH];
6950 /* Create directory if no existing */
6951 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6956 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6957 mono_error_set_pending_exception (&error);
6961 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6963 return mono_string_new (mono_domain_get (), "");
6966 ICALL_EXPORT MonoArray *
6967 ves_icall_System_Environment_GetLogicalDrives (void)
6970 gunichar2 buf [256], *ptr, *dname;
6972 guint initial_size = 127, size = 128;
6975 MonoString *drivestr;
6976 MonoDomain *domain = mono_domain_get ();
6982 while (size > initial_size) {
6983 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6984 if (size > initial_size) {
6987 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6988 initial_size = size;
7002 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
7007 while (*u16) { u16++; len ++; }
7008 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7009 if (mono_error_set_pending_exception (&error))
7012 mono_array_setref (result, ndrives++, drivestr);
7022 ICALL_EXPORT MonoString *
7023 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7025 gunichar2 volume_name [MAX_PATH + 1];
7027 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7029 return mono_string_from_utf16 (volume_name);
7032 ICALL_EXPORT MonoString *
7033 ves_icall_System_Environment_InternalGetHome (void)
7035 return mono_string_new (mono_domain_get (), g_get_home_dir ());
7038 static const char *encodings [] = {
7040 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7041 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7042 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7044 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7045 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7046 "x_unicode_2_0_utf_7",
7048 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7049 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7051 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7054 "unicodefffe", "utf_16be",
7061 * Returns the internal codepage, if the value of "int_code_page" is
7062 * 1 at entry, and we can not compute a suitable code page number,
7063 * returns the code page as a string
7065 ICALL_EXPORT MonoString*
7066 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
7071 char *codepage = NULL;
7073 int want_name = *int_code_page;
7076 *int_code_page = -1;
7078 g_get_charset (&cset);
7079 c = codepage = strdup (cset);
7080 for (c = codepage; *c; c++){
7081 if (isascii (*c) && isalpha (*c))
7086 /* g_print ("charset: %s\n", cset); */
7088 /* handle some common aliases */
7091 for (i = 0; p != 0; ){
7094 p = encodings [++i];
7097 if (strcmp (p, codepage) == 0){
7098 *int_code_page = code;
7101 p = encodings [++i];
7104 if (strstr (codepage, "utf_8") != NULL)
7105 *int_code_page |= 0x10000000;
7108 if (want_name && *int_code_page == -1)
7109 return mono_string_new (mono_domain_get (), cset);
7114 ICALL_EXPORT MonoBoolean
7115 ves_icall_System_Environment_get_HasShutdownStarted (void)
7117 if (mono_runtime_is_shutting_down ())
7120 if (mono_domain_is_unloading (mono_domain_get ()))
7127 ves_icall_System_Environment_BroadcastSettingChange (void)
7130 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7135 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7141 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
7142 MonoReflectionMethod *method,
7143 MonoArray *out_args)
7145 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
7148 #ifndef DISABLE_REMOTING
7149 ICALL_EXPORT MonoBoolean
7150 ves_icall_IsTransparentProxy (MonoObject *proxy)
7155 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7161 ICALL_EXPORT MonoReflectionMethod *
7162 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7163 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7165 MonoReflectionMethod *ret = NULL;
7170 MonoMethod **vtable;
7171 MonoMethod *res = NULL;
7173 MONO_CHECK_ARG_NULL (rtype, NULL);
7174 MONO_CHECK_ARG_NULL (rmethod, NULL);
7176 method = rmethod->method;
7177 klass = mono_class_from_mono_type (rtype->type);
7178 mono_class_init_checked (klass, &error);
7179 if (mono_error_set_pending_exception (&error))
7182 if (MONO_CLASS_IS_INTERFACE (klass))
7185 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7188 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7189 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7195 mono_class_setup_vtable (klass);
7196 vtable = klass->vtable;
7198 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7199 gboolean variance_used = FALSE;
7200 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7201 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7203 res = vtable [offs + method->slot];
7205 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7208 if (method->slot != -1)
7209 res = vtable [method->slot];
7215 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7216 mono_error_set_pending_exception (&error);
7221 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7227 klass = mono_class_from_mono_type (type->type);
7228 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7229 if (!is_ok (&error)) {
7230 mono_error_set_pending_exception (&error);
7234 mono_vtable_set_is_remote (vtable, enable);
7237 #else /* DISABLE_REMOTING */
7240 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7242 g_assert_not_reached ();
7247 ICALL_EXPORT MonoObject *
7248 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7255 domain = mono_object_domain (type);
7256 klass = mono_class_from_mono_type (type->type);
7257 mono_class_init_checked (klass, &error);
7258 if (mono_error_set_pending_exception (&error))
7261 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7262 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7266 if (klass->rank >= 1) {
7267 g_assert (klass->rank == 1);
7268 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7270 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7271 if (!is_ok (&error)) {
7272 mono_error_set_pending_exception (&error);
7275 /* Bypass remoting object creation check */
7276 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7277 mono_error_set_pending_exception (&error);
7283 ICALL_EXPORT MonoString *
7284 ves_icall_System_IO_get_temp_path (void)
7286 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7289 #ifndef PLATFORM_NO_DRIVEINFO
7290 ICALL_EXPORT MonoBoolean
7291 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7292 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7296 ULARGE_INTEGER wapi_free_bytes_avail;
7297 ULARGE_INTEGER wapi_total_number_of_bytes;
7298 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7300 *error = ERROR_SUCCESS;
7301 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7302 &wapi_total_number_of_free_bytes);
7305 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7306 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7307 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7309 *free_bytes_avail = 0;
7310 *total_number_of_bytes = 0;
7311 *total_number_of_free_bytes = 0;
7312 *error = GetLastError ();
7318 ICALL_EXPORT guint32
7319 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7321 return GetDriveType (mono_string_chars (root_path_name));
7325 ICALL_EXPORT gpointer
7326 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7328 return mono_compile_method (method);
7331 ICALL_EXPORT MonoString *
7332 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7337 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7339 #if defined (HOST_WIN32)
7340 /* Avoid mixing '/' and '\\' */
7343 for (i = strlen (path) - 1; i >= 0; i--)
7344 if (path [i] == '/')
7348 mcpath = mono_string_new (mono_domain_get (), path);
7355 get_bundled_app_config (void)
7357 const gchar *app_config;
7360 gchar *config_file_name, *config_file_path;
7361 gsize len, config_file_path_length, config_ext_length;
7364 domain = mono_domain_get ();
7365 file = domain->setup->configuration_file;
7366 if (!file || file->length == 0)
7369 // Retrieve config file and remove the extension
7370 config_file_name = mono_string_to_utf8 (file);
7371 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7372 if (!config_file_path)
7373 config_file_path = config_file_name;
7375 config_file_path_length = strlen (config_file_path);
7376 config_ext_length = strlen (".config");
7377 if (config_file_path_length <= config_ext_length)
7380 len = config_file_path_length - config_ext_length;
7381 module = (gchar *)g_malloc0 (len + 1);
7382 memcpy (module, config_file_path, len);
7383 // Get the config file from the module name
7384 app_config = mono_config_string_for_assembly_file (module);
7387 if (config_file_name != config_file_path)
7388 g_free (config_file_name);
7389 g_free (config_file_path);
7394 return mono_string_new (mono_domain_get (), app_config);
7398 get_bundled_machine_config (void)
7400 const gchar *machine_config;
7402 machine_config = mono_get_machine_config ();
7404 if (!machine_config)
7407 return mono_string_new (mono_domain_get (), machine_config);
7410 ICALL_EXPORT MonoString *
7411 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7416 path = g_path_get_dirname (mono_get_config_dir ());
7418 #if defined (HOST_WIN32)
7419 /* Avoid mixing '/' and '\\' */
7422 for (i = strlen (path) - 1; i >= 0; i--)
7423 if (path [i] == '/')
7427 ipath = mono_string_new (mono_domain_get (), path);
7433 ICALL_EXPORT gboolean
7434 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7436 MonoPEResourceDataEntry *entry;
7439 if (!assembly || !result || !size)
7444 image = assembly->assembly->image;
7445 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7449 *result = mono_image_rva_map (image, entry->rde_data_offset);
7454 *size = entry->rde_size;
7459 ICALL_EXPORT MonoBoolean
7460 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7462 return mono_is_debugger_attached ();
7465 ICALL_EXPORT MonoBoolean
7466 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7468 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7469 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7475 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7477 if (mono_get_runtime_callbacks ()->debug_log)
7478 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7482 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7484 #if defined (HOST_WIN32)
7485 OutputDebugString (mono_string_chars (message));
7487 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7491 /* Only used for value types */
7492 ICALL_EXPORT MonoObject *
7493 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7500 domain = mono_object_domain (type);
7501 klass = mono_class_from_mono_type (type->type);
7502 mono_class_init_checked (klass, &error);
7503 if (mono_error_set_pending_exception (&error))
7506 if (mono_class_is_nullable (klass))
7507 /* No arguments -> null */
7510 result = mono_object_new_checked (domain, klass, &error);
7511 mono_error_set_pending_exception (&error);
7515 ICALL_EXPORT MonoReflectionMethod *
7516 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7518 MonoReflectionMethod *ret = NULL;
7521 MonoClass *klass, *parent;
7522 MonoGenericContext *generic_inst = NULL;
7523 MonoMethod *method = m->method;
7524 MonoMethod *result = NULL;
7527 if (method->klass == NULL)
7530 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7531 MONO_CLASS_IS_INTERFACE (method->klass) ||
7532 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7535 slot = mono_method_get_vtable_slot (method);
7539 klass = method->klass;
7540 if (klass->generic_class) {
7541 generic_inst = mono_class_get_context (klass);
7542 klass = klass->generic_class->container_class;
7546 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7547 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7548 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7549 or klass is the generic container class and generic_inst is the instantiation.
7551 when we go to the parent, if the parent is an open constructed type, we need to
7552 replace the type parameters by the definitions from the generic_inst, and then take it
7553 apart again into the klass and the generic_inst.
7555 For cases like this:
7556 class C<T> : B<T, int> {
7557 public override void Foo () { ... }
7559 class B<U,V> : A<HashMap<U,V>> {
7560 public override void Foo () { ... }
7563 public virtual void Foo () { ... }
7566 if at each iteration the parent isn't open, we can skip inflating it. if at some
7567 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7570 MonoGenericContext *parent_inst = NULL;
7571 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7572 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7573 if (!mono_error_ok (&error)) {
7574 mono_error_set_pending_exception (&error);
7578 if (parent->generic_class) {
7579 parent_inst = mono_class_get_context (parent);
7580 parent = parent->generic_class->container_class;
7583 mono_class_setup_vtable (parent);
7584 if (parent->vtable_size <= slot)
7587 generic_inst = parent_inst;
7590 klass = klass->parent;
7593 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7594 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7595 if (!mono_error_ok (&error)) {
7596 mono_error_set_pending_exception (&error);
7600 generic_inst = NULL;
7602 if (klass->generic_class) {
7603 generic_inst = mono_class_get_context (klass);
7604 klass = klass->generic_class->container_class;
7610 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7611 if (!mono_error_ok (&error)) {
7612 mono_error_set_pending_exception (&error);
7617 if (klass == method->klass)
7620 /*This is possible if definition == FALSE.
7621 * Do it here to be really sure we don't read invalid memory.
7623 if (slot >= klass->vtable_size)
7626 mono_class_setup_vtable (klass);
7628 result = klass->vtable [slot];
7629 if (result == NULL) {
7630 /* It is an abstract method */
7631 gpointer iter = NULL;
7632 while ((result = mono_class_get_methods (klass, &iter)))
7633 if (result->slot == slot)
7640 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7641 mono_error_set_pending_exception (&error);
7645 ICALL_EXPORT MonoString*
7646 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7648 MonoMethod *method = m->method;
7650 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7655 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7657 iter->sig = *(MonoMethodSignature**)argsp;
7659 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7660 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7663 /* FIXME: it's not documented what start is exactly... */
7667 iter->args = argsp + sizeof (gpointer);
7669 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7671 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7674 ICALL_EXPORT MonoTypedRef
7675 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7677 guint32 i, arg_size;
7681 i = iter->sig->sentinelpos + iter->next_arg;
7683 g_assert (i < iter->sig->param_count);
7685 res.type = iter->sig->params [i];
7686 res.klass = mono_class_from_mono_type (res.type);
7687 arg_size = mono_type_stack_size (res.type, &align);
7688 #if defined(__arm__) || defined(__mips__)
7689 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7691 res.value = iter->args;
7692 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7693 /* Values are stored as 8 byte register sized objects, but 'value'
7694 * is dereferenced as a pointer in other routines.
7696 res.value = (char*)res.value + 4;
7698 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7699 if (arg_size <= sizeof (gpointer)) {
7701 int padding = arg_size - mono_type_size (res.type, &dummy);
7702 res.value = (guint8*)res.value + padding;
7705 iter->args = (char*)iter->args + arg_size;
7708 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7713 ICALL_EXPORT MonoTypedRef
7714 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7716 guint32 i, arg_size;
7720 i = iter->sig->sentinelpos + iter->next_arg;
7722 g_assert (i < iter->sig->param_count);
7724 while (i < iter->sig->param_count) {
7725 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7727 res.type = iter->sig->params [i];
7728 res.klass = mono_class_from_mono_type (res.type);
7729 /* FIXME: endianess issue... */
7730 arg_size = mono_type_stack_size (res.type, &align);
7731 #if defined(__arm__) || defined(__mips__)
7732 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7734 res.value = iter->args;
7735 iter->args = (char*)iter->args + arg_size;
7737 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7740 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7748 ICALL_EXPORT MonoType*
7749 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7753 i = iter->sig->sentinelpos + iter->next_arg;
7755 g_assert (i < iter->sig->param_count);
7757 return iter->sig->params [i];
7760 ICALL_EXPORT MonoObject*
7761 mono_TypedReference_ToObject (MonoTypedRef* tref)
7764 MonoObject *result = NULL;
7765 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7766 MonoObject** objp = (MonoObject **)tref->value;
7770 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7771 mono_error_set_pending_exception (&error);
7775 ICALL_EXPORT MonoTypedRef
7776 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7779 MonoReflectionField *f;
7781 MonoType *ftype = NULL;
7785 memset (&res, 0, sizeof (res));
7788 g_assert (mono_array_length (fields) > 0);
7790 klass = target->vtable->klass;
7792 for (i = 0; i < mono_array_length (fields); ++i) {
7793 f = mono_array_get (fields, MonoReflectionField*, i);
7795 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7798 if (f->field->parent != klass) {
7799 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7803 p = (guint8*)target + f->field->offset;
7805 p += f->field->offset - sizeof (MonoObject);
7806 klass = mono_class_from_mono_type (f->field->type);
7807 ftype = f->field->type;
7811 res.klass = mono_class_from_mono_type (ftype);
7818 prelink_method (MonoMethod *method, MonoError *error)
7820 const char *exc_class, *exc_arg;
7822 mono_error_init (error);
7823 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7825 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7827 mono_error_set_exception_instance (error,
7828 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7831 /* create the wrapper, too? */
7835 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7839 prelink_method (method->method, &error);
7840 mono_error_set_pending_exception (&error);
7844 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7847 MonoClass *klass = mono_class_from_mono_type (type->type);
7849 gpointer iter = NULL;
7851 mono_class_init_checked (klass, &error);
7852 if (mono_error_set_pending_exception (&error))
7855 while ((m = mono_class_get_methods (klass, &iter))) {
7856 prelink_method (m, &error);
7857 if (mono_error_set_pending_exception (&error))
7862 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7864 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7865 gint32 const **exponents,
7866 gunichar2 const **digitLowerTable,
7867 gunichar2 const **digitUpperTable,
7868 gint64 const **tenPowersList,
7869 gint32 const **decHexDigits)
7871 *mantissas = Formatter_MantissaBitsTable;
7872 *exponents = Formatter_TensExponentTable;
7873 *digitLowerTable = Formatter_DigitLowerTable;
7874 *digitUpperTable = Formatter_DigitUpperTable;
7875 *tenPowersList = Formatter_TenPowersList;
7876 *decHexDigits = Formatter_DecHexDigits;
7880 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7881 * and avoid useless allocations.
7884 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7886 MonoReflectionType *rt;
7890 mono_error_init (error);
7891 for (i = 0; i < type->num_mods; ++i) {
7892 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7897 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7899 for (i = 0; i < type->num_mods; ++i) {
7900 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7901 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7902 return_val_if_nok (error, NULL);
7904 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7905 return_val_if_nok (error, NULL);
7907 mono_array_setref (res, count, rt);
7914 ICALL_EXPORT MonoArray*
7915 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7918 MonoType *type = param->ClassImpl->type;
7919 MonoClass *member_class = mono_object_class (param->MemberImpl);
7920 MonoMethod *method = NULL;
7923 MonoMethodSignature *sig;
7926 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7927 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7928 method = rmethod->method;
7929 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7930 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7931 if (!(method = prop->property->get))
7932 method = prop->property->set;
7935 char *type_name = mono_type_get_full_name (member_class);
7936 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7937 MonoException *ex = mono_get_exception_not_supported (msg);
7940 mono_set_pending_exception (ex);
7944 image = method->klass->image;
7945 pos = param->PositionImpl;
7946 sig = mono_method_signature (method);
7950 type = sig->params [pos];
7952 res = type_array_from_modifiers (image, type, optional, &error);
7953 mono_error_set_pending_exception (&error);
7958 get_property_type (MonoProperty *prop)
7960 MonoMethodSignature *sig;
7962 sig = mono_method_signature (prop->get);
7964 } else if (prop->set) {
7965 sig = mono_method_signature (prop->set);
7966 return sig->params [sig->param_count - 1];
7971 ICALL_EXPORT MonoArray*
7972 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7975 MonoType *type = get_property_type (property->property);
7976 MonoImage *image = property->klass->image;
7981 res = type_array_from_modifiers (image, type, optional, &error);
7982 mono_error_set_pending_exception (&error);
7987 *Construct a MonoType suited to be used to decode a constant blob object.
7989 * @type is the target type which will be constructed
7990 * @blob_type is the blob type, for example, that comes from the constant table
7991 * @real_type is the expected constructed type.
7994 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7996 type->type = blob_type;
7997 type->data.klass = NULL;
7998 if (blob_type == MONO_TYPE_CLASS)
7999 type->data.klass = mono_defaults.object_class;
8000 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8001 /* For enums, we need to use the base type */
8002 type->type = MONO_TYPE_VALUETYPE;
8003 type->data.klass = mono_class_from_mono_type (real_type);
8005 type->data.klass = mono_class_from_mono_type (real_type);
8008 ICALL_EXPORT MonoObject*
8009 property_info_get_default_value (MonoReflectionProperty *property)
8013 MonoProperty *prop = property->property;
8014 MonoType *type = get_property_type (prop);
8015 MonoDomain *domain = mono_object_domain (property);
8016 MonoTypeEnum def_type;
8017 const char *def_value;
8020 mono_class_init (prop->parent);
8022 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8023 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8027 def_value = mono_class_get_property_default_value (prop, &def_type);
8029 mono_type_from_blob_type (&blob_type, def_type, type);
8030 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8032 mono_error_set_pending_exception (&error);
8036 ICALL_EXPORT MonoBoolean
8037 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8040 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8041 MonoCustomAttrInfo *cinfo;
8044 mono_class_init_checked (attr_class, &error);
8045 if (mono_error_set_pending_exception (&error))
8048 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8049 if (!is_ok (&error)) {
8050 mono_error_set_pending_exception (&error);
8055 found = mono_custom_attrs_has_attr (cinfo, attr_class);
8057 mono_custom_attrs_free (cinfo);
8061 ICALL_EXPORT MonoArray*
8062 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8064 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8069 mono_class_init_checked (attr_class, &error);
8070 if (mono_error_set_pending_exception (&error))
8074 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8075 if (!mono_error_ok (&error)) {
8076 mono_error_set_pending_exception (&error);
8083 ICALL_EXPORT MonoArray*
8084 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8088 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8089 mono_error_set_pending_exception (&error);
8094 ICALL_EXPORT MonoString*
8095 ves_icall_Mono_Runtime_GetDisplayName (void)
8098 MonoString *display_name;
8100 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8101 display_name = mono_string_new (mono_domain_get (), info);
8103 return display_name;
8106 ICALL_EXPORT MonoString*
8107 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8110 MonoString *message;
8114 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8115 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8118 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8120 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8121 if (mono_error_set_pending_exception (&error))
8128 ICALL_EXPORT gpointer
8129 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8131 return GetCurrentProcess ();
8134 ICALL_EXPORT MonoBoolean
8135 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8137 return GetExitCodeProcess (handle, (guint32*) exitcode);
8140 ICALL_EXPORT MonoBoolean
8141 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8143 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8144 return CloseHandle (handle);
8146 return CloseProcess (handle);
8150 ICALL_EXPORT MonoBoolean
8151 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8153 return TerminateProcess (handle, exitcode);
8157 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8159 return WaitForInputIdle (handle, milliseconds);
8162 ICALL_EXPORT MonoBoolean
8163 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8165 return GetProcessWorkingSetSize (handle, min, max);
8168 ICALL_EXPORT MonoBoolean
8169 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8171 return SetProcessWorkingSetSize (handle, min, max);
8174 ICALL_EXPORT MonoBoolean
8175 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8177 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8181 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8183 return mono_process_current_pid ();
8187 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8189 return GetPriorityClass (handle);
8192 ICALL_EXPORT MonoBoolean
8193 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8195 return SetPriorityClass (handle, priorityClass);
8198 #ifndef DISABLE_ICALL_TABLES
8200 #define ICALL_TYPE(id,name,first)
8201 #define ICALL(id,name,func) Icall_ ## id,
8204 #include "metadata/icall-def.h"
8210 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8211 #define ICALL(id,name,func)
8213 #include "metadata/icall-def.h"
8219 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8220 #define ICALL(id,name,func)
8222 guint16 first_icall;
8225 static const IcallTypeDesc
8226 icall_type_descs [] = {
8227 #include "metadata/icall-def.h"
8231 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8234 #define ICALL_TYPE(id,name,first)
8237 #ifdef HAVE_ARRAY_ELEM_INIT
8238 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8239 #define MSGSTRFIELD1(line) str##line
8241 static const struct msgstrtn_t {
8242 #define ICALL(id,name,func)
8244 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8245 #include "metadata/icall-def.h"
8247 } icall_type_names_str = {
8248 #define ICALL_TYPE(id,name,first) (name),
8249 #include "metadata/icall-def.h"
8252 static const guint16 icall_type_names_idx [] = {
8253 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8254 #include "metadata/icall-def.h"
8257 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8259 static const struct msgstr_t {
8261 #define ICALL_TYPE(id,name,first)
8262 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8263 #include "metadata/icall-def.h"
8265 } icall_names_str = {
8266 #define ICALL(id,name,func) (name),
8267 #include "metadata/icall-def.h"
8270 static const guint16 icall_names_idx [] = {
8271 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8272 #include "metadata/icall-def.h"
8275 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8281 #define ICALL_TYPE(id,name,first) name,
8282 #define ICALL(id,name,func)
8283 static const char* const
8284 icall_type_names [] = {
8285 #include "metadata/icall-def.h"
8289 #define icall_type_name_get(id) (icall_type_names [(id)])
8293 #define ICALL_TYPE(id,name,first)
8294 #define ICALL(id,name,func) name,
8295 static const char* const
8297 #include "metadata/icall-def.h"
8300 #define icall_name_get(id) icall_names [(id)]
8302 #endif /* !HAVE_ARRAY_ELEM_INIT */
8306 #define ICALL_TYPE(id,name,first)
8307 #define ICALL(id,name,func) func,
8308 static const gconstpointer
8309 icall_functions [] = {
8310 #include "metadata/icall-def.h"
8314 #ifdef ENABLE_ICALL_SYMBOL_MAP
8317 #define ICALL_TYPE(id,name,first)
8318 #define ICALL(id,name,func) #func,
8319 static const gconstpointer
8320 icall_symbols [] = {
8321 #include "metadata/icall-def.h"
8326 #endif /* DISABLE_ICALL_TABLES */
8328 static mono_mutex_t icall_mutex;
8329 static GHashTable *icall_hash = NULL;
8330 static GHashTable *jit_icall_hash_name = NULL;
8331 static GHashTable *jit_icall_hash_addr = NULL;
8334 mono_icall_init (void)
8336 #ifndef DISABLE_ICALL_TABLES
8339 /* check that tables are sorted: disable in release */
8342 const char *prev_class = NULL;
8343 const char *prev_method;
8345 for (i = 0; i < Icall_type_num; ++i) {
8346 const IcallTypeDesc *desc;
8349 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8350 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8351 prev_class = icall_type_name_get (i);
8352 desc = &icall_type_descs [i];
8353 num_icalls = icall_desc_num_icalls (desc);
8354 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8355 for (j = 0; j < num_icalls; ++j) {
8356 const char *methodn = icall_name_get (desc->first_icall + j);
8357 if (prev_method && strcmp (prev_method, methodn) >= 0)
8358 g_print ("method %s should come before method %s\n", methodn, prev_method);
8359 prev_method = methodn;
8365 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8366 mono_os_mutex_init (&icall_mutex);
8370 mono_icall_lock (void)
8372 mono_locks_os_acquire (&icall_mutex, IcallLock);
8376 mono_icall_unlock (void)
8378 mono_locks_os_release (&icall_mutex, IcallLock);
8382 mono_icall_cleanup (void)
8384 g_hash_table_destroy (icall_hash);
8385 g_hash_table_destroy (jit_icall_hash_name);
8386 g_hash_table_destroy (jit_icall_hash_addr);
8387 mono_os_mutex_destroy (&icall_mutex);
8391 * mono_add_internal_call:
8392 * @name: method specification to surface to the managed world
8393 * @method: pointer to a C method to invoke when the method is called
8395 * This method surfaces the C function pointed by @method as a method
8396 * that has been surfaced in managed code with the method specified in
8397 * @name as an internal call.
8399 * Internal calls are surfaced to all app domains loaded and they are
8400 * accessibly by a type with the specified name.
8402 * You must provide a fully qualified type name, that is namespaces
8403 * and type name, followed by a colon and the method name, with an
8404 * optional signature to bind.
8406 * For example, the following are all valid declarations:
8408 * "MyApp.Services.ScriptService:Accelerate"
8409 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8411 * You use method parameters in cases where there might be more than
8412 * one surface method to managed code. That way you can register different
8413 * internal calls for different method overloads.
8415 * The internal calls are invoked with no marshalling. This means that .NET
8416 * types like System.String are exposed as `MonoString *` parameters. This is
8417 * different than the way that strings are surfaced in P/Invoke.
8419 * For more information on how the parameters are marshalled, see the
8420 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8423 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8424 * reference for more information on the format of method descriptions.
8427 mono_add_internal_call (const char *name, gconstpointer method)
8431 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8433 mono_icall_unlock ();
8436 #ifndef DISABLE_ICALL_TABLES
8438 #ifdef HAVE_ARRAY_ELEM_INIT
8440 compare_method_imap (const void *key, const void *elem)
8442 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8443 return strcmp (key, method_name);
8447 find_method_icall (const IcallTypeDesc *imap, const char *name)
8449 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);
8452 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8456 compare_class_imap (const void *key, const void *elem)
8458 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8459 return strcmp (key, class_name);
8462 static const IcallTypeDesc*
8463 find_class_icalls (const char *name)
8465 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);
8468 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8471 #else /* HAVE_ARRAY_ELEM_INIT */
8474 compare_method_imap (const void *key, const void *elem)
8476 const char** method_name = (const char**)elem;
8477 return strcmp (key, *method_name);
8481 find_method_icall (const IcallTypeDesc *imap, const char *name)
8483 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8486 return (gpointer)icall_functions [(nameslot - icall_names)];
8490 compare_class_imap (const void *key, const void *elem)
8492 const char** class_name = (const char**)elem;
8493 return strcmp (key, *class_name);
8496 static const IcallTypeDesc*
8497 find_class_icalls (const char *name)
8499 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8502 return &icall_type_descs [nameslot - icall_type_names];
8505 #endif /* HAVE_ARRAY_ELEM_INIT */
8507 #endif /* DISABLE_ICALL_TABLES */
8510 * we should probably export this as an helper (handle nested types).
8511 * Returns the number of chars written in buf.
8514 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8516 int nspacelen, cnamelen;
8517 nspacelen = strlen (klass->name_space);
8518 cnamelen = strlen (klass->name);
8519 if (nspacelen + cnamelen + 2 > bufsize)
8522 memcpy (buf, klass->name_space, nspacelen);
8523 buf [nspacelen ++] = '.';
8525 memcpy (buf + nspacelen, klass->name, cnamelen);
8526 buf [nspacelen + cnamelen] = 0;
8527 return nspacelen + cnamelen;
8530 #ifdef DISABLE_ICALL_TABLES
8532 no_icall_table (void)
8534 g_assert_not_reached ();
8539 mono_lookup_internal_call (MonoMethod *method)
8544 int typelen = 0, mlen, siglen;
8546 #ifndef DISABLE_ICALL_TABLES
8547 const IcallTypeDesc *imap = NULL;
8550 g_assert (method != NULL);
8552 if (method->is_inflated)
8553 method = ((MonoMethodInflated *) method)->declaring;
8555 if (method->klass->nested_in) {
8556 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8560 mname [pos++] = '/';
8563 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8569 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8574 #ifndef DISABLE_ICALL_TABLES
8575 imap = find_class_icalls (mname);
8578 mname [typelen] = ':';
8579 mname [typelen + 1] = ':';
8581 mlen = strlen (method->name);
8582 memcpy (mname + typelen + 2, method->name, mlen);
8583 sigstart = mname + typelen + 2 + mlen;
8586 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8587 siglen = strlen (tmpsig);
8588 if (typelen + mlen + siglen + 6 > sizeof (mname))
8591 memcpy (sigstart + 1, tmpsig, siglen);
8592 sigstart [siglen + 1] = ')';
8593 sigstart [siglen + 2] = 0;
8598 res = g_hash_table_lookup (icall_hash, mname);
8600 mono_icall_unlock ();;
8603 /* try without signature */
8605 res = g_hash_table_lookup (icall_hash, mname);
8607 mono_icall_unlock ();
8611 #ifdef DISABLE_ICALL_TABLES
8612 mono_icall_unlock ();
8613 /* Fail only when the result is actually used */
8614 /* mono_marshal_get_native_wrapper () depends on this */
8615 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8616 return ves_icall_System_String_ctor_RedirectToCreateString;
8618 return no_icall_table;
8620 /* it wasn't found in the static call tables */
8622 mono_icall_unlock ();
8625 res = find_method_icall (imap, sigstart - mlen);
8627 mono_icall_unlock ();
8630 /* try _with_ signature */
8632 res = find_method_icall (imap, sigstart - mlen);
8634 mono_icall_unlock ();
8638 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8639 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8640 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8641 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8642 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");
8643 g_print ("If you see other errors or faults after this message they are probably related\n");
8644 g_print ("and you need to fix your mono install first.\n");
8646 mono_icall_unlock ();
8652 #ifdef ENABLE_ICALL_SYMBOL_MAP
8654 func_cmp (gconstpointer key, gconstpointer p)
8656 return (gsize)key - (gsize)*(gsize*)p;
8661 * mono_lookup_icall_symbol:
8663 * Given the icall METHOD, returns its C symbol.
8666 mono_lookup_icall_symbol (MonoMethod *m)
8668 #ifdef DISABLE_ICALL_TABLES
8669 g_assert_not_reached ();
8672 #ifdef ENABLE_ICALL_SYMBOL_MAP
8676 static gconstpointer *functions_sorted;
8677 static const char**symbols_sorted;
8678 static gboolean inited;
8683 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8684 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8685 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8686 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8687 /* Bubble sort the two arrays */
8691 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8692 if (functions_sorted [i] > functions_sorted [i + 1]) {
8695 tmp = functions_sorted [i];
8696 functions_sorted [i] = functions_sorted [i + 1];
8697 functions_sorted [i + 1] = tmp;
8698 tmp = symbols_sorted [i];
8699 symbols_sorted [i] = symbols_sorted [i + 1];
8700 symbols_sorted [i + 1] = tmp;
8707 func = mono_lookup_internal_call (m);
8710 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8714 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8716 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8717 g_assert_not_reached ();
8724 type_from_typename (char *type_name)
8726 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8728 if (!strcmp (type_name, "int"))
8729 klass = mono_defaults.int_class;
8730 else if (!strcmp (type_name, "ptr"))
8731 klass = mono_defaults.int_class;
8732 else if (!strcmp (type_name, "void"))
8733 klass = mono_defaults.void_class;
8734 else if (!strcmp (type_name, "int32"))
8735 klass = mono_defaults.int32_class;
8736 else if (!strcmp (type_name, "uint32"))
8737 klass = mono_defaults.uint32_class;
8738 else if (!strcmp (type_name, "int8"))
8739 klass = mono_defaults.sbyte_class;
8740 else if (!strcmp (type_name, "uint8"))
8741 klass = mono_defaults.byte_class;
8742 else if (!strcmp (type_name, "int16"))
8743 klass = mono_defaults.int16_class;
8744 else if (!strcmp (type_name, "uint16"))
8745 klass = mono_defaults.uint16_class;
8746 else if (!strcmp (type_name, "long"))
8747 klass = mono_defaults.int64_class;
8748 else if (!strcmp (type_name, "ulong"))
8749 klass = mono_defaults.uint64_class;
8750 else if (!strcmp (type_name, "float"))
8751 klass = mono_defaults.single_class;
8752 else if (!strcmp (type_name, "double"))
8753 klass = mono_defaults.double_class;
8754 else if (!strcmp (type_name, "object"))
8755 klass = mono_defaults.object_class;
8756 else if (!strcmp (type_name, "obj"))
8757 klass = mono_defaults.object_class;
8758 else if (!strcmp (type_name, "string"))
8759 klass = mono_defaults.string_class;
8760 else if (!strcmp (type_name, "bool"))
8761 klass = mono_defaults.boolean_class;
8762 else if (!strcmp (type_name, "boolean"))
8763 klass = mono_defaults.boolean_class;
8765 g_error ("%s", type_name);
8766 g_assert_not_reached ();
8768 return &klass->byval_arg;
8772 * LOCKING: Take the corlib image lock.
8774 MonoMethodSignature*
8775 mono_create_icall_signature (const char *sigstr)
8780 MonoMethodSignature *res, *res2;
8781 MonoImage *corlib = mono_defaults.corlib;
8783 mono_image_lock (corlib);
8784 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8785 mono_image_unlock (corlib);
8790 parts = g_strsplit (sigstr, " ", 256);
8799 res = mono_metadata_signature_alloc (corlib, len - 1);
8804 * Under windows, the default pinvoke calling convention is STDCALL but
8807 res->call_convention = MONO_CALL_C;
8810 res->ret = type_from_typename (parts [0]);
8811 for (i = 1; i < len; ++i) {
8812 res->params [i - 1] = type_from_typename (parts [i]);
8817 mono_image_lock (corlib);
8818 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8820 res = res2; /*Value is allocated in the image pool*/
8822 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8823 mono_image_unlock (corlib);
8829 mono_find_jit_icall_by_name (const char *name)
8831 MonoJitICallInfo *info;
8832 g_assert (jit_icall_hash_name);
8835 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8836 mono_icall_unlock ();
8841 mono_find_jit_icall_by_addr (gconstpointer addr)
8843 MonoJitICallInfo *info;
8844 g_assert (jit_icall_hash_addr);
8847 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8848 mono_icall_unlock ();
8854 * mono_get_jit_icall_info:
8856 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8857 * caller should access it while holding the icall lock.
8860 mono_get_jit_icall_info (void)
8862 return jit_icall_hash_name;
8866 * mono_lookup_jit_icall_symbol:
8868 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8871 mono_lookup_jit_icall_symbol (const char *name)
8873 MonoJitICallInfo *info;
8874 const char *res = NULL;
8877 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8879 res = info->c_symbol;
8880 mono_icall_unlock ();
8885 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8888 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8889 mono_icall_unlock ();
8893 * 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
8894 * icalls without wrappers in some cases.
8897 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8899 MonoJitICallInfo *info;
8906 if (!jit_icall_hash_name) {
8907 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8908 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8911 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8912 g_warning ("jit icall already defined \"%s\"\n", name);
8913 g_assert_not_reached ();
8916 info = g_new0 (MonoJitICallInfo, 1);
8921 info->c_symbol = c_symbol;
8922 info->no_raise = no_raise;
8925 info->wrapper = func;
8927 info->wrapper = NULL;
8930 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8931 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8933 mono_icall_unlock ();
8938 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8940 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);