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_for_class_failure (error, 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 MonoArray*
717 ves_icall_System_Array_Clone (MonoArray *arr)
720 MonoArray *result = mono_array_clone_checked (arr, &error);
721 mono_error_set_pending_exception (&error);
725 ICALL_EXPORT gboolean
726 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
731 MonoVTable *src_vtable;
732 MonoVTable *dest_vtable;
733 MonoClass *src_class;
734 MonoClass *dest_class;
736 src_vtable = source->obj.vtable;
737 dest_vtable = dest->obj.vtable;
739 if (src_vtable->rank != dest_vtable->rank)
742 if (source->bounds || dest->bounds)
745 /* there's no integer overflow since mono_array_length returns an unsigned integer */
746 if ((dest_idx + length > mono_array_length_fast (dest)) ||
747 (source_idx + length > mono_array_length_fast (source)))
750 src_class = src_vtable->klass->element_class;
751 dest_class = dest_vtable->klass->element_class;
754 * Handle common cases.
757 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
758 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
760 if (src_class == mono_defaults.object_class && dest_class->valuetype)
763 /* Check if we're copying a char[] <==> (u)short[] */
764 if (src_class != dest_class) {
765 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
768 /* 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. */
769 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
773 if (dest_class->valuetype) {
774 element_size = mono_array_element_size (source->obj.vtable->klass);
775 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
776 if (dest_class->has_references) {
777 mono_value_copy_array (dest, dest_idx, source_addr, length);
779 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
780 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
783 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
790 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
796 ac = (MonoClass *)arr->obj.vtable->klass;
798 esize = mono_array_element_size (ac);
799 ea = (gpointer*)((char*)arr->vector + (pos * esize));
801 mono_gc_memmove_atomic (value, ea, esize);
805 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
811 ac = (MonoClass *)arr->obj.vtable->klass;
812 ec = ac->element_class;
814 esize = mono_array_element_size (ac);
815 ea = (gpointer*)((char*)arr->vector + (pos * esize));
817 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
818 g_assert (esize == sizeof (gpointer));
819 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
821 g_assert (ec->inited);
822 g_assert (esize == mono_class_value_size (ec, NULL));
823 if (ec->has_references)
824 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
826 mono_gc_memmove_atomic (ea, value, esize);
831 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
833 MonoClass *klass = array->obj.vtable->klass;
834 guint32 size = mono_array_element_size (klass);
835 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
837 const char *field_data;
839 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
840 MonoException *exc = mono_get_exception_argument("array",
841 "Cannot initialize array of non-primitive type.");
842 mono_set_pending_exception (exc);
846 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
847 MonoException *exc = mono_get_exception_argument("field_handle",
848 "Field doesn't have an RVA");
849 mono_set_pending_exception (exc);
853 size *= array->max_length;
854 field_data = mono_field_get_data (field_handle);
856 if (size > mono_type_size (field_handle->type, &align)) {
857 MonoException *exc = mono_get_exception_argument("field_handle",
858 "Field not large enough to fill array");
859 mono_set_pending_exception (exc);
863 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
865 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
866 guint ## n *src = (guint ## n *) field_data; \
868 nEnt = (size / sizeof(guint ## n)); \
870 for (i = 0; i < nEnt; i++) { \
871 data[i] = read ## n (&src[i]); \
875 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
877 switch (type->type) {
894 memcpy (mono_array_addr (array, char, 0), field_data, size);
898 memcpy (mono_array_addr (array, char, 0), field_data, size);
903 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
905 return offsetof (MonoString, chars);
908 ICALL_EXPORT MonoObject *
909 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
911 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
915 MonoObject *ret = mono_object_clone_checked (obj, &error);
916 mono_error_set_pending_exception (&error);
923 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
929 MONO_CHECK_ARG_NULL (handle,);
931 klass = mono_class_from_mono_type (handle);
932 MONO_CHECK_ARG (handle, klass,);
934 if (klass->generic_container)
937 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
938 if (!is_ok (&error)) {
939 mono_error_set_pending_exception (&error);
943 /* This will call the type constructor */
944 if (!mono_runtime_class_init_full (vtable, &error))
945 mono_error_set_pending_exception (&error);
949 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
953 mono_image_check_for_module_cctor (image);
954 if (image->has_module_cctor) {
955 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
956 if (!mono_error_ok (&error)) {
957 mono_error_set_pending_exception (&error);
960 /*It's fine to raise the exception here*/
961 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
962 if (!is_ok (&error)) {
963 mono_error_set_pending_exception (&error);
966 if (!mono_runtime_class_init_full (vtable, &error))
967 mono_error_set_pending_exception (&error);
971 ICALL_EXPORT MonoBoolean
972 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
977 /* later make this configurable and per-arch */
978 int min_size = 4096 * 4 * sizeof (void*);
979 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
980 /* if we have no info we are optimistic and assume there is enough room */
984 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
988 current = (guint8 *)&stack_addr;
989 if (current > stack_addr) {
990 if ((current - stack_addr) < min_size)
993 if (current - (stack_addr - stack_size) < min_size)
999 ICALL_EXPORT MonoObject *
1000 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
1003 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
1004 mono_error_set_pending_exception (&error);
1010 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1014 MonoObject **values = NULL;
1017 gint32 result = (int)(gsize)mono_defaults.int32_class;
1018 MonoClassField* field;
1021 klass = mono_object_class (this_obj);
1023 if (mono_class_num_fields (klass) == 0)
1027 * Compute the starting value of the hashcode for fields of primitive
1028 * types, and return the remaining fields in an array to the managed side.
1029 * This way, we can avoid costly reflection operations in managed code.
1032 while ((field = mono_class_get_fields (klass, &iter))) {
1033 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1035 if (mono_field_is_deleted (field))
1037 /* FIXME: Add more types */
1038 switch (field->type->type) {
1040 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1042 case MONO_TYPE_STRING: {
1044 s = *(MonoString**)((guint8*)this_obj + field->offset);
1046 result ^= mono_string_hash (s);
1051 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1052 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1053 if (!is_ok (&error)) {
1054 mono_error_set_pending_exception (&error);
1057 values [count++] = o;
1063 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1064 if (mono_error_set_pending_exception (&error))
1066 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1067 for (i = 0; i < count; ++i)
1068 mono_array_setref (*fields, i, values [i]);
1075 ICALL_EXPORT MonoBoolean
1076 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1080 MonoObject **values = NULL;
1082 MonoClassField* field;
1086 MONO_CHECK_ARG_NULL (that, FALSE);
1088 if (this_obj->vtable != that->vtable)
1091 klass = mono_object_class (this_obj);
1093 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1094 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1097 * Do the comparison for fields of primitive type and return a result if
1098 * possible. Otherwise, return the remaining fields in an array to the
1099 * managed side. This way, we can avoid costly reflection operations in
1104 while ((field = mono_class_get_fields (klass, &iter))) {
1105 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1107 if (mono_field_is_deleted (field))
1109 /* FIXME: Add more types */
1110 switch (field->type->type) {
1113 case MONO_TYPE_BOOLEAN:
1114 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1119 case MONO_TYPE_CHAR:
1120 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1125 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1130 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1134 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1138 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1143 case MONO_TYPE_STRING: {
1144 MonoString *s1, *s2;
1145 guint32 s1len, s2len;
1146 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1147 s2 = *(MonoString**)((guint8*)that + field->offset);
1150 if ((s1 == NULL) || (s2 == NULL))
1152 s1len = mono_string_length (s1);
1153 s2len = mono_string_length (s2);
1157 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1163 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1164 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1165 if (!is_ok (&error)) {
1166 mono_error_set_pending_exception (&error);
1169 values [count++] = o;
1170 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1171 if (!is_ok (&error)) {
1172 mono_error_set_pending_exception (&error);
1175 values [count++] = o;
1178 if (klass->enumtype)
1179 /* enums only have one non-static field */
1185 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1186 if (mono_error_set_pending_exception (&error))
1188 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1189 for (i = 0; i < count; ++i)
1190 mono_array_setref_fast (*fields, i, values [i]);
1197 ICALL_EXPORT MonoReflectionType *
1198 ves_icall_System_Object_GetType (MonoObject *obj)
1201 MonoReflectionType *ret;
1202 #ifndef DISABLE_REMOTING
1203 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1204 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1207 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1209 mono_error_set_pending_exception (&error);
1214 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1216 MONO_CHECK_ARG_NULL (obj, 0);
1219 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1220 mono_error_set_pending_exception (&error);
1225 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1226 MonoReflectionMethod *method,
1227 MonoArray *opt_param_types)
1229 MONO_CHECK_ARG_NULL (method, 0);
1232 gint32 result = mono_image_create_method_token (
1233 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1234 mono_error_set_pending_exception (&error);
1239 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1242 mono_image_create_pefile (mb, file, &error);
1243 mono_error_set_pending_exception (&error);
1247 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1250 mono_image_build_metadata (mb, &error);
1251 mono_error_set_pending_exception (&error);
1255 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1257 mono_image_register_token (mb->dynamic_image, token, obj);
1260 ICALL_EXPORT MonoObject*
1261 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1265 mono_loader_lock ();
1266 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1267 mono_loader_unlock ();
1272 ICALL_EXPORT MonoReflectionModule*
1273 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1276 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1277 mono_error_set_pending_exception (&error);
1282 * ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class:
1283 * @tb: a TypeBuilder object
1286 * Creates the generic class after all generic parameters have been added.
1289 ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class (MonoReflectionTypeBuilder *tb)
1292 (void) mono_reflection_create_generic_class (tb, &error);
1293 mono_error_set_pending_exception (&error);
1296 #ifndef DISABLE_REFLECTION_EMIT
1297 ICALL_EXPORT MonoArray*
1298 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
1301 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
1302 mono_error_set_pending_exception (&error);
1308 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1310 MonoMethod **dest = (MonoMethod **)data;
1312 /* skip unmanaged frames */
1317 if (!strcmp (m->klass->name_space, "System.Reflection"))
1326 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1328 MonoMethod **dest = (MonoMethod **)data;
1330 /* skip unmanaged frames */
1334 if (m->wrapper_type != MONO_WRAPPER_NONE)
1342 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1353 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1355 MonoMethod **dest = (MonoMethod **)data;
1357 /* skip unmanaged frames */
1361 if (m->wrapper_type != MONO_WRAPPER_NONE)
1369 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1370 || (!strcmp (m->klass->name_space, "System"))))
1380 static MonoReflectionType *
1381 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1383 MonoMethod *m, *dest;
1385 MonoType *type = NULL;
1386 MonoAssembly *assembly = NULL;
1387 gboolean type_resolve = FALSE;
1388 MonoImage *rootimage = NULL;
1390 mono_error_init (error);
1393 * We must compute the calling assembly as type loading must happen under a metadata context.
1394 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1395 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1397 m = mono_method_get_last_managed ();
1399 if (m && m->klass->image != mono_defaults.corlib) {
1400 /* Happens with inlining */
1402 /* Ugly hack: type_from_parsed_name is called from
1403 * System.Type.internal_from_name, which is called most
1404 * directly from System.Type.GetType(string,bool,bool) but
1405 * also indirectly from places such as
1406 * System.Type.GetType(string,func,func) (via
1407 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1408 * so we need to skip over all of those to find the true caller.
1410 * It would be nice if we had stack marks.
1412 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1418 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1419 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1420 * to crash. This only seems to happen in some strange remoting
1421 * scenarios and I was unable to figure out what's happening there.
1422 * Dec 10, 2005 - Martin.
1426 assembly = dest->klass->image->assembly;
1427 type_resolve = TRUE;
1428 rootimage = assembly->image;
1430 g_warning (G_STRLOC);
1433 if (info->assembly.name)
1434 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1437 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1438 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1439 return_val_if_nok (error, NULL);
1443 // Say we're looking for System.Generic.Dict<int, Local>
1444 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1445 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1446 // is messed up when we go to construct the Local as the type arg...
1448 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1449 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1450 if (!info->assembly.name && !type) {
1452 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1453 return_val_if_nok (error, NULL);
1455 if (assembly && !type && type_resolve) {
1456 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1457 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1458 return_val_if_nok (error, NULL);
1464 return mono_type_get_object_checked (mono_domain_get (), type, error);
1467 ICALL_EXPORT MonoReflectionType*
1468 ves_icall_System_Type_internal_from_name (MonoString *name,
1469 MonoBoolean throwOnError,
1470 MonoBoolean ignoreCase)
1473 MonoTypeNameParse info;
1474 MonoReflectionType *type = NULL;
1477 char *str = mono_string_to_utf8_checked (name, &error);
1478 if (!is_ok (&error))
1481 parsedOk = mono_reflection_parse_type (str, &info);
1483 /* mono_reflection_parse_type() mangles the string */
1485 mono_reflection_free_type_info (&info);
1487 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1491 type = type_from_parsed_name (&info, ignoreCase, &error);
1493 mono_reflection_free_type_info (&info);
1495 if (!is_ok (&error))
1500 mono_error_set_type_load_name (&error, g_strdup (str), NULL, "");
1507 if (!is_ok (&error)) {
1509 mono_error_set_pending_exception (&error);
1511 mono_error_cleanup (&error);
1519 ICALL_EXPORT MonoReflectionType*
1520 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1523 MonoReflectionType *ret;
1524 MonoDomain *domain = mono_domain_get ();
1526 ret = mono_type_get_object_checked (domain, handle, &error);
1527 mono_error_set_pending_exception (&error);
1532 ICALL_EXPORT MonoType*
1533 ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass)
1535 return mono_class_get_type (klass);
1539 ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array, MonoBoolean freeSeg)
1541 g_ptr_array_free (ptr_array, freeSeg);
1544 /* System.TypeCode */
1563 TYPECODE_STRING = 18
1566 ICALL_EXPORT guint32
1567 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1569 int t = type->type->type;
1571 if (type->type->byref)
1572 return TYPECODE_OBJECT;
1576 case MONO_TYPE_VOID:
1577 return TYPECODE_OBJECT;
1578 case MONO_TYPE_BOOLEAN:
1579 return TYPECODE_BOOLEAN;
1581 return TYPECODE_BYTE;
1583 return TYPECODE_SBYTE;
1585 return TYPECODE_UINT16;
1587 return TYPECODE_INT16;
1588 case MONO_TYPE_CHAR:
1589 return TYPECODE_CHAR;
1593 return TYPECODE_OBJECT;
1595 return TYPECODE_UINT32;
1597 return TYPECODE_INT32;
1599 return TYPECODE_UINT64;
1601 return TYPECODE_INT64;
1603 return TYPECODE_SINGLE;
1605 return TYPECODE_DOUBLE;
1606 case MONO_TYPE_VALUETYPE: {
1607 MonoClass *klass = type->type->data.klass;
1609 if (klass->enumtype) {
1610 t = mono_class_enum_basetype (klass)->type;
1612 } else if (mono_is_corlib_image (klass->image)) {
1613 if (strcmp (klass->name_space, "System") == 0) {
1614 if (strcmp (klass->name, "Decimal") == 0)
1615 return TYPECODE_DECIMAL;
1616 else if (strcmp (klass->name, "DateTime") == 0)
1617 return TYPECODE_DATETIME;
1620 return TYPECODE_OBJECT;
1622 case MONO_TYPE_STRING:
1623 return TYPECODE_STRING;
1624 case MONO_TYPE_SZARRAY:
1625 case MONO_TYPE_ARRAY:
1626 case MONO_TYPE_OBJECT:
1628 case MONO_TYPE_MVAR:
1629 case MONO_TYPE_TYPEDBYREF:
1630 return TYPECODE_OBJECT;
1631 case MONO_TYPE_CLASS:
1633 MonoClass *klass = type->type->data.klass;
1634 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1635 if (strcmp (klass->name, "DBNull") == 0)
1636 return TYPECODE_DBNULL;
1639 return TYPECODE_OBJECT;
1640 case MONO_TYPE_GENERICINST:
1641 return TYPECODE_OBJECT;
1643 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1649 mono_type_is_primitive (MonoType *type)
1651 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1652 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1656 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1658 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1659 return mono_class_enum_basetype (type->data.klass);
1660 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1661 return mono_class_enum_basetype (type->data.generic_class->container_class);
1665 ICALL_EXPORT guint32
1666 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1671 g_assert (type != NULL);
1673 klass = mono_class_from_mono_type (type->type);
1674 klassc = mono_class_from_mono_type (c->type);
1676 if (type->type->byref ^ c->type->byref)
1679 if (type->type->byref) {
1680 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1681 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1683 klass = mono_class_from_mono_type (t);
1684 klassc = mono_class_from_mono_type (ot);
1686 if (mono_type_is_primitive (t)) {
1687 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1688 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1689 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1690 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1691 return t->type == ot->type;
1693 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1696 if (klass->valuetype)
1697 return klass == klassc;
1698 return klass->valuetype == klassc->valuetype;
1701 return mono_class_is_assignable_from (klass, klassc);
1704 ICALL_EXPORT guint32
1705 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1708 MonoClass *klass = mono_class_from_mono_type (type->type);
1709 mono_class_init_checked (klass, &error);
1710 if (!is_ok (&error)) {
1711 mono_error_set_pending_exception (&error);
1714 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1715 mono_error_set_pending_exception (&error);
1719 ICALL_EXPORT guint32
1720 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1722 MonoClass *klass = mono_class_from_mono_type (type->type);
1723 return klass->flags;
1726 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1727 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1730 MonoClass *klass = field->field->parent;
1731 MonoMarshalType *info;
1735 if (klass->generic_container ||
1736 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1739 ftype = mono_field_get_type (field->field);
1740 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1743 info = mono_marshal_load_type_info (klass);
1745 for (i = 0; i < info->num_fields; ++i) {
1746 if (info->fields [i].field == field->field) {
1747 if (!info->fields [i].mspec)
1750 MonoReflectionMarshalAsAttribute* obj;
1751 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1752 if (!mono_error_ok (&error))
1753 mono_error_set_pending_exception (&error);
1762 ICALL_EXPORT MonoReflectionField*
1763 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1766 gboolean found = FALSE;
1772 klass = handle->parent;
1774 klass = mono_class_from_mono_type (type);
1776 found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1779 /* The managed code will throw the exception */
1783 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1784 mono_error_set_pending_exception (&error);
1788 ICALL_EXPORT MonoReflectionEvent*
1789 ves_icall_System_Reflection_EventInfo_internal_from_handle_type (MonoEvent *handle, MonoType *type)
1797 klass = handle->parent;
1799 klass = mono_class_from_mono_type (type);
1801 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1803 /* Managed code will throw an exception */
1807 MonoReflectionEvent *result = mono_event_get_object_checked (mono_domain_get (), klass, handle, &error);
1808 mono_error_set_pending_exception (&error);
1813 ICALL_EXPORT MonoReflectionProperty*
1814 ves_icall_System_Reflection_PropertyInfo_internal_from_handle_type (MonoProperty *handle, MonoType *type)
1822 klass = handle->parent;
1824 klass = mono_class_from_mono_type (type);
1826 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1828 /* Managed code will throw an exception */
1832 MonoReflectionProperty *result = mono_property_get_object_checked (mono_domain_get (), klass, handle, &error);
1833 mono_error_set_pending_exception (&error);
1837 ICALL_EXPORT MonoArray*
1838 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1841 MonoType *type = mono_field_get_type_checked (field->field, &error);
1844 if (!mono_error_ok (&error)) {
1845 mono_error_set_pending_exception (&error);
1849 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1850 mono_error_set_pending_exception (&error);
1855 vell_icall_get_method_attributes (MonoMethod *method)
1857 return method->flags;
1861 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1864 MonoReflectionType *rt;
1865 MonoDomain *domain = mono_domain_get ();
1866 MonoMethodSignature* sig;
1868 sig = mono_method_signature_checked (method, &error);
1869 if (!mono_error_ok (&error)) {
1870 mono_error_set_pending_exception (&error);
1874 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1875 if (!mono_error_ok (&error)) {
1876 mono_error_set_pending_exception (&error);
1880 MONO_STRUCT_SETREF (info, parent, rt);
1882 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1883 if (!mono_error_ok (&error)) {
1884 mono_error_set_pending_exception (&error);
1888 MONO_STRUCT_SETREF (info, ret, rt);
1890 info->attrs = method->flags;
1891 info->implattrs = method->iflags;
1892 if (sig->call_convention == MONO_CALL_DEFAULT)
1893 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1895 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1900 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1903 ICALL_EXPORT MonoArray*
1904 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1907 MonoDomain *domain = mono_domain_get ();
1909 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1910 mono_error_set_pending_exception (&error);
1914 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1915 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1918 MonoDomain *domain = mono_domain_get ();
1919 MonoReflectionMarshalAsAttribute* res = NULL;
1920 MonoMarshalSpec **mspecs;
1923 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1924 mono_method_get_marshal_info (method, mspecs);
1927 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1928 if (!mono_error_ok (&error)) {
1929 mono_error_set_pending_exception (&error);
1934 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1936 mono_metadata_free_marshal_spec (mspecs [i]);
1943 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1945 MonoClass *parent = field->field->parent;
1946 if (!parent->size_inited)
1947 mono_class_init (parent);
1948 mono_class_setup_fields_locking (parent);
1950 return field->field->offset - sizeof (MonoObject);
1953 ICALL_EXPORT MonoReflectionType*
1954 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1957 MonoReflectionType *ret;
1960 parent = declaring? field->field->parent: field->klass;
1962 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1963 mono_error_set_pending_exception (&error);
1969 ICALL_EXPORT MonoObject *
1970 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1973 MonoClass *fklass = field->klass;
1974 MonoClassField *cf = field->field;
1975 MonoDomain *domain = mono_object_domain (field);
1977 if (fklass->image->assembly->ref_only) {
1978 mono_set_pending_exception (mono_get_exception_invalid_operation (
1979 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1983 if (mono_security_core_clr_enabled () &&
1984 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1985 mono_error_set_pending_exception (&error);
1989 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1990 mono_error_set_pending_exception (&error);
1995 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1998 MonoClassField *cf = field->field;
2002 if (field->klass->image->assembly->ref_only) {
2003 mono_set_pending_exception (mono_get_exception_invalid_operation (
2004 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
2008 if (mono_security_core_clr_enabled () &&
2009 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
2010 mono_error_set_pending_exception (&error);
2014 type = mono_field_get_type_checked (cf, &error);
2015 if (!mono_error_ok (&error)) {
2016 mono_error_set_pending_exception (&error);
2020 v = (gchar *) value;
2022 switch (type->type) {
2025 case MONO_TYPE_BOOLEAN:
2028 case MONO_TYPE_CHAR:
2037 case MONO_TYPE_VALUETYPE:
2040 v += sizeof (MonoObject);
2042 case MONO_TYPE_STRING:
2043 case MONO_TYPE_OBJECT:
2044 case MONO_TYPE_CLASS:
2045 case MONO_TYPE_ARRAY:
2046 case MONO_TYPE_SZARRAY:
2049 case MONO_TYPE_GENERICINST: {
2050 MonoGenericClass *gclass = type->data.generic_class;
2051 g_assert (!gclass->context.class_inst->is_open);
2053 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
2054 MonoClass *nklass = mono_class_from_mono_type (type);
2055 MonoObject *nullable;
2058 * Convert the boxed vtype into a Nullable structure.
2059 * This is complicated by the fact that Nullables have
2060 * a variable structure.
2062 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2063 if (!mono_error_ok (&error)) {
2064 mono_error_set_pending_exception (&error);
2068 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2070 v = (gchar *)mono_object_unbox (nullable);
2073 if (gclass->container_class->valuetype && (v != NULL))
2074 v += sizeof (MonoObject);
2078 g_error ("type 0x%x not handled in "
2079 "ves_icall_FieldInfo_SetValueInternal", type->type);
2084 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2085 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2086 if (!is_ok (&error)) {
2087 mono_error_set_pending_exception (&error);
2090 if (!vtable->initialized) {
2091 if (!mono_runtime_class_init_full (vtable, &error)) {
2092 mono_error_set_pending_exception (&error);
2096 mono_field_static_set_value (vtable, cf, v);
2098 mono_field_set_value (obj, cf, v);
2103 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2112 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2113 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2117 if (MONO_TYPE_IS_REFERENCE (f->type))
2118 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2120 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2123 ICALL_EXPORT MonoObject *
2124 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2126 MonoObject *o = NULL;
2127 MonoClassField *field = rfield->field;
2129 MonoDomain *domain = mono_object_domain (rfield);
2131 MonoTypeEnum def_type;
2132 const char *def_value;
2136 mono_class_init (field->parent);
2138 t = mono_field_get_type_checked (field, &error);
2139 if (!mono_error_ok (&error)) {
2140 mono_error_set_pending_exception (&error);
2144 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2145 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2149 if (image_is_dynamic (field->parent->image)) {
2150 MonoClass *klass = field->parent;
2151 int fidx = field - klass->fields;
2153 g_assert (fidx >= 0 && fidx < klass->field.count);
2154 g_assert (klass->ext);
2155 g_assert (klass->ext->field_def_values);
2156 def_type = klass->ext->field_def_values [fidx].def_type;
2157 def_value = klass->ext->field_def_values [fidx].data;
2158 if (def_type == MONO_TYPE_END) {
2159 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2163 def_value = mono_class_get_field_default_value (field, &def_type);
2164 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2166 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2171 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2175 case MONO_TYPE_BOOLEAN:
2178 case MONO_TYPE_CHAR:
2186 case MONO_TYPE_R8: {
2189 /* boxed value type */
2190 t = g_new0 (MonoType, 1);
2192 klass = mono_class_from_mono_type (t);
2194 o = mono_object_new_checked (domain, klass, &error);
2195 if (!mono_error_ok (&error)) {
2196 mono_error_set_pending_exception (&error);
2199 v = ((gchar *) o) + sizeof (MonoObject);
2200 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2201 if (mono_error_set_pending_exception (&error))
2205 case MONO_TYPE_STRING:
2206 case MONO_TYPE_CLASS:
2207 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2208 if (mono_error_set_pending_exception (&error))
2212 g_assert_not_reached ();
2218 ICALL_EXPORT MonoReflectionType*
2219 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2222 MonoReflectionType *ret;
2225 type = mono_field_get_type_checked (ref_field->field, &error);
2226 if (!mono_error_ok (&error)) {
2227 mono_error_set_pending_exception (&error);
2231 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2232 if (!mono_error_ok (&error)) {
2233 mono_error_set_pending_exception (&error);
2240 /* From MonoProperty.cs */
2242 PInfo_Attributes = 1,
2243 PInfo_GetMethod = 1 << 1,
2244 PInfo_SetMethod = 1 << 2,
2245 PInfo_ReflectedType = 1 << 3,
2246 PInfo_DeclaringType = 1 << 4,
2251 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2254 MonoReflectionType *rt;
2255 MonoReflectionMethod *rm;
2256 MonoDomain *domain = mono_object_domain (property);
2257 const MonoProperty *pproperty = property->property;
2259 if ((req_info & PInfo_ReflectedType) != 0) {
2260 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2261 if (mono_error_set_pending_exception (&error))
2264 MONO_STRUCT_SETREF (info, parent, rt);
2266 if ((req_info & PInfo_DeclaringType) != 0) {
2267 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2268 if (mono_error_set_pending_exception (&error))
2271 MONO_STRUCT_SETREF (info, declaring_type, rt);
2274 if ((req_info & PInfo_Name) != 0)
2275 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2277 if ((req_info & PInfo_Attributes) != 0)
2278 info->attrs = pproperty->attrs;
2280 if ((req_info & PInfo_GetMethod) != 0) {
2281 if (pproperty->get &&
2282 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2283 pproperty->get->klass == property->klass)) {
2284 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2285 if (mono_error_set_pending_exception (&error))
2291 MONO_STRUCT_SETREF (info, get, rm);
2293 if ((req_info & PInfo_SetMethod) != 0) {
2294 if (pproperty->set &&
2295 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2296 pproperty->set->klass == property->klass)) {
2297 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2298 if (mono_error_set_pending_exception (&error))
2304 MONO_STRUCT_SETREF (info, set, rm);
2307 * There may be other methods defined for properties, though, it seems they are not exposed
2308 * in the reflection API
2313 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2316 MonoReflectionType *rt;
2317 MonoReflectionMethod *rm;
2318 MonoDomain *domain = mono_object_domain (event);
2320 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2321 if (mono_error_set_pending_exception (&error))
2324 MONO_STRUCT_SETREF (info, reflected_type, rt);
2326 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2327 if (mono_error_set_pending_exception (&error))
2330 MONO_STRUCT_SETREF (info, declaring_type, rt);
2332 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2333 info->attrs = event->event->attrs;
2335 if (event->event->add) {
2336 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2337 if (mono_error_set_pending_exception (&error))
2343 MONO_STRUCT_SETREF (info, add_method, rm);
2345 if (event->event->remove) {
2346 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2347 if (mono_error_set_pending_exception (&error))
2353 MONO_STRUCT_SETREF (info, remove_method, rm);
2355 if (event->event->raise) {
2356 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2357 if (mono_error_set_pending_exception (&error))
2363 MONO_STRUCT_SETREF (info, raise_method, rm);
2365 #ifndef MONO_SMALL_CONFIG
2366 if (event->event->other) {
2368 while (event->event->other [n])
2370 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2371 if (mono_error_set_pending_exception (&error))
2373 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2375 for (i = 0; i < n; i++) {
2376 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2377 if (mono_error_set_pending_exception (&error))
2379 mono_array_setref (info->other_methods, i, rm);
2386 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2391 mono_class_setup_interfaces (klass, error);
2392 if (!mono_error_ok (error))
2395 for (i = 0; i < klass->interface_count; i++) {
2396 ic = klass->interfaces [i];
2397 g_hash_table_insert (ifaces, ic, ic);
2399 collect_interfaces (ic, ifaces, error);
2400 if (!mono_error_ok (error))
2406 MonoArray *iface_array;
2407 MonoGenericContext *context;
2411 } FillIfaceArrayData;
2414 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2416 MonoReflectionType *rt;
2417 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2418 MonoClass *ic = (MonoClass *)key;
2419 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2421 if (!mono_error_ok (data->error))
2424 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2425 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2426 if (!mono_error_ok (data->error))
2430 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2431 if (!mono_error_ok (data->error))
2434 mono_array_setref (data->iface_array, data->next_idx++, rt);
2437 mono_metadata_free_type (inflated);
2441 get_interfaces_hash (gconstpointer v1)
2443 MonoClass *k = (MonoClass*)v1;
2445 return k->type_token;
2448 ICALL_EXPORT MonoArray*
2449 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2452 MonoClass *klass = mono_class_from_mono_type (type->type);
2454 FillIfaceArrayData data = { 0 };
2457 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2459 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2460 data.context = mono_class_get_context (klass);
2461 klass = klass->generic_class->container_class;
2464 for (parent = klass; parent; parent = parent->parent) {
2465 mono_class_setup_interfaces (parent, &error);
2466 if (!mono_error_ok (&error))
2468 collect_interfaces (parent, iface_hash, &error);
2469 if (!mono_error_ok (&error))
2473 data.error = &error;
2474 data.domain = mono_object_domain (type);
2476 len = g_hash_table_size (iface_hash);
2478 g_hash_table_destroy (iface_hash);
2479 if (!data.domain->empty_types) {
2480 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2481 if (!is_ok (&error))
2484 return data.domain->empty_types;
2487 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2488 if (!is_ok (&error))
2490 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2491 if (!mono_error_ok (&error))
2494 g_hash_table_destroy (iface_hash);
2495 return data.iface_array;
2498 g_hash_table_destroy (iface_hash);
2499 mono_error_set_pending_exception (&error);
2504 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2506 gboolean variance_used;
2507 MonoClass *klass = mono_class_from_mono_type (type->type);
2508 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2509 MonoReflectionMethod *member;
2512 int i = 0, len, ioffset;
2516 mono_class_init_checked (klass, &error);
2517 if (mono_error_set_pending_exception (&error))
2519 mono_class_init_checked (iclass, &error);
2520 if (mono_error_set_pending_exception (&error))
2523 mono_class_setup_vtable (klass);
2525 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2529 len = mono_class_num_methods (iclass);
2530 domain = mono_object_domain (type);
2531 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2532 if (mono_error_set_pending_exception (&error))
2534 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2535 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2536 if (mono_error_set_pending_exception (&error))
2538 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2540 while ((method = mono_class_get_methods (iclass, &iter))) {
2541 member = mono_method_get_object_checked (domain, method, iclass, &error);
2542 if (mono_error_set_pending_exception (&error))
2544 mono_array_setref (*methods, i, member);
2545 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2546 if (mono_error_set_pending_exception (&error))
2548 mono_array_setref (*targets, i, member);
2555 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2558 MonoClass *klass = mono_class_from_mono_type (type->type);
2560 mono_class_init_checked (klass, &error);
2561 if (mono_error_set_pending_exception (&error))
2564 if (image_is_dynamic (klass->image)) {
2565 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2566 *packing = tb->packing_size;
2567 *size = tb->class_size;
2569 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2573 ICALL_EXPORT MonoReflectionType*
2574 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2577 MonoReflectionType *ret;
2580 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2581 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2582 mono_error_set_pending_exception (&error);
2586 klass = mono_class_from_mono_type (type->type);
2587 mono_class_init_checked (klass, &error);
2588 if (mono_error_set_pending_exception (&error))
2592 // GetElementType should only return a type for:
2593 // Array Pointer PassedByRef
2594 if (type->type->byref)
2595 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2596 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2597 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2598 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2599 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2603 mono_error_set_pending_exception (&error);
2608 ICALL_EXPORT MonoReflectionType*
2609 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2612 MonoReflectionType *ret;
2614 if (type->type->byref)
2617 MonoClass *klass = mono_class_from_mono_type (type->type);
2621 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2622 mono_error_set_pending_exception (&error);
2627 ICALL_EXPORT MonoBoolean
2628 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2630 return type->type->type == MONO_TYPE_PTR;
2633 ICALL_EXPORT MonoBoolean
2634 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2636 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)));
2639 ICALL_EXPORT MonoBoolean
2640 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2642 return type->type->byref;
2645 ICALL_EXPORT MonoBoolean
2646 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2649 MonoClass *klass = mono_class_from_mono_type (type->type);
2650 mono_class_init_checked (klass, &error);
2651 if (mono_error_set_pending_exception (&error))
2654 return mono_class_is_com_object (klass);
2657 ICALL_EXPORT guint32
2658 ves_icall_reflection_get_token (MonoObject* obj)
2661 guint32 result = mono_reflection_get_token_checked (obj, &error);
2662 mono_error_set_pending_exception (&error);
2666 ICALL_EXPORT MonoReflectionModule*
2667 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2670 MonoReflectionModule *result = NULL;
2671 MonoClass *klass = mono_class_from_mono_type (type->type);
2672 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2673 mono_error_set_pending_exception (&error);
2677 ICALL_EXPORT MonoReflectionAssembly*
2678 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2681 MonoDomain *domain = mono_domain_get ();
2682 MonoClass *klass = mono_class_from_mono_type (type->type);
2683 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2684 mono_error_set_pending_exception (&error);
2688 ICALL_EXPORT MonoReflectionType*
2689 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2692 MonoReflectionType *ret;
2693 MonoDomain *domain = mono_domain_get ();
2696 if (type->type->byref)
2698 if (type->type->type == MONO_TYPE_VAR) {
2699 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2700 klass = param ? param->owner.klass : NULL;
2701 } else if (type->type->type == MONO_TYPE_MVAR) {
2702 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2703 klass = param ? param->owner.method->klass : NULL;
2705 klass = mono_class_from_mono_type (type->type)->nested_in;
2711 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2712 mono_error_set_pending_exception (&error);
2717 ICALL_EXPORT MonoString*
2718 ves_icall_RuntimeType_get_Name (MonoReflectionType *type)
2720 MonoDomain *domain = mono_domain_get ();
2721 MonoClass *klass = mono_class_from_mono_type (type->type);
2723 if (type->type->byref) {
2724 char *n = g_strdup_printf ("%s&", klass->name);
2725 MonoString *res = mono_string_new (domain, n);
2731 return mono_string_new (domain, klass->name);
2735 ICALL_EXPORT MonoString*
2736 ves_icall_RuntimeType_get_Namespace (MonoReflectionType *type)
2738 MonoDomain *domain = mono_domain_get ();
2739 MonoClass *klass = mono_class_from_mono_type (type->type);
2741 while (klass->nested_in)
2742 klass = klass->nested_in;
2744 if (klass->name_space [0] == '\0')
2747 return mono_string_new (domain, klass->name_space);
2751 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2755 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2756 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2760 klass = mono_class_from_mono_type (type->type);
2766 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2768 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2771 ICALL_EXPORT MonoArray*
2772 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2775 MonoReflectionType *rt;
2777 MonoClass *klass, *pklass;
2778 MonoDomain *domain = mono_object_domain (type);
2781 klass = mono_class_from_mono_type (type->type);
2783 if (klass->generic_container) {
2784 MonoGenericContainer *container = klass->generic_container;
2785 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2786 if (mono_error_set_pending_exception (&error))
2788 for (i = 0; i < container->type_argc; ++i) {
2789 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2791 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2792 if (mono_error_set_pending_exception (&error))
2795 mono_array_setref (res, i, rt);
2797 } else if (klass->generic_class) {
2798 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2799 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2800 if (mono_error_set_pending_exception (&error))
2802 for (i = 0; i < inst->type_argc; ++i) {
2803 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2804 if (mono_error_set_pending_exception (&error))
2807 mono_array_setref (res, i, rt);
2815 ICALL_EXPORT gboolean
2816 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2820 if (!IS_MONOTYPE (type))
2823 if (type->type->byref)
2826 klass = mono_class_from_mono_type (type->type);
2827 return klass->generic_container != NULL;
2830 ICALL_EXPORT MonoReflectionType*
2831 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2834 MonoReflectionType *ret;
2837 if (type->type->byref)
2840 klass = mono_class_from_mono_type (type->type);
2842 if (klass->generic_container) {
2843 return type; /* check this one */
2845 if (klass->generic_class) {
2846 MonoClass *generic_class = klass->generic_class->container_class;
2849 tb = mono_class_get_ref_info (generic_class);
2851 if (generic_class->wastypebuilder && tb)
2852 return (MonoReflectionType *)tb;
2854 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2855 mono_error_set_pending_exception (&error);
2863 ICALL_EXPORT MonoReflectionType*
2864 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2867 MonoReflectionType *ret;
2869 MonoType *geninst, **types;
2872 g_assert (IS_MONOTYPE (type));
2873 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2874 if (mono_error_set_pending_exception (&error))
2877 count = mono_array_length (type_array);
2878 types = g_new0 (MonoType *, count);
2880 for (i = 0; i < count; i++) {
2881 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2882 types [i] = t->type;
2885 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2888 mono_error_set_pending_exception (&error);
2892 klass = mono_class_from_mono_type (geninst);
2894 /*we might inflate to the GTD*/
2895 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2896 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2900 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2901 mono_error_set_pending_exception (&error);
2906 ICALL_EXPORT gboolean
2907 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2911 if (!IS_MONOTYPE (type))
2914 if (type->type->byref)
2917 klass = mono_class_from_mono_type (type->type);
2918 return klass->generic_class != NULL || klass->generic_container != NULL;
2922 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2924 if (!IS_MONOTYPE (type))
2927 if (is_generic_parameter (type->type))
2928 return mono_type_get_generic_param_num (type->type);
2932 ICALL_EXPORT MonoGenericParamInfo *
2933 ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionType *type)
2935 return mono_generic_param_info (type->type->data.generic_param);
2938 ICALL_EXPORT MonoBoolean
2939 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2941 return is_generic_parameter (type->type);
2944 ICALL_EXPORT MonoBoolean
2945 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2947 return is_generic_parameter (tb->type.type);
2951 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2952 MonoReflectionType *t)
2954 enumtype->type = t->type;
2957 ICALL_EXPORT MonoReflectionMethod*
2958 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2959 MonoReflectionMethod* generic)
2966 MonoReflectionMethod *ret = NULL;
2968 domain = ((MonoObject *)type)->vtable->domain;
2970 klass = mono_class_from_mono_type (type->type);
2971 mono_class_init_checked (klass, &error);
2972 if (mono_error_set_pending_exception (&error))
2976 while ((method = mono_class_get_methods (klass, &iter))) {
2977 if (method->token == generic->method->token) {
2978 ret = mono_method_get_object_checked (domain, method, klass, &error);
2979 if (mono_error_set_pending_exception (&error))
2987 ICALL_EXPORT MonoReflectionMethod *
2988 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
2991 MonoType *type = ref_type->type;
2993 MonoReflectionMethod *ret = NULL;
2995 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2996 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2999 if (type->type == MONO_TYPE_VAR)
3002 method = mono_type_get_generic_param_owner (type)->owner.method;
3005 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
3006 if (!mono_error_ok (&error))
3007 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3011 ICALL_EXPORT MonoBoolean
3012 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
3014 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3018 ICALL_EXPORT MonoBoolean
3019 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
3021 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3026 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
3028 MonoDomain *domain = mono_domain_get ();
3029 MonoImage *image = method->method->klass->image;
3030 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
3031 MonoTableInfo *tables = image->tables;
3032 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
3033 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
3034 guint32 im_cols [MONO_IMPLMAP_SIZE];
3035 guint32 scope_token;
3036 const char *import = NULL;
3037 const char *scope = NULL;
3039 if (image_is_dynamic (image)) {
3040 MonoReflectionMethodAux *method_aux =
3041 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
3043 import = method_aux->dllentry;
3044 scope = method_aux->dll;
3047 if (!import || !scope) {
3048 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
3053 if (piinfo->implmap_idx) {
3054 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
3056 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
3057 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
3058 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
3059 scope = mono_metadata_string_heap (image, scope_token);
3063 *flags = piinfo->piflags;
3064 *entry_point = mono_string_new (domain, import);
3065 *dll_name = mono_string_new (domain, scope);
3068 ICALL_EXPORT MonoReflectionMethod *
3069 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3071 MonoMethodInflated *imethod;
3073 MonoReflectionMethod *ret = NULL;
3076 if (method->method->is_generic)
3079 if (!method->method->is_inflated)
3082 imethod = (MonoMethodInflated *) method->method;
3084 result = imethod->declaring;
3085 /* Not a generic method. */
3086 if (!result->is_generic)
3089 if (image_is_dynamic (method->method->klass->image)) {
3090 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3091 MonoReflectionMethod *res;
3094 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3095 * the dynamic case as well ?
3097 mono_image_lock ((MonoImage*)image);
3098 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3099 mono_image_unlock ((MonoImage*)image);
3105 if (imethod->context.class_inst) {
3106 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3107 /*Generic methods gets the context of the GTD.*/
3108 if (mono_class_get_context (klass)) {
3109 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3110 if (!mono_error_ok (&error))
3115 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3117 if (!mono_error_ok (&error))
3118 mono_error_set_pending_exception (&error);
3122 ICALL_EXPORT gboolean
3123 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3125 return mono_method_signature (method->method)->generic_param_count != 0;
3128 ICALL_EXPORT gboolean
3129 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3131 return method->method->is_generic;
3134 ICALL_EXPORT MonoArray*
3135 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3138 MonoReflectionType *rt;
3143 domain = mono_object_domain (method);
3145 if (method->method->is_inflated) {
3146 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3149 count = inst->type_argc;
3150 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3151 if (mono_error_set_pending_exception (&error))
3154 for (i = 0; i < count; i++) {
3155 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3156 if (mono_error_set_pending_exception (&error))
3159 mono_array_setref (res, i, rt);
3166 count = mono_method_signature (method->method)->generic_param_count;
3167 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3168 if (mono_error_set_pending_exception (&error))
3171 for (i = 0; i < count; i++) {
3172 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3173 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3174 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3176 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3177 if (mono_error_set_pending_exception (&error))
3180 mono_array_setref (res, i, rt);
3186 ICALL_EXPORT MonoObject *
3187 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3191 * Invoke from reflection is supposed to always be a virtual call (the API
3192 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3193 * greater flexibility.
3195 MonoMethod *m = method->method;
3196 MonoMethodSignature *sig = mono_method_signature (m);
3199 void *obj = this_arg;
3203 if (mono_security_core_clr_enabled () &&
3204 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3205 mono_error_set_pending_exception (&error);
3209 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3210 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3211 mono_error_cleanup (&error); /* FIXME does this make sense? */
3212 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3217 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3218 if (!is_ok (&error)) {
3219 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3222 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3223 char *target_name = mono_type_get_full_name (m->klass);
3224 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3225 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3227 g_free (target_name);
3231 m = mono_object_get_virtual_method (this_arg, m);
3232 /* must pass the pointer to the value for valuetype methods */
3233 if (m->klass->valuetype)
3234 obj = mono_object_unbox (this_arg);
3235 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3236 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3241 if (sig->ret->byref) {
3242 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"));
3246 pcount = params? mono_array_length (params): 0;
3247 if (pcount != sig->param_count) {
3248 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3252 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3253 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."));
3257 image = m->klass->image;
3258 if (image->assembly->ref_only) {
3259 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."));
3263 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3264 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3268 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3272 intptr_t *lower_bounds;
3273 pcount = mono_array_length (params);
3274 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3275 /* Note: the synthetized array .ctors have int32 as argument type */
3276 for (i = 0; i < pcount; ++i)
3277 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3279 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3280 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3281 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3282 if (!mono_error_ok (&error)) {
3283 mono_error_set_pending_exception (&error);
3287 for (i = 0; i < mono_array_length (arr); ++i) {
3288 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3289 if (!mono_error_ok (&error)) {
3290 mono_error_set_pending_exception (&error);
3293 mono_array_setref_fast (arr, i, subarray);
3295 return (MonoObject*)arr;
3298 if (m->klass->rank == pcount) {
3299 /* Only lengths provided. */
3300 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3301 if (!mono_error_ok (&error)) {
3302 mono_error_set_pending_exception (&error);
3306 return (MonoObject*)arr;
3308 g_assert (pcount == (m->klass->rank * 2));
3309 /* The arguments are lower-bound-length pairs */
3310 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3312 for (i = 0; i < pcount / 2; ++i) {
3313 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3314 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3317 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3318 if (!mono_error_ok (&error)) {
3319 mono_error_set_pending_exception (&error);
3323 return (MonoObject*)arr;
3326 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3327 mono_error_set_pending_exception (&error);
3331 #ifndef DISABLE_REMOTING
3332 ICALL_EXPORT MonoObject *
3333 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3336 MonoDomain *domain = mono_object_domain (method);
3337 MonoMethod *m = method->method;
3338 MonoMethodSignature *sig = mono_method_signature (m);
3339 MonoArray *out_args;
3341 int i, j, outarg_count = 0;
3343 if (m->klass == mono_defaults.object_class) {
3344 if (!strcmp (m->name, "FieldGetter")) {
3345 MonoClass *k = this_arg->vtable->klass;
3349 /* If this is a proxy, then it must be a CBO */
3350 if (k == mono_defaults.transparent_proxy_class) {
3351 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3352 this_arg = tp->rp->unwrapped_server;
3353 g_assert (this_arg);
3354 k = this_arg->vtable->klass;
3357 name = mono_array_get (params, MonoString *, 1);
3358 str = mono_string_to_utf8_checked (name, &error);
3359 if (mono_error_set_pending_exception (&error))
3363 MonoClassField* field = mono_class_get_field_from_name (k, str);
3366 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3367 if (field_klass->valuetype) {
3368 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3369 if (mono_error_set_pending_exception (&error))
3372 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3374 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3375 if (mono_error_set_pending_exception (&error))
3377 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3378 mono_array_setref (out_args, 0, result);
3385 g_assert_not_reached ();
3387 } else if (!strcmp (m->name, "FieldSetter")) {
3388 MonoClass *k = this_arg->vtable->klass;
3394 /* If this is a proxy, then it must be a CBO */
3395 if (k == mono_defaults.transparent_proxy_class) {
3396 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3397 this_arg = tp->rp->unwrapped_server;
3398 g_assert (this_arg);
3399 k = this_arg->vtable->klass;
3402 name = mono_array_get (params, MonoString *, 1);
3403 str = mono_string_to_utf8_checked (name, &error);
3404 if (mono_error_set_pending_exception (&error))
3408 MonoClassField* field = mono_class_get_field_from_name (k, str);
3411 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3412 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3414 if (field_klass->valuetype) {
3415 size = mono_type_size (field->type, &align);
3416 g_assert (size == mono_class_value_size (field_klass, NULL));
3417 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3419 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3422 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3423 if (mono_error_set_pending_exception (&error))
3425 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3434 g_assert_not_reached ();
3439 for (i = 0; i < mono_array_length (params); i++) {
3440 if (sig->params [i]->byref)
3444 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3445 if (mono_error_set_pending_exception (&error))
3448 /* handle constructors only for objects already allocated */
3449 if (!strcmp (method->method->name, ".ctor"))
3450 g_assert (this_arg);
3452 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3453 g_assert (!method->method->klass->valuetype);
3454 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3455 if (mono_error_set_pending_exception (&error))
3458 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3459 if (sig->params [i]->byref) {
3461 arg = mono_array_get (params, gpointer, i);
3462 mono_array_setref (out_args, j, arg);
3467 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3474 read_enum_value (const char *mem, int type)
3477 case MONO_TYPE_BOOLEAN:
3479 return *(guint8*)mem;
3481 return *(gint8*)mem;
3482 case MONO_TYPE_CHAR:
3484 return read16 (mem);
3486 return (gint16) read16 (mem);
3488 return read32 (mem);
3490 return (gint32) read32 (mem);
3493 return read64 (mem);
3495 g_assert_not_reached ();
3501 write_enum_value (char *mem, int type, guint64 value)
3505 case MONO_TYPE_I1: {
3506 guint8 *p = (guint8*)mem;
3512 case MONO_TYPE_CHAR: {
3513 guint16 *p = (guint16 *)mem;
3518 case MONO_TYPE_I4: {
3519 guint32 *p = (guint32 *)mem;
3524 case MONO_TYPE_I8: {
3525 guint64 *p = (guint64 *)mem;
3530 g_assert_not_reached ();
3535 ICALL_EXPORT MonoObject *
3536 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3544 domain = mono_object_domain (enumType);
3545 enumc = mono_class_from_mono_type (enumType->type);
3547 mono_class_init_checked (enumc, &error);
3548 if (mono_error_set_pending_exception (&error))
3551 etype = mono_class_enum_basetype (enumc);
3553 res = mono_object_new_checked (domain, enumc, &error);
3554 if (mono_error_set_pending_exception (&error))
3556 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3561 ICALL_EXPORT MonoBoolean
3562 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3564 int size = mono_class_value_size (a->vtable->klass, NULL);
3565 guint64 a_val = 0, b_val = 0;
3567 memcpy (&a_val, mono_object_unbox (a), size);
3568 memcpy (&b_val, mono_object_unbox (b), size);
3570 return (a_val & b_val) == b_val;
3573 ICALL_EXPORT MonoObject *
3574 ves_icall_System_Enum_get_value (MonoObject *eobj)
3586 g_assert (eobj->vtable->klass->enumtype);
3588 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3589 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3590 if (mono_error_set_pending_exception (&error))
3592 dst = (char *)res + sizeof (MonoObject);
3593 src = (char *)eobj + sizeof (MonoObject);
3594 size = mono_class_value_size (enumc, NULL);
3596 memcpy (dst, src, size);
3601 ICALL_EXPORT MonoReflectionType *
3602 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3605 MonoReflectionType *ret;
3609 klass = mono_class_from_mono_type (type->type);
3610 mono_class_init_checked (klass, &error);
3611 if (mono_error_set_pending_exception (&error))
3614 etype = mono_class_enum_basetype (klass);
3616 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3620 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3621 mono_error_set_pending_exception (&error);
3627 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3629 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3630 gpointer odata = (char *)other + sizeof (MonoObject);
3631 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3632 g_assert (basetype);
3637 if (eobj->vtable->klass != other->vtable->klass)
3640 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3641 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3642 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3645 return me > other ? 1 : -1; \
3648 switch (basetype->type) {
3650 COMPARE_ENUM_VALUES (guint8);
3652 COMPARE_ENUM_VALUES (gint8);
3653 case MONO_TYPE_CHAR:
3655 COMPARE_ENUM_VALUES (guint16);
3657 COMPARE_ENUM_VALUES (gint16);
3659 COMPARE_ENUM_VALUES (guint32);
3661 COMPARE_ENUM_VALUES (gint32);
3663 COMPARE_ENUM_VALUES (guint64);
3665 COMPARE_ENUM_VALUES (gint64);
3669 #undef COMPARE_ENUM_VALUES
3670 /* indicates that the enum was of an unsupported unerlying type */
3675 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3677 gpointer data = (char *)eobj + sizeof (MonoObject);
3678 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3679 g_assert (basetype);
3681 switch (basetype->type) {
3682 case MONO_TYPE_I1: {
3683 gint8 value = *((gint8*)data);
3684 return ((int)value ^ (int)value << 8);
3687 return *((guint8*)data);
3688 case MONO_TYPE_CHAR:
3690 return *((guint16*)data);
3692 case MONO_TYPE_I2: {
3693 gint16 value = *((gint16*)data);
3694 return ((int)(guint16)value | (((int)value) << 16));
3697 return *((guint32*)data);
3699 return *((gint32*)data);
3701 case MONO_TYPE_I8: {
3702 gint64 value = *((gint64*)data);
3703 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3706 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3711 ICALL_EXPORT MonoBoolean
3712 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3715 MonoDomain *domain = mono_object_domain (type);
3716 MonoClass *enumc = mono_class_from_mono_type (type->type);
3717 guint j = 0, nvalues;
3719 MonoClassField *field;
3721 guint64 field_value, previous_value = 0;
3722 gboolean sorted = TRUE;
3724 mono_class_init_checked (enumc, &error);
3725 if (mono_error_set_pending_exception (&error))
3729 if (!enumc->enumtype) {
3730 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3734 base_type = mono_class_enum_basetype (enumc)->type;
3736 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3737 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3738 if (mono_error_set_pending_exception (&error))
3740 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3741 if (mono_error_set_pending_exception (&error))
3745 while ((field = mono_class_get_fields (enumc, &iter))) {
3747 MonoTypeEnum def_type;
3749 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3751 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3753 if (mono_field_is_deleted (field))
3755 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3757 p = mono_class_get_field_default_value (field, &def_type);
3758 /* len = */ mono_metadata_decode_blob_size (p, &p);
3760 field_value = read_enum_value (p, base_type);
3761 mono_array_set (*values, guint64, j, field_value);
3763 if (previous_value > field_value)
3766 previous_value = field_value;
3774 BFLAGS_IgnoreCase = 1,
3775 BFLAGS_DeclaredOnly = 2,
3776 BFLAGS_Instance = 4,
3778 BFLAGS_Public = 0x10,
3779 BFLAGS_NonPublic = 0x20,
3780 BFLAGS_FlattenHierarchy = 0x40,
3781 BFLAGS_InvokeMethod = 0x100,
3782 BFLAGS_CreateInstance = 0x200,
3783 BFLAGS_GetField = 0x400,
3784 BFLAGS_SetField = 0x800,
3785 BFLAGS_GetProperty = 0x1000,
3786 BFLAGS_SetProperty = 0x2000,
3787 BFLAGS_ExactBinding = 0x10000,
3788 BFLAGS_SuppressChangeType = 0x20000,
3789 BFLAGS_OptionalParamBinding = 0x40000
3792 ICALL_EXPORT GPtrArray*
3793 ves_icall_RuntimeType_GetFields_native (MonoReflectionType *type, MonoString *name, guint32 bflags)
3797 MonoClass *startklass, *klass;
3800 char *utf8_name = NULL;
3801 int (*compare_func) (const char *s1, const char *s2) = NULL;
3802 MonoClassField *field;
3804 domain = ((MonoObject *)type)->vtable->domain;
3805 if (type->type->byref) {
3806 return g_ptr_array_new ();
3809 klass = startklass = mono_class_from_mono_type (type->type);
3811 GPtrArray *ptr_array = g_ptr_array_sized_new (16);
3814 if (mono_class_has_failure (klass)) {
3815 mono_error_init (&error);
3816 mono_error_set_for_class_failure (&error, klass);
3821 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3822 guint32 flags = mono_field_get_flags (field);
3824 if (mono_field_is_deleted_with_flags (field, flags))
3826 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3827 if (bflags & BFLAGS_Public)
3829 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3830 if (bflags & BFLAGS_NonPublic) {
3837 if (flags & FIELD_ATTRIBUTE_STATIC) {
3838 if (bflags & BFLAGS_Static)
3839 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3842 if (bflags & BFLAGS_Instance)
3850 if (utf8_name == NULL) {
3851 utf8_name = mono_string_to_utf8_checked (name, &error);
3852 if (!is_ok (&error))
3854 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3857 if (compare_func (mono_field_get_name (field), utf8_name))
3861 g_ptr_array_add (ptr_array, field);
3863 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3866 if (utf8_name != NULL)
3871 g_ptr_array_free (ptr_array, FALSE);
3872 mono_error_set_pending_exception (&error);
3877 method_nonpublic (MonoMethod* method, gboolean start_klass)
3879 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3880 case METHOD_ATTRIBUTE_ASSEM:
3881 return (start_klass || mono_defaults.generic_ilist_class);
3882 case METHOD_ATTRIBUTE_PRIVATE:
3884 case METHOD_ATTRIBUTE_PUBLIC:
3892 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoError *error)
3895 MonoClass *startklass;
3899 /*FIXME, use MonoBitSet*/
3900 guint32 method_slots_default [8];
3901 guint32 *method_slots = NULL;
3902 int (*compare_func) (const char *s1, const char *s2) = NULL;
3904 array = g_ptr_array_new ();
3906 mono_error_init (error);
3909 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3911 /* An optimization for calls made from Delegate:CreateDelegate () */
3912 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3913 method = mono_get_delegate_invoke (klass);
3916 g_ptr_array_add (array, method);
3920 mono_class_setup_methods (klass);
3921 mono_class_setup_vtable (klass);
3922 if (mono_class_has_failure (klass))
3925 if (is_generic_parameter (&klass->byval_arg))
3926 nslots = mono_class_get_vtable_size (klass->parent);
3928 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3929 if (nslots >= sizeof (method_slots_default) * 8) {
3930 method_slots = g_new0 (guint32, nslots / 32 + 1);
3932 method_slots = method_slots_default;
3933 memset (method_slots, 0, sizeof (method_slots_default));
3936 mono_class_setup_methods (klass);
3937 mono_class_setup_vtable (klass);
3938 if (mono_class_has_failure (klass))
3942 while ((method = mono_class_get_methods (klass, &iter))) {
3944 if (method->slot != -1) {
3945 g_assert (method->slot < nslots);
3946 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3948 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3949 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3952 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3954 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3955 if (bflags & BFLAGS_Public)
3957 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3963 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3964 if (bflags & BFLAGS_Static)
3965 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3968 if (bflags & BFLAGS_Instance)
3976 if (compare_func (name, method->name))
3981 g_ptr_array_add (array, method);
3983 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3985 if (method_slots != method_slots_default)
3986 g_free (method_slots);
3991 if (method_slots != method_slots_default)
3992 g_free (method_slots);
3993 g_ptr_array_free (array, TRUE);
3995 g_assert (mono_class_has_failure (klass));
3996 mono_error_set_for_class_failure (error, klass);
4000 ICALL_EXPORT GPtrArray*
4001 ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case)
4005 const char *mname = NULL;
4006 GPtrArray *method_array;
4009 klass = mono_class_from_mono_type (type->type);
4010 domain = ((MonoObject *)type)->vtable->domain;
4011 if (type->type->byref) {
4012 return g_ptr_array_new ();
4016 mname = mono_string_to_utf8_checked (name, &error);
4017 if (mono_error_set_pending_exception (&error))
4021 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &error);
4022 g_free ((char*)mname);
4023 mono_error_set_pending_exception (&error);
4024 return method_array;
4027 ICALL_EXPORT GPtrArray*
4028 ves_icall_RuntimeType_GetConstructors_native (MonoReflectionType *type, guint32 bflags)
4030 MonoClass *startklass, *klass;
4033 gpointer iter = NULL;
4034 GPtrArray *res_array;
4037 if (type->type->byref) {
4038 return g_ptr_array_new ();
4041 klass = startklass = mono_class_from_mono_type (type->type);
4043 mono_class_setup_methods (klass);
4044 if (mono_class_has_failure (klass)) {
4045 mono_error_init (&error);
4046 mono_error_set_for_class_failure (&error, klass);
4047 mono_error_set_pending_exception (&error);
4051 res_array = g_ptr_array_sized_new (4); /* FIXME, guestimating */
4054 while ((method = mono_class_get_methods (klass, &iter))) {
4056 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
4058 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4059 if (bflags & BFLAGS_Public)
4062 if (bflags & BFLAGS_NonPublic)
4068 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4069 if (bflags & BFLAGS_Static)
4070 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4073 if (bflags & BFLAGS_Instance)
4079 g_ptr_array_add (res_array, method);
4086 property_hash (gconstpointer data)
4088 MonoProperty *prop = (MonoProperty*)data;
4090 return g_str_hash (prop->name);
4094 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
4096 if (method1->slot != -1 && method1->slot == method2->slot)
4099 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
4100 if (method1->is_inflated)
4101 method1 = ((MonoMethodInflated*) method1)->declaring;
4102 if (method2->is_inflated)
4103 method2 = ((MonoMethodInflated*) method2)->declaring;
4106 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4110 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4112 // Properties are hide-by-name-and-signature
4113 if (!g_str_equal (prop1->name, prop2->name))
4116 /* If we see a property in a generic method, we want to
4117 compare the generic signatures, not the inflated signatures
4118 because we might conflate two properties that were
4122 public T this[T t] { getter { return t; } } // method 1
4123 public U this[U u] { getter { return u; } } // method 2
4126 If we see int Foo<int,int>::Item[int] we need to know if
4127 the indexer came from method 1 or from method 2, and we
4128 shouldn't conflate them. (Bugzilla 36283)
4130 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4133 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4140 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4145 return method_nonpublic (accessor, start_klass);
4148 ICALL_EXPORT GPtrArray*
4149 ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case)
4152 MonoClass *startklass, *klass;
4157 gchar *propname = NULL;
4158 int (*compare_func) (const char *s1, const char *s2) = NULL;
4160 GHashTable *properties = NULL;
4161 GPtrArray *res_array;
4163 if (type->type->byref) {
4164 return g_ptr_array_new ();
4167 mono_error_init (&error);
4169 klass = startklass = mono_class_from_mono_type (type->type);
4172 propname = mono_string_to_utf8_checked (name, &error);
4173 if (mono_error_set_pending_exception (&error))
4175 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4178 res_array = g_ptr_array_sized_new (8); /*This the average for ASP.NET types*/
4180 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4182 mono_class_setup_methods (klass);
4183 mono_class_setup_vtable (klass);
4184 if (mono_class_has_failure (klass))
4188 while ((prop = mono_class_get_properties (klass, &iter))) {
4194 flags = method->flags;
4197 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4198 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4199 if (bflags & BFLAGS_Public)
4201 } else if (bflags & BFLAGS_NonPublic) {
4202 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4203 property_accessor_nonpublic(prop->set, startklass == klass)) {
4210 if (flags & METHOD_ATTRIBUTE_STATIC) {
4211 if (bflags & BFLAGS_Static)
4212 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4215 if (bflags & BFLAGS_Instance)
4224 if (compare_func (propname, prop->name))
4228 if (g_hash_table_lookup (properties, prop))
4231 g_ptr_array_add (res_array, prop);
4233 g_hash_table_insert (properties, prop, prop);
4235 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4238 g_hash_table_destroy (properties);
4245 if (mono_class_has_failure (klass))
4246 mono_error_set_for_class_failure (&error, klass);
4249 g_hash_table_destroy (properties);
4252 g_ptr_array_free (res_array, FALSE);
4254 mono_error_set_pending_exception (&error);
4260 event_hash (gconstpointer data)
4262 MonoEvent *event = (MonoEvent*)data;
4264 return g_str_hash (event->name);
4268 event_equal (MonoEvent *event1, MonoEvent *event2)
4270 // Events are hide-by-name
4271 return g_str_equal (event1->name, event2->name);
4274 ICALL_EXPORT GPtrArray*
4275 ves_icall_RuntimeType_GetEvents_native (MonoReflectionType *type, MonoString *name, guint32 bflags)
4278 MonoClass *startklass, *klass;
4283 char *utf8_name = NULL;
4284 int (*compare_func) (const char *s1, const char *s2) = NULL;
4285 GHashTable *events = NULL;
4286 GPtrArray *res_array;
4288 if (type->type->byref) {
4289 return g_ptr_array_new ();
4292 mono_error_init (&error);
4294 res_array = g_ptr_array_sized_new (4);
4296 klass = startklass = mono_class_from_mono_type (type->type);
4298 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4300 mono_class_setup_methods (klass);
4301 mono_class_setup_vtable (klass);
4302 if (mono_class_has_failure (klass))
4306 while ((event = mono_class_get_events (klass, &iter))) {
4308 method = event->add;
4310 method = event->remove;
4312 method = event->raise;
4314 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4315 if (bflags & BFLAGS_Public)
4317 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4318 if (bflags & BFLAGS_NonPublic)
4323 if (bflags & BFLAGS_NonPublic)
4329 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4330 if (bflags & BFLAGS_Static)
4331 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4334 if (bflags & BFLAGS_Instance)
4339 if (bflags & BFLAGS_Instance)
4345 if (utf8_name == NULL) {
4346 utf8_name = mono_string_to_utf8_checked (name, &error);
4347 if (!is_ok (&error))
4349 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4352 if (compare_func (event->name, utf8_name))
4356 if (g_hash_table_lookup (events, event))
4359 g_ptr_array_add (res_array, event);
4361 g_hash_table_insert (events, event, event);
4363 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4366 g_hash_table_destroy (events);
4368 if (utf8_name != NULL)
4374 if (mono_class_has_failure (klass))
4375 mono_error_set_for_class_failure (&error, klass);
4380 g_hash_table_destroy (events);
4381 if (utf8_name != NULL)
4384 g_ptr_array_free (res_array, FALSE);
4386 mono_error_set_pending_exception (&error);
4390 ICALL_EXPORT MonoArray*
4391 ves_icall_RuntimeType_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4394 MonoReflectionType *rt;
4397 MonoArray *res = NULL;
4402 MonoPtrArray tmp_array;
4404 mono_error_init (&error);
4406 domain = ((MonoObject *)type)->vtable->domain;
4407 if (type->type->byref) {
4408 MonoArray *result = mono_array_new_cached (domain, mono_defaults.runtimetype_class, 0, &error);
4409 mono_error_set_pending_exception (&error);
4412 klass = mono_class_from_mono_type (type->type);
4415 * If a nested type is generic, return its generic type definition.
4416 * Note that this means that the return value is essentially the set
4417 * of nested types of the generic type definition of @klass.
4419 * A note in MSDN claims that a generic type definition can have
4420 * nested types that aren't generic. In any case, the container of that
4421 * nested type would be the generic type definition.
4423 if (klass->generic_class)
4424 klass = klass->generic_class->container_class;
4426 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4428 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4430 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4431 if (bflags & BFLAGS_Public)
4434 if (bflags & BFLAGS_NonPublic)
4442 str = mono_string_to_utf8_checked (name, &error);
4443 if (!is_ok (&error))
4445 mono_identifier_unescape_type_name_chars (str);
4448 if (strcmp (nested->name, str))
4452 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4453 if (!is_ok (&error))
4456 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4459 res = mono_array_new_cached (domain, mono_defaults.runtimetype_class, mono_ptr_array_size (tmp_array), &error);
4460 if (!is_ok (&error))
4463 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4464 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4467 mono_ptr_array_destroy (tmp_array);
4471 mono_error_set_pending_exception (&error);
4475 ICALL_EXPORT MonoReflectionType*
4476 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4479 MonoReflectionType *ret;
4481 MonoType *type = NULL;
4482 MonoTypeNameParse info;
4483 gboolean type_resolve;
4485 /* On MS.NET, this does not fire a TypeResolve event */
4486 type_resolve = TRUE;
4487 str = mono_string_to_utf8_checked (name, &error);
4488 if (mono_error_set_pending_exception (&error))
4490 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4491 if (!mono_reflection_parse_type (str, &info)) {
4493 mono_reflection_free_type_info (&info);
4495 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4498 /*g_print ("failed parse\n");*/
4502 if (info.assembly.name) {
4504 mono_reflection_free_type_info (&info);
4506 /* 1.0 and 2.0 throw different exceptions */
4507 if (mono_defaults.generic_ilist_class)
4508 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4510 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4516 if (module != NULL) {
4517 if (module->image) {
4518 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4519 if (!is_ok (&error)) {
4521 mono_reflection_free_type_info (&info);
4522 mono_error_set_pending_exception (&error);
4529 if (assembly_is_dynamic (assembly->assembly)) {
4530 /* Enumerate all modules */
4531 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4535 if (abuilder->modules) {
4536 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4537 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4538 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4539 if (!is_ok (&error)) {
4541 mono_reflection_free_type_info (&info);
4542 mono_error_set_pending_exception (&error);
4550 if (!type && abuilder->loaded_modules) {
4551 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4552 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4553 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4554 if (!is_ok (&error)) {
4556 mono_reflection_free_type_info (&info);
4557 mono_error_set_pending_exception (&error);
4566 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4567 if (!is_ok (&error)) {
4569 mono_reflection_free_type_info (&info);
4570 mono_error_set_pending_exception (&error);
4575 mono_reflection_free_type_info (&info);
4577 MonoException *e = NULL;
4580 e = mono_get_exception_type_load (name, NULL);
4583 mono_set_pending_exception (e);
4587 if (type->type == MONO_TYPE_CLASS) {
4588 MonoClass *klass = mono_type_get_class (type);
4590 /* need to report exceptions ? */
4591 if (throwOnError && mono_class_has_failure (klass)) {
4592 /* report SecurityException (or others) that occured when loading the assembly */
4593 MonoException *exc = mono_class_get_exception_for_failure (klass);
4594 mono_set_pending_exception (exc);
4599 /* g_print ("got it\n"); */
4600 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4601 mono_error_set_pending_exception (&error);
4607 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4610 gchar *shadow_ini_file;
4613 /* Check for shadow-copied assembly */
4614 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4615 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4617 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4618 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4624 g_free (shadow_ini_file);
4625 if (content != NULL) {
4628 *filename = content;
4635 ICALL_EXPORT MonoString *
4636 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4638 MonoDomain *domain = mono_object_domain (assembly);
4639 MonoAssembly *mass = assembly->assembly;
4640 MonoString *res = NULL;
4645 if (g_path_is_absolute (mass->image->name)) {
4646 absolute = g_strdup (mass->image->name);
4647 dirname = g_path_get_dirname (absolute);
4649 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4650 dirname = g_strdup (mass->basedir);
4653 replace_shadow_path (domain, dirname, &absolute);
4658 for (i = strlen (absolute) - 1; i >= 0; i--)
4659 if (absolute [i] == '\\')
4664 uri = g_filename_to_uri (absolute, NULL, NULL);
4666 const char *prepend = "file://";
4668 if (*absolute == '/' && *(absolute + 1) == '/') {
4671 prepend = "file:///";
4674 uri = g_strconcat (prepend, absolute, NULL);
4678 res = mono_string_new (domain, uri);
4685 ICALL_EXPORT MonoBoolean
4686 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4688 MonoAssembly *mass = assembly->assembly;
4690 return mass->in_gac;
4693 ICALL_EXPORT MonoReflectionAssembly*
4694 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4699 MonoImageOpenStatus status;
4700 MonoReflectionAssembly* result = NULL;
4702 name = mono_string_to_utf8_checked (mname, &error);
4703 if (mono_error_set_pending_exception (&error))
4705 res = mono_assembly_load_with_partial_name (name, &status);
4711 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4713 mono_error_set_pending_exception (&error);
4717 ICALL_EXPORT MonoString *
4718 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4720 MonoDomain *domain = mono_object_domain (assembly);
4723 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4728 ICALL_EXPORT MonoBoolean
4729 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4731 return assembly->assembly->ref_only;
4734 ICALL_EXPORT MonoString *
4735 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4737 MonoDomain *domain = mono_object_domain (assembly);
4739 return mono_string_new (domain, assembly->assembly->image->version);
4742 ICALL_EXPORT MonoReflectionMethod*
4743 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4746 MonoReflectionMethod *res = NULL;
4749 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4753 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4754 if (!mono_error_ok (&error))
4757 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4760 if (!mono_error_ok (&error))
4761 mono_error_set_pending_exception (&error);
4765 ICALL_EXPORT MonoReflectionModule*
4766 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4769 MonoReflectionModule *result = NULL;
4770 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4771 if (!mono_error_ok (&error))
4772 mono_error_set_pending_exception (&error);
4776 ICALL_EXPORT MonoArray*
4777 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4780 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4781 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4782 if (mono_error_set_pending_exception (&error))
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));
4794 ICALL_EXPORT MonoString*
4795 ves_icall_System_Reflection_Assembly_GetAotId ()
4798 guint8 aotid_sum = 0;
4799 MonoDomain* domain = mono_domain_get ();
4801 if (!domain->entry_assembly || !domain->entry_assembly->image)
4804 guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
4806 for (i = 0; i < 16; ++i)
4807 aotid_sum |= (*aotid)[i];
4812 return mono_string_new (domain, mono_guid_to_string((guint8*) aotid));
4816 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4818 static MonoMethod *create_version = NULL;
4822 mono_error_init (error);
4825 if (!create_version) {
4826 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4827 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4828 g_assert (create_version);
4829 mono_method_desc_free (desc);
4835 args [3] = &revision;
4836 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4837 return_val_if_nok (error, NULL);
4839 mono_runtime_invoke_checked (create_version, result, args, error);
4840 return_val_if_nok (error, NULL);
4845 ICALL_EXPORT MonoArray*
4846 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4850 MonoDomain *domain = mono_object_domain (assembly);
4852 static MonoMethod *create_culture = NULL;
4853 MonoImage *image = assembly->assembly->image;
4857 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4860 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4861 if (mono_error_set_pending_exception (&error))
4865 if (count > 0 && !create_culture) {
4866 MonoMethodDesc *desc = mono_method_desc_new (
4867 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4868 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4869 g_assert (create_culture);
4870 mono_method_desc_free (desc);
4873 for (i = 0; i < count; i++) {
4874 MonoObject *version;
4875 MonoReflectionAssemblyName *aname;
4876 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4878 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4880 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4881 domain, mono_class_get_assembly_name_class (), &error);
4882 if (mono_error_set_pending_exception (&error))
4885 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4887 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4888 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4889 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4890 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4891 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4892 aname->versioncompat = 1; /* SameMachine (default) */
4893 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4895 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4896 if (mono_error_set_pending_exception (&error))
4899 MONO_OBJECT_SETREF (aname, version, version);
4901 if (create_culture) {
4903 MonoBoolean assembly_ref = 1;
4904 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4905 args [1] = &assembly_ref;
4907 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4908 if (mono_error_set_pending_exception (&error))
4911 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4914 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4915 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4916 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4918 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4919 /* public key token isn't copied - the class library will
4920 automatically generate it from the public key if required */
4921 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4922 if (mono_error_set_pending_exception (&error))
4925 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4926 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4928 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4929 if (mono_error_set_pending_exception (&error))
4932 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4933 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
4936 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
4937 if (mono_error_set_pending_exception (&error))
4940 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4943 /* note: this function doesn't return the codebase on purpose (i.e. it can
4944 be used under partial trust as path information isn't present). */
4946 mono_array_setref (result, i, aname);
4951 /* move this in some file in mono/util/ */
4953 g_concat_dir_and_file (const char *dir, const char *file)
4955 g_return_val_if_fail (dir != NULL, NULL);
4956 g_return_val_if_fail (file != NULL, NULL);
4959 * If the directory name doesn't have a / on the end, we need
4960 * to add one so we get a proper path to the file
4962 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4963 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4965 return g_strconcat (dir, file, NULL);
4969 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4972 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4974 guint32 cols [MONO_MANIFEST_SIZE];
4975 guint32 impl, file_idx;
4979 char *n = mono_string_to_utf8_checked (name, &error);
4980 if (mono_error_set_pending_exception (&error))
4983 for (i = 0; i < table->rows; ++i) {
4984 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4985 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4986 if (strcmp (val, n) == 0)
4990 if (i == table->rows)
4993 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4996 * this code should only be called after obtaining the
4997 * ResourceInfo and handling the other cases.
4999 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
5000 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
5002 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
5007 module = assembly->assembly->image;
5010 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
5011 if (mono_error_set_pending_exception (&error))
5013 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
5015 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
5018 ICALL_EXPORT gboolean
5019 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
5022 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5024 guint32 cols [MONO_MANIFEST_SIZE];
5025 guint32 file_cols [MONO_FILE_SIZE];
5029 n = mono_string_to_utf8_checked (name, &error);
5030 if (mono_error_set_pending_exception (&error))
5032 for (i = 0; i < table->rows; ++i) {
5033 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5034 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5035 if (strcmp (val, n) == 0)
5039 if (i == table->rows)
5042 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
5043 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
5046 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
5047 case MONO_IMPLEMENTATION_FILE:
5048 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5049 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5050 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
5051 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
5052 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
5053 if (file_cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA)
5056 info->location = RESOURCE_LOCATION_EMBEDDED;
5059 case MONO_IMPLEMENTATION_ASSEMBLYREF:
5060 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5061 mono_assembly_load_reference (assembly->assembly->image, i - 1);
5062 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
5063 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
5064 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
5066 mono_set_pending_exception (ex);
5069 MonoReflectionAssembly *assm_obj;
5070 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5072 mono_error_set_pending_exception (&error);
5075 MONO_OBJECT_SETREF (info, assembly, assm_obj);
5077 /* Obtain info recursively */
5078 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5079 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5082 case MONO_IMPLEMENTATION_EXP_TYPE:
5083 g_assert_not_reached ();
5091 ICALL_EXPORT MonoObject*
5092 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
5095 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5096 MonoArray *result = NULL;
5101 /* check hash if needed */
5103 n = mono_string_to_utf8_checked (name, &error);
5104 if (mono_error_set_pending_exception (&error))
5107 for (i = 0; i < table->rows; ++i) {
5108 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5109 if (strcmp (val, n) == 0) {
5112 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5113 fn = mono_string_new (mono_object_domain (assembly), n);
5115 return (MonoObject*)fn;
5123 for (i = 0; i < table->rows; ++i) {
5124 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5128 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
5129 if (mono_error_set_pending_exception (&error))
5134 for (i = 0; i < table->rows; ++i) {
5135 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5136 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5137 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5138 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5143 return (MonoObject*)result;
5146 ICALL_EXPORT MonoArray*
5147 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5150 MonoDomain *domain = mono_domain_get();
5153 int i, j, file_count = 0;
5154 MonoImage **modules;
5155 guint32 module_count, real_module_count;
5156 MonoTableInfo *table;
5157 guint32 cols [MONO_FILE_SIZE];
5158 MonoImage *image = assembly->assembly->image;
5160 g_assert (image != NULL);
5161 g_assert (!assembly_is_dynamic (assembly->assembly));
5163 table = &image->tables [MONO_TABLE_FILE];
5164 file_count = table->rows;
5166 modules = image->modules;
5167 module_count = image->module_count;
5169 real_module_count = 0;
5170 for (i = 0; i < module_count; ++i)
5172 real_module_count ++;
5174 klass = mono_class_get_module_class ();
5175 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5176 if (mono_error_set_pending_exception (&error))
5179 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5180 if (mono_error_set_pending_exception (&error))
5183 mono_array_setref (res, 0, image_obj);
5185 for (i = 0; i < module_count; ++i)
5187 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5188 if (mono_error_set_pending_exception (&error))
5190 mono_array_setref (res, j, rm);
5194 for (i = 0; i < file_count; ++i, ++j) {
5195 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5196 if (cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA) {
5197 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5198 if (mono_error_set_pending_exception (&error))
5200 mono_array_setref (res, j, rm);
5203 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5205 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5206 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5209 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5210 if (mono_error_set_pending_exception (&error))
5212 mono_array_setref (res, j, rm);
5219 ICALL_EXPORT MonoReflectionMethod*
5220 ves_icall_GetCurrentMethod (void)
5222 MonoReflectionMethod *res = NULL;
5225 MonoMethod *m = mono_method_get_last_managed ();
5228 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5232 while (m->is_inflated)
5233 m = ((MonoMethodInflated*)m)->declaring;
5235 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5236 mono_error_set_pending_exception (&error);
5242 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5245 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5248 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5249 //method is inflated, we should inflate it on the other class
5250 MonoGenericContext ctx;
5251 ctx.method_inst = inflated->context.method_inst;
5252 ctx.class_inst = inflated->context.class_inst;
5253 if (klass->generic_class)
5254 ctx.class_inst = klass->generic_class->context.class_inst;
5255 else if (klass->generic_container)
5256 ctx.class_inst = klass->generic_container->context.class_inst;
5257 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5258 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5262 mono_class_setup_methods (method->klass);
5263 if (mono_class_has_failure (method->klass))
5265 for (i = 0; i < method->klass->method.count; ++i) {
5266 if (method->klass->methods [i] == method) {
5271 mono_class_setup_methods (klass);
5272 if (mono_class_has_failure (klass))
5274 g_assert (offset >= 0 && offset < klass->method.count);
5275 return klass->methods [offset];
5278 ICALL_EXPORT MonoReflectionMethod*
5279 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check)
5281 MonoReflectionMethod *res = NULL;
5284 if (type && generic_check) {
5285 klass = mono_class_from_mono_type (type);
5286 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5289 if (method->klass != klass) {
5290 method = mono_method_get_equivalent_method (method, klass);
5295 klass = mono_class_from_mono_type (type);
5297 klass = method->klass;
5298 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5299 mono_error_set_pending_exception (&error);
5303 ICALL_EXPORT MonoReflectionMethodBody*
5304 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5307 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5308 mono_error_set_pending_exception (&error);
5312 ICALL_EXPORT MonoReflectionAssembly*
5313 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5316 MonoReflectionAssembly *result;
5317 MonoMethod *dest = NULL;
5319 mono_stack_walk_no_il (get_executing, &dest);
5321 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5323 mono_error_set_pending_exception (&error);
5328 ICALL_EXPORT MonoReflectionAssembly*
5329 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5332 MonoReflectionAssembly *result;
5333 MonoDomain* domain = mono_domain_get ();
5335 if (!domain->entry_assembly)
5338 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5340 mono_error_set_pending_exception (&error);
5344 ICALL_EXPORT MonoReflectionAssembly*
5345 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5350 MonoReflectionAssembly *result;
5353 mono_stack_walk_no_il (get_executing, &dest);
5355 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5359 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5362 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5364 mono_error_set_pending_exception (&error);
5368 ICALL_EXPORT MonoString *
5369 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5370 gboolean assembly_qualified)
5372 MonoDomain *domain = mono_object_domain (object);
5373 MonoTypeNameFormat format;
5378 format = assembly_qualified ?
5379 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5380 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5382 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5384 name = mono_type_get_name_full (object->type, format);
5388 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5393 res = mono_string_new (domain, name);
5400 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5403 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5405 mono_class_init_checked (klass, &error);
5406 mono_error_set_pending_exception (&error);
5407 return mono_security_core_clr_class_level (klass);
5411 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5413 MonoClassField *field = rfield->field;
5414 return mono_security_core_clr_field_level (field, TRUE);
5418 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5420 MonoMethod *method = rfield->method;
5421 return mono_security_core_clr_method_level (method, TRUE);
5425 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)
5427 static MonoMethod *create_culture = NULL;
5431 const char *pkey_ptr;
5433 MonoBoolean assembly_ref = 0;
5435 mono_error_init (error);
5437 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5438 aname->major = name->major;
5439 aname->minor = name->minor;
5440 aname->build = name->build;
5441 aname->flags = name->flags;
5442 aname->revision = name->revision;
5443 aname->hashalg = name->hash_alg;
5444 aname->versioncompat = 1; /* SameMachine (default) */
5445 aname->processor_architecture = name->arch;
5447 if (by_default_version) {
5448 MonoObject *version;
5450 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5451 return_if_nok (error);
5453 MONO_OBJECT_SETREF (aname, version, version);
5457 if (absolute != NULL && *absolute != '\0') {
5458 const gchar *prepend = "file://";
5461 codebase = g_strdup (absolute);
5466 for (i = strlen (codebase) - 1; i >= 0; i--)
5467 if (codebase [i] == '\\')
5470 if (*codebase == '/' && *(codebase + 1) == '/') {
5473 prepend = "file:///";
5477 result = g_strconcat (prepend, codebase, NULL);
5483 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5487 if (!create_culture) {
5488 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5489 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5490 g_assert (create_culture);
5491 mono_method_desc_free (desc);
5494 if (name->culture) {
5495 args [0] = mono_string_new (domain, name->culture);
5496 args [1] = &assembly_ref;
5498 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5499 return_if_nok (error);
5501 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5504 if (name->public_key) {
5505 pkey_ptr = (char*)name->public_key;
5506 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5508 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5509 return_if_nok (error);
5510 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5511 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5512 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5513 } else if (default_publickey) {
5514 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5515 return_if_nok (error);
5516 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5517 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5520 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5521 if (name->public_key_token [0]) {
5525 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5526 return_if_nok (error);
5528 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5529 p = mono_array_addr (keyToken, char, 0);
5531 for (i = 0, j = 0; i < 8; i++) {
5532 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5533 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5536 } else if (default_token) {
5537 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5538 return_if_nok (error);
5539 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5543 ICALL_EXPORT MonoString *
5544 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5546 MonoDomain *domain = mono_object_domain (assembly);
5547 MonoAssembly *mass = assembly->assembly;
5551 name = mono_stringify_assembly_name (&mass->aname);
5552 res = mono_string_new (domain, name);
5559 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5562 gchar *absolute, *dirname;
5563 MonoAssembly *mass = assembly->assembly;
5565 /* XXX this is duplicated code to compute the codebase URI, unify it */
5566 if (g_path_is_absolute (mass->image->name)) {
5567 absolute = g_strdup (mass->image->name);
5568 dirname = g_path_get_dirname (absolute);
5570 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5571 dirname = g_strdup (mass->basedir);
5574 replace_shadow_path (mono_object_domain (assembly), dirname, &absolute);
5577 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5578 mono_error_set_pending_exception (&error);
5584 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5588 MonoImageOpenStatus status = MONO_IMAGE_OK;
5591 MonoAssemblyName name;
5594 filename = mono_string_to_utf8_checked (fname, &error);
5595 if (mono_error_set_pending_exception (&error))
5598 dirname = g_path_get_dirname (filename);
5599 replace_shadow_path (mono_domain_get (), dirname, &filename);
5602 image = mono_image_open (filename, &status);
5608 if (status == MONO_IMAGE_IMAGE_INVALID)
5609 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5611 exc = mono_get_exception_file_not_found2 (NULL, fname);
5612 mono_set_pending_exception (exc);
5616 res = mono_assembly_fill_assembly_name (image, &name);
5618 mono_image_close (image);
5620 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5624 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5625 mono_error_set_pending_exception (&error);
5627 mono_image_close (image);
5631 ICALL_EXPORT MonoBoolean
5632 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5633 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5635 MonoBoolean result = FALSE;
5636 MonoDeclSecurityEntry entry;
5638 /* SecurityAction.RequestMinimum */
5639 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5640 *minimum = entry.blob;
5641 *minLength = entry.size;
5644 /* SecurityAction.RequestOptional */
5645 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5646 *optional = entry.blob;
5647 *optLength = entry.size;
5650 /* SecurityAction.RequestRefuse */
5651 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5652 *refused = entry.blob;
5653 *refLength = entry.size;
5661 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5663 guint32 attrs, visibility;
5665 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5666 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5667 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5670 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5676 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5678 MonoReflectionType *rt;
5681 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5684 mono_error_init (error);
5686 /* we start the count from 1 because we skip the special type <Module> */
5689 for (i = 1; i < tdef->rows; ++i) {
5690 if (mono_module_type_is_visible (tdef, image, i + 1))
5694 count = tdef->rows - 1;
5696 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5697 return_val_if_nok (error, NULL);
5698 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5699 return_val_if_nok (error, NULL);
5701 for (i = 1; i < tdef->rows; ++i) {
5702 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5703 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5706 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5707 return_val_if_nok (error, NULL);
5709 mono_array_setref (res, count, rt);
5711 MonoException *ex = mono_error_convert_to_exception (error);
5712 mono_array_setref (*exceptions, count, ex);
5721 ICALL_EXPORT MonoArray*
5722 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5725 MonoArray *res = NULL;
5726 MonoArray *exceptions = NULL;
5727 MonoImage *image = NULL;
5728 MonoTableInfo *table = NULL;
5731 int i, len, ex_count;
5733 domain = mono_object_domain (assembly);
5735 g_assert (!assembly_is_dynamic (assembly->assembly));
5736 image = assembly->assembly->image;
5737 table = &image->tables [MONO_TABLE_FILE];
5738 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5739 if (mono_error_set_pending_exception (&error))
5742 /* Append data from all modules in the assembly */
5743 for (i = 0; i < table->rows; ++i) {
5744 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5745 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5750 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5751 if (mono_error_set_pending_exception (&error))
5755 /* Append the new types to the end of the array */
5756 if (mono_array_length (res2) > 0) {
5758 MonoArray *res3, *ex3;
5760 len1 = mono_array_length (res);
5761 len2 = mono_array_length (res2);
5763 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5764 if (mono_error_set_pending_exception (&error))
5766 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5767 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5770 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5771 if (mono_error_set_pending_exception (&error))
5773 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5774 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5781 /* the ReflectionTypeLoadException must have all the types (Types property),
5782 * NULL replacing types which throws an exception. The LoaderException must
5783 * contain all exceptions for NULL items.
5786 len = mono_array_length (res);
5789 for (i = 0; i < len; i++) {
5790 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5794 klass = mono_type_get_class (t->type);
5795 if ((klass != NULL) && mono_class_has_failure (klass)) {
5796 /* keep the class in the list */
5797 list = g_list_append (list, klass);
5798 /* and replace Type with NULL */
5799 mono_array_setref (res, i, NULL);
5806 if (list || ex_count) {
5808 MonoException *exc = NULL;
5809 MonoArray *exl = NULL;
5810 int j, length = g_list_length (list) + ex_count;
5812 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5813 if (mono_error_set_pending_exception (&error)) {
5817 /* Types for which mono_class_get_checked () succeeded */
5818 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5819 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5820 mono_array_setref (exl, i, exc);
5822 /* Types for which it don't */
5823 for (j = 0; j < mono_array_length (exceptions); ++j) {
5824 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5826 g_assert (i < length);
5827 mono_array_setref (exl, i, exc);
5834 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5835 if (!is_ok (&error)) {
5836 mono_error_set_pending_exception (&error);
5839 mono_set_pending_exception (exc);
5846 ICALL_EXPORT gboolean
5847 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5850 MonoAssemblyName aname;
5851 MonoDomain *domain = mono_object_domain (name);
5853 gboolean is_version_defined;
5854 gboolean is_token_defined;
5856 aname.public_key = NULL;
5857 val = mono_string_to_utf8_checked (assname, &error);
5858 if (mono_error_set_pending_exception (&error))
5861 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5862 g_free ((guint8*) aname.public_key);
5867 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5868 mono_error_set_pending_exception (&error);
5870 mono_assembly_name_free (&aname);
5871 g_free ((guint8*) aname.public_key);
5877 ICALL_EXPORT MonoReflectionType*
5878 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5881 MonoReflectionType *ret;
5882 MonoDomain *domain = mono_object_domain (module);
5885 g_assert (module->image);
5887 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5888 /* These images do not have a global type */
5891 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5892 if (!mono_error_ok (&error)) {
5893 mono_error_set_pending_exception (&error);
5897 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5898 if (!mono_error_ok (&error)) {
5899 mono_error_set_pending_exception (&error);
5907 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5909 /*if (module->image)
5910 mono_image_close (module->image);*/
5913 ICALL_EXPORT MonoString*
5914 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5916 MonoDomain *domain = mono_object_domain (module);
5918 g_assert (module->image);
5919 return mono_string_new (domain, module->image->guid);
5922 ICALL_EXPORT gpointer
5923 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5926 if (module->image && module->image->is_module_handle)
5927 return module->image->raw_data;
5930 return (gpointer) (-1);
5934 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5936 if (image_is_dynamic (image)) {
5937 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5938 *pe_kind = dyn->pe_kind;
5939 *machine = dyn->machine;
5942 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5943 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5948 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5950 return (image->md_version_major << 16) | (image->md_version_minor);
5953 ICALL_EXPORT MonoArray*
5954 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5957 MonoArray *exceptions;
5960 if (!module->image) {
5961 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
5962 mono_error_set_pending_exception (&error);
5967 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5968 if (mono_error_set_pending_exception (&error))
5971 for (i = 0; i < mono_array_length (exceptions); ++i) {
5972 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5974 mono_set_pending_exception (ex);
5983 mono_memberref_is_method (MonoImage *image, guint32 token)
5985 if (!image_is_dynamic (image)) {
5986 guint32 cols [MONO_MEMBERREF_SIZE];
5988 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5989 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5990 mono_metadata_decode_blob_size (sig, &sig);
5991 return (*sig != 0x6);
5994 MonoClass *handle_class;
5996 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5997 mono_error_cleanup (&error); /* just probing, ignore error */
6001 return mono_defaults.methodhandle_class == handle_class;
6006 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
6009 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
6010 mono_array_addr (type_args, MonoType*, 0));
6012 context->class_inst = NULL;
6014 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
6015 mono_array_addr (method_args, MonoType*, 0));
6017 context->method_inst = NULL;
6020 ICALL_EXPORT MonoType*
6021 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6024 int table = mono_metadata_token_table (token);
6025 int index = mono_metadata_token_index (token);
6026 MonoGenericContext context;
6029 *resolve_error = ResolveTokenError_Other;
6031 /* Validate token */
6032 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
6033 (table != MONO_TABLE_TYPESPEC)) {
6034 *resolve_error = ResolveTokenError_BadTable;
6038 if (image_is_dynamic (image)) {
6039 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
6040 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6041 mono_error_cleanup (&error);
6042 return klass ? &klass->byval_arg : NULL;
6045 init_generic_context_from_args (&context, type_args, method_args);
6046 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6047 mono_error_cleanup (&error);
6048 return klass ? &klass->byval_arg : NULL;
6051 if ((index <= 0) || (index > image->tables [table].rows)) {
6052 *resolve_error = ResolveTokenError_OutOfRange;
6056 init_generic_context_from_args (&context, type_args, method_args);
6057 klass = mono_class_get_checked (image, token, &error);
6059 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
6060 if (!mono_error_ok (&error)) {
6061 mono_error_set_pending_exception (&error);
6066 return &klass->byval_arg;
6071 ICALL_EXPORT MonoMethod*
6072 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6075 int table = mono_metadata_token_table (token);
6076 int index = mono_metadata_token_index (token);
6077 MonoGenericContext context;
6080 *resolve_error = ResolveTokenError_Other;
6082 /* Validate token */
6083 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
6084 (table != MONO_TABLE_MEMBERREF)) {
6085 *resolve_error = ResolveTokenError_BadTable;
6089 if (image_is_dynamic (image)) {
6090 if (table == MONO_TABLE_METHOD) {
6091 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6092 mono_error_cleanup (&error);
6096 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
6097 *resolve_error = ResolveTokenError_BadTable;
6101 init_generic_context_from_args (&context, type_args, method_args);
6102 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6103 mono_error_cleanup (&error);
6107 if ((index <= 0) || (index > image->tables [table].rows)) {
6108 *resolve_error = ResolveTokenError_OutOfRange;
6111 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6112 *resolve_error = ResolveTokenError_BadTable;
6116 init_generic_context_from_args (&context, type_args, method_args);
6117 method = mono_get_method_checked (image, token, NULL, &context, &error);
6118 mono_error_set_pending_exception (&error);
6123 ICALL_EXPORT MonoString*
6124 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6127 int index = mono_metadata_token_index (token);
6129 *resolve_error = ResolveTokenError_Other;
6131 /* Validate token */
6132 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6133 *resolve_error = ResolveTokenError_BadTable;
6137 if (image_is_dynamic (image)) {
6138 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6139 mono_error_cleanup (&error);
6143 if ((index <= 0) || (index >= image->heap_us.size)) {
6144 *resolve_error = ResolveTokenError_OutOfRange;
6148 /* FIXME: What to do if the index points into the middle of a string ? */
6150 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
6151 mono_error_set_pending_exception (&error);
6155 ICALL_EXPORT MonoClassField*
6156 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6160 int table = mono_metadata_token_table (token);
6161 int index = mono_metadata_token_index (token);
6162 MonoGenericContext context;
6163 MonoClassField *field;
6165 *resolve_error = ResolveTokenError_Other;
6167 /* Validate token */
6168 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6169 *resolve_error = ResolveTokenError_BadTable;
6173 if (image_is_dynamic (image)) {
6174 if (table == MONO_TABLE_FIELD) {
6175 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6176 mono_error_cleanup (&error);
6180 if (mono_memberref_is_method (image, token)) {
6181 *resolve_error = ResolveTokenError_BadTable;
6185 init_generic_context_from_args (&context, type_args, method_args);
6186 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6187 mono_error_cleanup (&error);
6191 if ((index <= 0) || (index > image->tables [table].rows)) {
6192 *resolve_error = ResolveTokenError_OutOfRange;
6195 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6196 *resolve_error = ResolveTokenError_BadTable;
6200 init_generic_context_from_args (&context, type_args, method_args);
6201 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6202 mono_error_set_pending_exception (&error);
6208 ICALL_EXPORT MonoObject*
6209 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6213 int table = mono_metadata_token_table (token);
6215 *error = ResolveTokenError_Other;
6218 case MONO_TABLE_TYPEDEF:
6219 case MONO_TABLE_TYPEREF:
6220 case MONO_TABLE_TYPESPEC: {
6221 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6223 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6224 mono_error_set_pending_exception (&merror);
6231 case MONO_TABLE_METHOD:
6232 case MONO_TABLE_METHODSPEC: {
6233 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6235 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6236 mono_error_set_pending_exception (&merror);
6242 case MONO_TABLE_FIELD: {
6243 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6245 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6246 mono_error_set_pending_exception (&merror);
6252 case MONO_TABLE_MEMBERREF:
6253 if (mono_memberref_is_method (image, token)) {
6254 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6256 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6257 mono_error_set_pending_exception (&merror);
6264 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6266 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6267 mono_error_set_pending_exception (&merror);
6276 *error = ResolveTokenError_BadTable;
6282 ICALL_EXPORT MonoArray*
6283 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6286 int table = mono_metadata_token_table (token);
6287 int idx = mono_metadata_token_index (token);
6288 MonoTableInfo *tables = image->tables;
6293 *resolve_error = ResolveTokenError_OutOfRange;
6295 /* FIXME: Support other tables ? */
6296 if (table != MONO_TABLE_STANDALONESIG)
6299 if (image_is_dynamic (image))
6302 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6305 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6307 ptr = mono_metadata_blob_heap (image, sig);
6308 len = mono_metadata_decode_blob_size (ptr, &ptr);
6310 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6311 if (mono_error_set_pending_exception (&error))
6313 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6317 ICALL_EXPORT MonoReflectionType*
6318 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6321 MonoReflectionType *ret;
6323 int isbyref = 0, rank;
6325 char *str = mono_string_to_utf8_checked (smodifiers, &error);
6326 if (mono_error_set_pending_exception (&error))
6329 klass = mono_class_from_mono_type (tb->type.type);
6331 /* logic taken from mono_reflection_parse_type(): keep in sync */
6335 if (isbyref) { /* only one level allowed by the spec */
6344 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6345 mono_error_set_pending_exception (&error);
6349 klass = mono_ptr_class_get (&klass->byval_arg);
6350 mono_class_init (klass);
6361 else if (*p != '*') { /* '*' means unknown lower bound */
6372 klass = mono_array_class_get (klass, rank);
6373 mono_class_init (klass);
6382 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6383 mono_error_set_pending_exception (&error);
6388 ICALL_EXPORT MonoBoolean
6389 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6395 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6401 check_for_invalid_type (MonoClass *klass, MonoError *error)
6406 mono_error_init (error);
6408 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6411 name = mono_type_get_full_name (klass);
6412 str = mono_string_new (mono_domain_get (), name);
6414 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6417 ICALL_EXPORT MonoReflectionType *
6418 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6421 MonoReflectionType *ret;
6422 MonoClass *klass, *aklass;
6424 klass = mono_class_from_mono_type (type->type);
6425 check_for_invalid_type (klass, &error);
6426 mono_error_set_pending_exception (&error);
6428 if (rank == 0) //single dimentional array
6429 aklass = mono_array_class_get (klass, 1);
6431 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6433 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6434 mono_error_set_pending_exception (&error);
6439 ICALL_EXPORT MonoReflectionType *
6440 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6443 MonoReflectionType *ret;
6446 klass = mono_class_from_mono_type (type->type);
6447 mono_class_init_checked (klass, &error);
6448 if (mono_error_set_pending_exception (&error))
6451 check_for_invalid_type (klass, &error);
6452 if (mono_error_set_pending_exception (&error))
6455 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6456 mono_error_set_pending_exception (&error);
6461 ICALL_EXPORT MonoReflectionType *
6462 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6465 MonoReflectionType *ret;
6466 MonoClass *klass, *pklass;
6468 klass = mono_class_from_mono_type (type->type);
6469 mono_class_init_checked (klass, &error);
6470 if (mono_error_set_pending_exception (&error))
6472 check_for_invalid_type (klass, &error);
6473 if (mono_error_set_pending_exception (&error))
6476 pklass = mono_ptr_class_get (type->type);
6478 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6479 mono_error_set_pending_exception (&error);
6484 ICALL_EXPORT MonoObject *
6485 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6486 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6489 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6490 MonoObject *delegate;
6492 MonoMethod *method = info->method;
6494 mono_class_init_checked (delegate_class, &error);
6495 if (mono_error_set_pending_exception (&error))
6498 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6499 /* FIXME improve this exception message */
6500 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6502 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6503 mono_error_set_pending_exception (&error);
6507 if (mono_security_core_clr_enabled ()) {
6508 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6509 if (throwOnBindFailure)
6510 mono_error_set_pending_exception (&error);
6512 mono_error_cleanup (&error);
6517 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6518 if (mono_error_set_pending_exception (&error))
6521 if (method_is_dynamic (method)) {
6522 /* Creating a trampoline would leak memory */
6523 func = mono_compile_method_checked (method, &error);
6524 if (mono_error_set_pending_exception (&error))
6527 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6528 method = mono_object_get_virtual_method (target, method);
6529 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6530 if (mono_error_set_pending_exception (&error))
6532 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6535 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6536 if (mono_error_set_pending_exception (&error))
6541 ICALL_EXPORT MonoMulticastDelegate *
6542 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6545 MonoMulticastDelegate *ret;
6547 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6549 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6550 if (mono_error_set_pending_exception (&error))
6553 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6558 ICALL_EXPORT MonoReflectionMethod*
6559 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6561 MonoReflectionMethod *ret = NULL;
6563 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6564 mono_error_set_pending_exception (&error);
6570 static inline gint32
6571 mono_array_get_byte_length (MonoArray *array)
6577 klass = array->obj.vtable->klass;
6579 if (array->bounds == NULL)
6580 length = array->max_length;
6583 for (i = 0; i < klass->rank; ++ i)
6584 length *= array->bounds [i].length;
6587 switch (klass->element_class->byval_arg.type) {
6590 case MONO_TYPE_BOOLEAN:
6594 case MONO_TYPE_CHAR:
6602 return length * sizeof (gpointer);
6613 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6615 return mono_array_get_byte_length (array);
6619 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6621 return mono_array_get (array, gint8, idx);
6625 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6627 mono_array_set (array, gint8, idx, value);
6630 ICALL_EXPORT MonoBoolean
6631 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6633 guint8 *src_buf, *dest_buf;
6636 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6640 g_assert (count >= 0);
6642 /* This is called directly from the class libraries without going through the managed wrapper */
6643 MONO_CHECK_ARG_NULL (src, FALSE);
6644 MONO_CHECK_ARG_NULL (dest, FALSE);
6646 /* watch out for integer overflow */
6647 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6650 src_buf = (guint8 *)src->vector + src_offset;
6651 dest_buf = (guint8 *)dest->vector + dest_offset;
6654 memcpy (dest_buf, src_buf, count);
6656 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6661 #ifndef DISABLE_REMOTING
6662 ICALL_EXPORT MonoObject *
6663 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6666 MonoDomain *domain = mono_object_domain (this_obj);
6668 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6669 MonoTransparentProxy *tp;
6673 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6674 if (mono_error_set_pending_exception (&error))
6677 tp = (MonoTransparentProxy*) res;
6679 MONO_OBJECT_SETREF (tp, rp, rp);
6680 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6681 klass = mono_class_from_mono_type (type);
6683 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6684 mono_class_setup_vtable (klass);
6685 if (mono_class_has_failure (klass)) {
6686 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6690 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6691 if (mono_error_set_pending_exception (&error))
6693 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6694 if (mono_error_set_pending_exception (&error))
6697 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6698 if (mono_error_set_pending_exception (&error))
6703 ICALL_EXPORT MonoReflectionType *
6704 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6707 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6708 mono_error_set_pending_exception (&error);
6714 /* System.Environment */
6717 ves_icall_System_Environment_get_UserName (void)
6719 /* using glib is more portable */
6720 return mono_string_new (mono_domain_get (), g_get_user_name ());
6724 ICALL_EXPORT MonoString *
6725 ves_icall_System_Environment_get_MachineName (void)
6727 #if defined (HOST_WIN32)
6732 len = MAX_COMPUTERNAME_LENGTH + 1;
6733 buf = g_new (gunichar2, len);
6736 if (GetComputerName (buf, (PDWORD) &len)) {
6738 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6739 mono_error_set_pending_exception (&error);
6744 #elif !defined(DISABLE_SOCKETS)
6748 #if defined _SC_HOST_NAME_MAX
6749 n = sysconf (_SC_HOST_NAME_MAX);
6753 buf = g_malloc (n+1);
6755 if (gethostname (buf, n) == 0){
6757 result = mono_string_new (mono_domain_get (), buf);
6764 return mono_string_new (mono_domain_get (), "mono");
6769 ves_icall_System_Environment_get_Platform (void)
6771 #if defined (TARGET_WIN32)
6774 #elif defined(__MACH__)
6777 // Notice that the value is hidden from user code, and only exposed
6778 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6779 // define and making assumptions based on Unix/128/4 values before there
6780 // was a MacOS define. Lots of code would assume that not-Unix meant
6781 // Windows, but in this case, it would be OSX.
6790 ICALL_EXPORT MonoString *
6791 ves_icall_System_Environment_get_NewLine (void)
6793 #if defined (HOST_WIN32)
6794 return mono_string_new (mono_domain_get (), "\r\n");
6796 return mono_string_new (mono_domain_get (), "\n");
6800 ICALL_EXPORT MonoBoolean
6801 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6803 #if SIZEOF_VOID_P == 8
6807 gboolean isWow64Process = FALSE;
6808 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6809 return (MonoBoolean)isWow64Process;
6811 #elif defined(HAVE_SYS_UTSNAME_H)
6812 struct utsname name;
6814 if (uname (&name) >= 0) {
6815 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6822 ICALL_EXPORT MonoString *
6823 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6832 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6833 if (mono_error_set_pending_exception (&error))
6835 value = g_getenv (utf8_name);
6842 return mono_string_new (mono_domain_get (), value);
6846 * There is no standard way to get at environ.
6849 #ifndef __MINGW32_VERSION
6850 #if defined(__APPLE__)
6851 #if defined (TARGET_OSX)
6852 /* Apple defines this in crt_externs.h but doesn't provide that header for
6853 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6854 * in fact exist on all implementations (so far)
6856 gchar ***_NSGetEnviron(void);
6857 #define environ (*_NSGetEnviron())
6859 static char *mono_environ[1] = { NULL };
6860 #define environ mono_environ
6861 #endif /* defined (TARGET_OSX) */
6869 ICALL_EXPORT MonoArray *
6870 ves_icall_System_Environment_GetCoomandLineArgs (void)
6873 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6874 mono_error_set_pending_exception (&error);
6878 ICALL_EXPORT MonoArray *
6879 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6891 env_strings = GetEnvironmentStrings();
6894 env_string = env_strings;
6895 while (*env_string != '\0') {
6896 /* weird case that MS seems to skip */
6897 if (*env_string != '=')
6899 while (*env_string != '\0')
6905 domain = mono_domain_get ();
6906 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6907 if (mono_error_set_pending_exception (&error))
6912 env_string = env_strings;
6913 while (*env_string != '\0') {
6914 /* weird case that MS seems to skip */
6915 if (*env_string != '=') {
6916 equal_str = wcschr(env_string, '=');
6917 g_assert(equal_str);
6919 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6920 if (mono_error_set_pending_exception (&error))
6923 mono_array_setref (names, n, str);
6926 while (*env_string != '\0')
6931 FreeEnvironmentStrings (env_strings);
6945 for (e = environ; *e != 0; ++ e)
6948 domain = mono_domain_get ();
6949 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6950 if (mono_error_set_pending_exception (&error))
6954 for (e = environ; *e != 0; ++ e) {
6955 parts = g_strsplit (*e, "=", 2);
6957 str = mono_string_new (domain, *parts);
6958 mono_array_setref (names, n, str);
6971 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6974 gunichar2 *utf16_name, *utf16_value;
6976 gchar *utf8_name, *utf8_value;
6981 utf16_name = mono_string_to_utf16 (name);
6982 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6983 SetEnvironmentVariable (utf16_name, NULL);
6984 g_free (utf16_name);
6988 utf16_value = mono_string_to_utf16 (value);
6990 SetEnvironmentVariable (utf16_name, utf16_value);
6992 g_free (utf16_name);
6993 g_free (utf16_value);
6995 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6996 if (mono_error_set_pending_exception (&error))
6999 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7000 g_unsetenv (utf8_name);
7005 utf8_value = mono_string_to_utf8_checked (value, &error);
7006 if (!mono_error_ok (&error)) {
7008 mono_error_set_pending_exception (&error);
7011 g_setenv (utf8_name, utf8_value, TRUE);
7014 g_free (utf8_value);
7019 ves_icall_System_Environment_Exit (int result)
7021 mono_environment_exitcode_set (result);
7023 /* FIXME: There are some cleanup hangs that should be worked out, but
7024 * if the program is going to exit, everything will be cleaned up when
7025 * NaCl exits anyway.
7027 #ifndef __native_client__
7028 if (!mono_runtime_try_shutdown ())
7029 mono_thread_exit ();
7031 /* Suspend all managed threads since the runtime is going away */
7032 mono_thread_suspend_all_other_threads ();
7034 mono_runtime_quit ();
7037 /* we may need to do some cleanup here... */
7041 ICALL_EXPORT MonoString*
7042 ves_icall_System_Environment_GetGacPath (void)
7044 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
7047 ICALL_EXPORT MonoString*
7048 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
7050 #if defined (HOST_WIN32)
7051 #ifndef CSIDL_FLAG_CREATE
7052 #define CSIDL_FLAG_CREATE 0x8000
7055 WCHAR path [MAX_PATH];
7056 /* Create directory if no existing */
7057 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
7062 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
7063 mono_error_set_pending_exception (&error);
7067 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7069 return mono_string_new (mono_domain_get (), "");
7072 ICALL_EXPORT MonoArray *
7073 ves_icall_System_Environment_GetLogicalDrives (void)
7076 gunichar2 buf [256], *ptr, *dname;
7078 guint initial_size = 127, size = 128;
7081 MonoString *drivestr;
7082 MonoDomain *domain = mono_domain_get ();
7088 while (size > initial_size) {
7089 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
7090 if (size > initial_size) {
7093 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7094 initial_size = size;
7108 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7109 if (mono_error_set_pending_exception (&error))
7116 while (*u16) { u16++; len ++; }
7117 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7118 if (mono_error_set_pending_exception (&error))
7121 mono_array_setref (result, ndrives++, drivestr);
7132 ICALL_EXPORT MonoString *
7133 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7136 gunichar2 volume_name [MAX_PATH + 1];
7138 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7140 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
7141 mono_error_set_pending_exception (&error);
7145 ICALL_EXPORT MonoString *
7146 ves_icall_System_Environment_InternalGetHome (void)
7148 return mono_string_new (mono_domain_get (), g_get_home_dir ());
7151 static const char *encodings [] = {
7153 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7154 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7155 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7157 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7158 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7159 "x_unicode_2_0_utf_7",
7161 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7162 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7164 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7167 "unicodefffe", "utf_16be",
7174 * Returns the internal codepage, if the value of "int_code_page" is
7175 * 1 at entry, and we can not compute a suitable code page number,
7176 * returns the code page as a string
7178 ICALL_EXPORT MonoString*
7179 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
7184 char *codepage = NULL;
7186 int want_name = *int_code_page;
7189 *int_code_page = -1;
7191 g_get_charset (&cset);
7192 c = codepage = strdup (cset);
7193 for (c = codepage; *c; c++){
7194 if (isascii (*c) && isalpha (*c))
7199 /* g_print ("charset: %s\n", cset); */
7201 /* handle some common aliases */
7204 for (i = 0; p != 0; ){
7207 p = encodings [++i];
7210 if (strcmp (p, codepage) == 0){
7211 *int_code_page = code;
7214 p = encodings [++i];
7217 if (strstr (codepage, "utf_8") != NULL)
7218 *int_code_page |= 0x10000000;
7221 if (want_name && *int_code_page == -1)
7222 return mono_string_new (mono_domain_get (), cset);
7227 ICALL_EXPORT MonoBoolean
7228 ves_icall_System_Environment_get_HasShutdownStarted (void)
7230 if (mono_runtime_is_shutting_down ())
7233 if (mono_domain_is_unloading (mono_domain_get ()))
7240 ves_icall_System_Environment_BroadcastSettingChange (void)
7243 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7249 ves_icall_System_Environment_get_TickCount (void)
7251 /* this will overflow after ~24 days */
7252 return (gint32) (mono_msec_boottime () & 0xffffffff);
7256 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7261 #ifndef DISABLE_REMOTING
7262 ICALL_EXPORT MonoBoolean
7263 ves_icall_IsTransparentProxy (MonoObject *proxy)
7268 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7274 ICALL_EXPORT MonoReflectionMethod *
7275 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7276 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7278 MonoReflectionMethod *ret = NULL;
7283 MonoMethod **vtable;
7284 MonoMethod *res = NULL;
7286 MONO_CHECK_ARG_NULL (rtype, NULL);
7287 MONO_CHECK_ARG_NULL (rmethod, NULL);
7289 method = rmethod->method;
7290 klass = mono_class_from_mono_type (rtype->type);
7291 mono_class_init_checked (klass, &error);
7292 if (mono_error_set_pending_exception (&error))
7295 if (MONO_CLASS_IS_INTERFACE (klass))
7298 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7301 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7302 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7308 mono_class_setup_vtable (klass);
7309 vtable = klass->vtable;
7311 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7312 gboolean variance_used = FALSE;
7313 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7314 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7316 res = vtable [offs + method->slot];
7318 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7321 if (method->slot != -1)
7322 res = vtable [method->slot];
7328 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7329 mono_error_set_pending_exception (&error);
7334 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7340 klass = mono_class_from_mono_type (type->type);
7341 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7342 if (!is_ok (&error)) {
7343 mono_error_set_pending_exception (&error);
7347 mono_vtable_set_is_remote (vtable, enable);
7350 #else /* DISABLE_REMOTING */
7353 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7355 g_assert_not_reached ();
7360 ICALL_EXPORT MonoObject *
7361 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7368 domain = mono_object_domain (type);
7369 klass = mono_class_from_mono_type (type->type);
7370 mono_class_init_checked (klass, &error);
7371 if (mono_error_set_pending_exception (&error))
7374 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7375 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7379 if (klass->rank >= 1) {
7380 g_assert (klass->rank == 1);
7381 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7382 mono_error_set_pending_exception (&error);
7385 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7386 if (!is_ok (&error)) {
7387 mono_error_set_pending_exception (&error);
7390 /* Bypass remoting object creation check */
7391 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7392 mono_error_set_pending_exception (&error);
7398 ICALL_EXPORT MonoString *
7399 ves_icall_System_IO_get_temp_path (void)
7401 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7404 #ifndef PLATFORM_NO_DRIVEINFO
7405 ICALL_EXPORT MonoBoolean
7406 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7407 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7411 ULARGE_INTEGER wapi_free_bytes_avail;
7412 ULARGE_INTEGER wapi_total_number_of_bytes;
7413 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7415 *error = ERROR_SUCCESS;
7416 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7417 &wapi_total_number_of_free_bytes);
7420 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7421 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7422 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7424 *free_bytes_avail = 0;
7425 *total_number_of_bytes = 0;
7426 *total_number_of_free_bytes = 0;
7427 *error = GetLastError ();
7433 ICALL_EXPORT guint32
7434 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7436 return GetDriveType (mono_string_chars (root_path_name));
7440 ICALL_EXPORT gpointer
7441 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7444 gpointer result = mono_compile_method_checked (method, &error);
7445 mono_error_set_pending_exception (&error);
7449 ICALL_EXPORT MonoString *
7450 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7455 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7457 #if defined (HOST_WIN32)
7458 /* Avoid mixing '/' and '\\' */
7461 for (i = strlen (path) - 1; i >= 0; i--)
7462 if (path [i] == '/')
7466 mcpath = mono_string_new (mono_domain_get (), path);
7472 /* this is an icall */
7474 get_bundled_app_config (void)
7477 const gchar *app_config;
7480 gchar *config_file_name, *config_file_path;
7481 gsize len, config_file_path_length, config_ext_length;
7484 domain = mono_domain_get ();
7485 file = domain->setup->configuration_file;
7486 if (!file || file->length == 0)
7489 // Retrieve config file and remove the extension
7490 config_file_name = mono_string_to_utf8_checked (file, &error);
7491 if (mono_error_set_pending_exception (&error))
7493 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7494 if (!config_file_path)
7495 config_file_path = config_file_name;
7497 config_file_path_length = strlen (config_file_path);
7498 config_ext_length = strlen (".config");
7499 if (config_file_path_length <= config_ext_length)
7502 len = config_file_path_length - config_ext_length;
7503 module = (gchar *)g_malloc0 (len + 1);
7504 memcpy (module, config_file_path, len);
7505 // Get the config file from the module name
7506 app_config = mono_config_string_for_assembly_file (module);
7509 if (config_file_name != config_file_path)
7510 g_free (config_file_name);
7511 g_free (config_file_path);
7516 return mono_string_new (mono_domain_get (), app_config);
7520 get_bundled_machine_config (void)
7522 const gchar *machine_config;
7524 machine_config = mono_get_machine_config ();
7526 if (!machine_config)
7529 return mono_string_new (mono_domain_get (), machine_config);
7532 ICALL_EXPORT MonoString *
7533 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7538 path = g_path_get_dirname (mono_get_config_dir ());
7540 #if defined (HOST_WIN32)
7541 /* Avoid mixing '/' and '\\' */
7544 for (i = strlen (path) - 1; i >= 0; i--)
7545 if (path [i] == '/')
7549 ipath = mono_string_new (mono_domain_get (), path);
7555 ICALL_EXPORT gboolean
7556 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7558 MonoPEResourceDataEntry *entry;
7561 if (!assembly || !result || !size)
7566 image = assembly->assembly->image;
7567 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7571 *result = mono_image_rva_map (image, entry->rde_data_offset);
7576 *size = entry->rde_size;
7581 ICALL_EXPORT MonoBoolean
7582 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7584 return mono_is_debugger_attached ();
7587 ICALL_EXPORT MonoBoolean
7588 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7590 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7591 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7597 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7599 if (mono_get_runtime_callbacks ()->debug_log)
7600 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7604 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7606 #if defined (HOST_WIN32)
7607 OutputDebugString (mono_string_chars (message));
7609 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7613 /* Only used for value types */
7614 ICALL_EXPORT MonoObject *
7615 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7622 domain = mono_object_domain (type);
7623 klass = mono_class_from_mono_type (type->type);
7624 mono_class_init_checked (klass, &error);
7625 if (mono_error_set_pending_exception (&error))
7628 if (mono_class_is_nullable (klass))
7629 /* No arguments -> null */
7632 result = mono_object_new_checked (domain, klass, &error);
7633 mono_error_set_pending_exception (&error);
7637 ICALL_EXPORT MonoReflectionMethod *
7638 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7640 MonoReflectionMethod *ret = NULL;
7643 MonoClass *klass, *parent;
7644 MonoGenericContext *generic_inst = NULL;
7645 MonoMethod *method = m->method;
7646 MonoMethod *result = NULL;
7649 if (method->klass == NULL)
7652 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7653 MONO_CLASS_IS_INTERFACE (method->klass) ||
7654 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7657 slot = mono_method_get_vtable_slot (method);
7661 klass = method->klass;
7662 if (klass->generic_class) {
7663 generic_inst = mono_class_get_context (klass);
7664 klass = klass->generic_class->container_class;
7668 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7669 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7670 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7671 or klass is the generic container class and generic_inst is the instantiation.
7673 when we go to the parent, if the parent is an open constructed type, we need to
7674 replace the type parameters by the definitions from the generic_inst, and then take it
7675 apart again into the klass and the generic_inst.
7677 For cases like this:
7678 class C<T> : B<T, int> {
7679 public override void Foo () { ... }
7681 class B<U,V> : A<HashMap<U,V>> {
7682 public override void Foo () { ... }
7685 public virtual void Foo () { ... }
7688 if at each iteration the parent isn't open, we can skip inflating it. if at some
7689 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7692 MonoGenericContext *parent_inst = NULL;
7693 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7694 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7695 if (!mono_error_ok (&error)) {
7696 mono_error_set_pending_exception (&error);
7700 if (parent->generic_class) {
7701 parent_inst = mono_class_get_context (parent);
7702 parent = parent->generic_class->container_class;
7705 mono_class_setup_vtable (parent);
7706 if (parent->vtable_size <= slot)
7709 generic_inst = parent_inst;
7712 klass = klass->parent;
7715 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7716 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7717 if (!mono_error_ok (&error)) {
7718 mono_error_set_pending_exception (&error);
7722 generic_inst = NULL;
7724 if (klass->generic_class) {
7725 generic_inst = mono_class_get_context (klass);
7726 klass = klass->generic_class->container_class;
7732 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7733 if (!mono_error_ok (&error)) {
7734 mono_error_set_pending_exception (&error);
7739 if (klass == method->klass)
7742 /*This is possible if definition == FALSE.
7743 * Do it here to be really sure we don't read invalid memory.
7745 if (slot >= klass->vtable_size)
7748 mono_class_setup_vtable (klass);
7750 result = klass->vtable [slot];
7751 if (result == NULL) {
7752 /* It is an abstract method */
7753 gpointer iter = NULL;
7754 while ((result = mono_class_get_methods (klass, &iter)))
7755 if (result->slot == slot)
7762 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7763 mono_error_set_pending_exception (&error);
7767 ICALL_EXPORT MonoString*
7768 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7770 MonoMethod *method = m->method;
7772 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7777 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7779 iter->sig = *(MonoMethodSignature**)argsp;
7781 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7782 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7785 /* FIXME: it's not documented what start is exactly... */
7789 iter->args = argsp + sizeof (gpointer);
7791 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7793 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7796 ICALL_EXPORT MonoTypedRef
7797 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7799 guint32 i, arg_size;
7803 i = iter->sig->sentinelpos + iter->next_arg;
7805 g_assert (i < iter->sig->param_count);
7807 res.type = iter->sig->params [i];
7808 res.klass = mono_class_from_mono_type (res.type);
7809 arg_size = mono_type_stack_size (res.type, &align);
7810 #if defined(__arm__) || defined(__mips__)
7811 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7813 res.value = iter->args;
7814 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7815 /* Values are stored as 8 byte register sized objects, but 'value'
7816 * is dereferenced as a pointer in other routines.
7818 res.value = (char*)res.value + 4;
7820 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7821 if (arg_size <= sizeof (gpointer)) {
7823 int padding = arg_size - mono_type_size (res.type, &dummy);
7824 res.value = (guint8*)res.value + padding;
7827 iter->args = (char*)iter->args + arg_size;
7830 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7835 ICALL_EXPORT MonoTypedRef
7836 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7838 guint32 i, arg_size;
7842 i = iter->sig->sentinelpos + iter->next_arg;
7844 g_assert (i < iter->sig->param_count);
7846 while (i < iter->sig->param_count) {
7847 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7849 res.type = iter->sig->params [i];
7850 res.klass = mono_class_from_mono_type (res.type);
7851 /* FIXME: endianess issue... */
7852 arg_size = mono_type_stack_size (res.type, &align);
7853 #if defined(__arm__) || defined(__mips__)
7854 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7856 res.value = iter->args;
7857 iter->args = (char*)iter->args + arg_size;
7859 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7862 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7870 ICALL_EXPORT MonoType*
7871 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7875 i = iter->sig->sentinelpos + iter->next_arg;
7877 g_assert (i < iter->sig->param_count);
7879 return iter->sig->params [i];
7882 ICALL_EXPORT MonoObject*
7883 mono_TypedReference_ToObject (MonoTypedRef* tref)
7886 MonoObject *result = NULL;
7887 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7888 MonoObject** objp = (MonoObject **)tref->value;
7892 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7893 mono_error_set_pending_exception (&error);
7897 ICALL_EXPORT MonoTypedRef
7898 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7901 MonoReflectionField *f;
7903 MonoType *ftype = NULL;
7907 memset (&res, 0, sizeof (res));
7910 g_assert (mono_array_length (fields) > 0);
7912 klass = target->vtable->klass;
7914 for (i = 0; i < mono_array_length (fields); ++i) {
7915 f = mono_array_get (fields, MonoReflectionField*, i);
7917 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7920 if (f->field->parent != klass) {
7921 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7925 p = (guint8*)target + f->field->offset;
7927 p += f->field->offset - sizeof (MonoObject);
7928 klass = mono_class_from_mono_type (f->field->type);
7929 ftype = f->field->type;
7933 res.klass = mono_class_from_mono_type (ftype);
7940 prelink_method (MonoMethod *method, MonoError *error)
7942 const char *exc_class, *exc_arg;
7944 mono_error_init (error);
7945 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7947 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7949 mono_error_set_exception_instance (error,
7950 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7953 /* create the wrapper, too? */
7957 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7961 prelink_method (method->method, &error);
7962 mono_error_set_pending_exception (&error);
7966 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7969 MonoClass *klass = mono_class_from_mono_type (type->type);
7971 gpointer iter = NULL;
7973 mono_class_init_checked (klass, &error);
7974 if (mono_error_set_pending_exception (&error))
7977 while ((m = mono_class_get_methods (klass, &iter))) {
7978 prelink_method (m, &error);
7979 if (mono_error_set_pending_exception (&error))
7984 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7986 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7987 gint32 const **exponents,
7988 gunichar2 const **digitLowerTable,
7989 gunichar2 const **digitUpperTable,
7990 gint64 const **tenPowersList,
7991 gint32 const **decHexDigits)
7993 *mantissas = Formatter_MantissaBitsTable;
7994 *exponents = Formatter_TensExponentTable;
7995 *digitLowerTable = Formatter_DigitLowerTable;
7996 *digitUpperTable = Formatter_DigitUpperTable;
7997 *tenPowersList = Formatter_TenPowersList;
7998 *decHexDigits = Formatter_DecHexDigits;
8002 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
8003 * and avoid useless allocations.
8006 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
8008 MonoReflectionType *rt;
8012 mono_error_init (error);
8013 for (i = 0; i < type->num_mods; ++i) {
8014 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
8019 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
8020 return_val_if_nok (error, NULL);
8022 for (i = 0; i < type->num_mods; ++i) {
8023 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
8024 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
8025 return_val_if_nok (error, NULL);
8027 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8028 return_val_if_nok (error, NULL);
8030 mono_array_setref (res, count, rt);
8037 ICALL_EXPORT MonoArray*
8038 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
8041 MonoType *type = param->ClassImpl->type;
8042 MonoClass *member_class = mono_object_class (param->MemberImpl);
8043 MonoMethod *method = NULL;
8046 MonoMethodSignature *sig;
8049 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8050 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8051 method = rmethod->method;
8052 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
8053 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8054 if (!(method = prop->property->get))
8055 method = prop->property->set;
8058 char *type_name = mono_type_get_full_name (member_class);
8059 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
8060 MonoException *ex = mono_get_exception_not_supported (msg);
8063 mono_set_pending_exception (ex);
8067 image = method->klass->image;
8068 pos = param->PositionImpl;
8069 sig = mono_method_signature (method);
8073 type = sig->params [pos];
8075 res = type_array_from_modifiers (image, type, optional, &error);
8076 mono_error_set_pending_exception (&error);
8081 get_property_type (MonoProperty *prop)
8083 MonoMethodSignature *sig;
8085 sig = mono_method_signature (prop->get);
8087 } else if (prop->set) {
8088 sig = mono_method_signature (prop->set);
8089 return sig->params [sig->param_count - 1];
8094 ICALL_EXPORT MonoArray*
8095 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
8098 MonoType *type = get_property_type (property->property);
8099 MonoImage *image = property->klass->image;
8104 res = type_array_from_modifiers (image, type, optional, &error);
8105 mono_error_set_pending_exception (&error);
8110 *Construct a MonoType suited to be used to decode a constant blob object.
8112 * @type is the target type which will be constructed
8113 * @blob_type is the blob type, for example, that comes from the constant table
8114 * @real_type is the expected constructed type.
8117 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8119 type->type = blob_type;
8120 type->data.klass = NULL;
8121 if (blob_type == MONO_TYPE_CLASS)
8122 type->data.klass = mono_defaults.object_class;
8123 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8124 /* For enums, we need to use the base type */
8125 type->type = MONO_TYPE_VALUETYPE;
8126 type->data.klass = mono_class_from_mono_type (real_type);
8128 type->data.klass = mono_class_from_mono_type (real_type);
8131 ICALL_EXPORT MonoObject*
8132 property_info_get_default_value (MonoReflectionProperty *property)
8136 MonoProperty *prop = property->property;
8137 MonoType *type = get_property_type (prop);
8138 MonoDomain *domain = mono_object_domain (property);
8139 MonoTypeEnum def_type;
8140 const char *def_value;
8143 mono_class_init (prop->parent);
8145 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8146 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8150 def_value = mono_class_get_property_default_value (prop, &def_type);
8152 mono_type_from_blob_type (&blob_type, def_type, type);
8153 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8155 mono_error_set_pending_exception (&error);
8159 ICALL_EXPORT MonoBoolean
8160 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8163 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8164 MonoCustomAttrInfo *cinfo;
8167 mono_class_init_checked (attr_class, &error);
8168 if (mono_error_set_pending_exception (&error))
8171 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8172 if (!is_ok (&error)) {
8173 mono_error_set_pending_exception (&error);
8178 found = mono_custom_attrs_has_attr (cinfo, attr_class);
8180 mono_custom_attrs_free (cinfo);
8184 ICALL_EXPORT MonoArray*
8185 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8187 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8192 mono_class_init_checked (attr_class, &error);
8193 if (mono_error_set_pending_exception (&error))
8197 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8198 if (!mono_error_ok (&error)) {
8199 mono_error_set_pending_exception (&error);
8206 ICALL_EXPORT MonoArray*
8207 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8211 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8212 mono_error_set_pending_exception (&error);
8217 ICALL_EXPORT MonoString*
8218 ves_icall_Mono_Runtime_GetDisplayName (void)
8221 MonoString *display_name;
8223 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8224 display_name = mono_string_new (mono_domain_get (), info);
8226 return display_name;
8229 ICALL_EXPORT MonoString*
8230 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8233 MonoString *message;
8237 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8238 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8241 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8243 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8244 if (mono_error_set_pending_exception (&error))
8251 ICALL_EXPORT gpointer
8252 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8254 return GetCurrentProcess ();
8257 ICALL_EXPORT MonoBoolean
8258 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8260 return GetExitCodeProcess (handle, (guint32*) exitcode);
8263 ICALL_EXPORT MonoBoolean
8264 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8266 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8267 return CloseHandle (handle);
8269 return CloseProcess (handle);
8273 ICALL_EXPORT MonoBoolean
8274 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8276 return TerminateProcess (handle, exitcode);
8280 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8282 return WaitForInputIdle (handle, milliseconds);
8285 ICALL_EXPORT MonoBoolean
8286 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8288 return GetProcessWorkingSetSize (handle, min, max);
8291 ICALL_EXPORT MonoBoolean
8292 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8294 return SetProcessWorkingSetSize (handle, min, max);
8297 ICALL_EXPORT MonoBoolean
8298 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8300 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8304 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8306 return mono_process_current_pid ();
8310 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8312 return GetPriorityClass (handle);
8315 ICALL_EXPORT MonoBoolean
8316 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8318 return SetPriorityClass (handle, priorityClass);
8321 #ifndef DISABLE_ICALL_TABLES
8323 #define ICALL_TYPE(id,name,first)
8324 #define ICALL(id,name,func) Icall_ ## id,
8327 #include "metadata/icall-def.h"
8333 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8334 #define ICALL(id,name,func)
8336 #include "metadata/icall-def.h"
8342 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8343 #define ICALL(id,name,func)
8345 guint16 first_icall;
8348 static const IcallTypeDesc
8349 icall_type_descs [] = {
8350 #include "metadata/icall-def.h"
8354 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8357 #define ICALL_TYPE(id,name,first)
8360 #ifdef HAVE_ARRAY_ELEM_INIT
8361 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8362 #define MSGSTRFIELD1(line) str##line
8364 static const struct msgstrtn_t {
8365 #define ICALL(id,name,func)
8367 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8368 #include "metadata/icall-def.h"
8370 } icall_type_names_str = {
8371 #define ICALL_TYPE(id,name,first) (name),
8372 #include "metadata/icall-def.h"
8375 static const guint16 icall_type_names_idx [] = {
8376 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8377 #include "metadata/icall-def.h"
8380 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8382 static const struct msgstr_t {
8384 #define ICALL_TYPE(id,name,first)
8385 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8386 #include "metadata/icall-def.h"
8388 } icall_names_str = {
8389 #define ICALL(id,name,func) (name),
8390 #include "metadata/icall-def.h"
8393 static const guint16 icall_names_idx [] = {
8394 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8395 #include "metadata/icall-def.h"
8398 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8404 #define ICALL_TYPE(id,name,first) name,
8405 #define ICALL(id,name,func)
8406 static const char* const
8407 icall_type_names [] = {
8408 #include "metadata/icall-def.h"
8412 #define icall_type_name_get(id) (icall_type_names [(id)])
8416 #define ICALL_TYPE(id,name,first)
8417 #define ICALL(id,name,func) name,
8418 static const char* const
8420 #include "metadata/icall-def.h"
8423 #define icall_name_get(id) icall_names [(id)]
8425 #endif /* !HAVE_ARRAY_ELEM_INIT */
8429 #define ICALL_TYPE(id,name,first)
8430 #define ICALL(id,name,func) func,
8431 static const gconstpointer
8432 icall_functions [] = {
8433 #include "metadata/icall-def.h"
8437 #ifdef ENABLE_ICALL_SYMBOL_MAP
8440 #define ICALL_TYPE(id,name,first)
8441 #define ICALL(id,name,func) #func,
8442 static const gconstpointer
8443 icall_symbols [] = {
8444 #include "metadata/icall-def.h"
8449 #endif /* DISABLE_ICALL_TABLES */
8451 static mono_mutex_t icall_mutex;
8452 static GHashTable *icall_hash = NULL;
8453 static GHashTable *jit_icall_hash_name = NULL;
8454 static GHashTable *jit_icall_hash_addr = NULL;
8457 mono_icall_init (void)
8459 #ifndef DISABLE_ICALL_TABLES
8462 /* check that tables are sorted: disable in release */
8465 const char *prev_class = NULL;
8466 const char *prev_method;
8468 for (i = 0; i < Icall_type_num; ++i) {
8469 const IcallTypeDesc *desc;
8472 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8473 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8474 prev_class = icall_type_name_get (i);
8475 desc = &icall_type_descs [i];
8476 num_icalls = icall_desc_num_icalls (desc);
8477 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8478 for (j = 0; j < num_icalls; ++j) {
8479 const char *methodn = icall_name_get (desc->first_icall + j);
8480 if (prev_method && strcmp (prev_method, methodn) >= 0)
8481 g_print ("method %s should come before method %s\n", methodn, prev_method);
8482 prev_method = methodn;
8488 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8489 mono_os_mutex_init (&icall_mutex);
8493 mono_icall_lock (void)
8495 mono_locks_os_acquire (&icall_mutex, IcallLock);
8499 mono_icall_unlock (void)
8501 mono_locks_os_release (&icall_mutex, IcallLock);
8505 mono_icall_cleanup (void)
8507 g_hash_table_destroy (icall_hash);
8508 g_hash_table_destroy (jit_icall_hash_name);
8509 g_hash_table_destroy (jit_icall_hash_addr);
8510 mono_os_mutex_destroy (&icall_mutex);
8514 * mono_add_internal_call:
8515 * @name: method specification to surface to the managed world
8516 * @method: pointer to a C method to invoke when the method is called
8518 * This method surfaces the C function pointed by @method as a method
8519 * that has been surfaced in managed code with the method specified in
8520 * @name as an internal call.
8522 * Internal calls are surfaced to all app domains loaded and they are
8523 * accessibly by a type with the specified name.
8525 * You must provide a fully qualified type name, that is namespaces
8526 * and type name, followed by a colon and the method name, with an
8527 * optional signature to bind.
8529 * For example, the following are all valid declarations:
8531 * "MyApp.Services.ScriptService:Accelerate"
8532 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8534 * You use method parameters in cases where there might be more than
8535 * one surface method to managed code. That way you can register different
8536 * internal calls for different method overloads.
8538 * The internal calls are invoked with no marshalling. This means that .NET
8539 * types like System.String are exposed as `MonoString *` parameters. This is
8540 * different than the way that strings are surfaced in P/Invoke.
8542 * For more information on how the parameters are marshalled, see the
8543 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8546 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8547 * reference for more information on the format of method descriptions.
8550 mono_add_internal_call (const char *name, gconstpointer method)
8554 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8556 mono_icall_unlock ();
8559 #ifndef DISABLE_ICALL_TABLES
8561 #ifdef HAVE_ARRAY_ELEM_INIT
8563 compare_method_imap (const void *key, const void *elem)
8565 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8566 return strcmp (key, method_name);
8570 find_method_icall (const IcallTypeDesc *imap, const char *name)
8572 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);
8575 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8579 compare_class_imap (const void *key, const void *elem)
8581 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8582 return strcmp (key, class_name);
8585 static const IcallTypeDesc*
8586 find_class_icalls (const char *name)
8588 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);
8591 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8594 #else /* HAVE_ARRAY_ELEM_INIT */
8597 compare_method_imap (const void *key, const void *elem)
8599 const char** method_name = (const char**)elem;
8600 return strcmp (key, *method_name);
8604 find_method_icall (const IcallTypeDesc *imap, const char *name)
8606 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8609 return (gpointer)icall_functions [(nameslot - icall_names)];
8613 compare_class_imap (const void *key, const void *elem)
8615 const char** class_name = (const char**)elem;
8616 return strcmp (key, *class_name);
8619 static const IcallTypeDesc*
8620 find_class_icalls (const char *name)
8622 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8625 return &icall_type_descs [nameslot - icall_type_names];
8628 #endif /* HAVE_ARRAY_ELEM_INIT */
8630 #endif /* DISABLE_ICALL_TABLES */
8633 * we should probably export this as an helper (handle nested types).
8634 * Returns the number of chars written in buf.
8637 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8639 int nspacelen, cnamelen;
8640 nspacelen = strlen (klass->name_space);
8641 cnamelen = strlen (klass->name);
8642 if (nspacelen + cnamelen + 2 > bufsize)
8645 memcpy (buf, klass->name_space, nspacelen);
8646 buf [nspacelen ++] = '.';
8648 memcpy (buf + nspacelen, klass->name, cnamelen);
8649 buf [nspacelen + cnamelen] = 0;
8650 return nspacelen + cnamelen;
8653 #ifdef DISABLE_ICALL_TABLES
8655 no_icall_table (void)
8657 g_assert_not_reached ();
8662 mono_lookup_internal_call (MonoMethod *method)
8667 int typelen = 0, mlen, siglen;
8669 #ifndef DISABLE_ICALL_TABLES
8670 const IcallTypeDesc *imap = NULL;
8673 g_assert (method != NULL);
8675 if (method->is_inflated)
8676 method = ((MonoMethodInflated *) method)->declaring;
8678 if (method->klass->nested_in) {
8679 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8683 mname [pos++] = '/';
8686 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8692 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8697 #ifndef DISABLE_ICALL_TABLES
8698 imap = find_class_icalls (mname);
8701 mname [typelen] = ':';
8702 mname [typelen + 1] = ':';
8704 mlen = strlen (method->name);
8705 memcpy (mname + typelen + 2, method->name, mlen);
8706 sigstart = mname + typelen + 2 + mlen;
8709 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8710 siglen = strlen (tmpsig);
8711 if (typelen + mlen + siglen + 6 > sizeof (mname))
8714 memcpy (sigstart + 1, tmpsig, siglen);
8715 sigstart [siglen + 1] = ')';
8716 sigstart [siglen + 2] = 0;
8721 res = g_hash_table_lookup (icall_hash, mname);
8723 mono_icall_unlock ();;
8726 /* try without signature */
8728 res = g_hash_table_lookup (icall_hash, mname);
8730 mono_icall_unlock ();
8734 #ifdef DISABLE_ICALL_TABLES
8735 mono_icall_unlock ();
8736 /* Fail only when the result is actually used */
8737 /* mono_marshal_get_native_wrapper () depends on this */
8738 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8739 return ves_icall_System_String_ctor_RedirectToCreateString;
8741 return no_icall_table;
8743 /* it wasn't found in the static call tables */
8745 mono_icall_unlock ();
8748 res = find_method_icall (imap, sigstart - mlen);
8750 mono_icall_unlock ();
8753 /* try _with_ signature */
8755 res = find_method_icall (imap, sigstart - mlen);
8757 mono_icall_unlock ();
8761 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8762 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8763 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8764 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8765 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");
8766 g_print ("If you see other errors or faults after this message they are probably related\n");
8767 g_print ("and you need to fix your mono install first.\n");
8769 mono_icall_unlock ();
8775 #ifdef ENABLE_ICALL_SYMBOL_MAP
8777 func_cmp (gconstpointer key, gconstpointer p)
8779 return (gsize)key - (gsize)*(gsize*)p;
8784 * mono_lookup_icall_symbol:
8786 * Given the icall METHOD, returns its C symbol.
8789 mono_lookup_icall_symbol (MonoMethod *m)
8791 #ifdef DISABLE_ICALL_TABLES
8792 g_assert_not_reached ();
8795 #ifdef ENABLE_ICALL_SYMBOL_MAP
8799 static gconstpointer *functions_sorted;
8800 static const char**symbols_sorted;
8801 static gboolean inited;
8806 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8807 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8808 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8809 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8810 /* Bubble sort the two arrays */
8814 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8815 if (functions_sorted [i] > functions_sorted [i + 1]) {
8818 tmp = functions_sorted [i];
8819 functions_sorted [i] = functions_sorted [i + 1];
8820 functions_sorted [i + 1] = tmp;
8821 tmp = symbols_sorted [i];
8822 symbols_sorted [i] = symbols_sorted [i + 1];
8823 symbols_sorted [i + 1] = tmp;
8830 func = mono_lookup_internal_call (m);
8833 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8837 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8839 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8840 g_assert_not_reached ();
8847 type_from_typename (char *type_name)
8849 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8851 if (!strcmp (type_name, "int"))
8852 klass = mono_defaults.int_class;
8853 else if (!strcmp (type_name, "ptr"))
8854 klass = mono_defaults.int_class;
8855 else if (!strcmp (type_name, "void"))
8856 klass = mono_defaults.void_class;
8857 else if (!strcmp (type_name, "int32"))
8858 klass = mono_defaults.int32_class;
8859 else if (!strcmp (type_name, "uint32"))
8860 klass = mono_defaults.uint32_class;
8861 else if (!strcmp (type_name, "int8"))
8862 klass = mono_defaults.sbyte_class;
8863 else if (!strcmp (type_name, "uint8"))
8864 klass = mono_defaults.byte_class;
8865 else if (!strcmp (type_name, "int16"))
8866 klass = mono_defaults.int16_class;
8867 else if (!strcmp (type_name, "uint16"))
8868 klass = mono_defaults.uint16_class;
8869 else if (!strcmp (type_name, "long"))
8870 klass = mono_defaults.int64_class;
8871 else if (!strcmp (type_name, "ulong"))
8872 klass = mono_defaults.uint64_class;
8873 else if (!strcmp (type_name, "float"))
8874 klass = mono_defaults.single_class;
8875 else if (!strcmp (type_name, "double"))
8876 klass = mono_defaults.double_class;
8877 else if (!strcmp (type_name, "object"))
8878 klass = mono_defaults.object_class;
8879 else if (!strcmp (type_name, "obj"))
8880 klass = mono_defaults.object_class;
8881 else if (!strcmp (type_name, "string"))
8882 klass = mono_defaults.string_class;
8883 else if (!strcmp (type_name, "bool"))
8884 klass = mono_defaults.boolean_class;
8885 else if (!strcmp (type_name, "boolean"))
8886 klass = mono_defaults.boolean_class;
8888 g_error ("%s", type_name);
8889 g_assert_not_reached ();
8891 return &klass->byval_arg;
8895 * LOCKING: Take the corlib image lock.
8897 MonoMethodSignature*
8898 mono_create_icall_signature (const char *sigstr)
8903 MonoMethodSignature *res, *res2;
8904 MonoImage *corlib = mono_defaults.corlib;
8906 mono_image_lock (corlib);
8907 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8908 mono_image_unlock (corlib);
8913 parts = g_strsplit (sigstr, " ", 256);
8922 res = mono_metadata_signature_alloc (corlib, len - 1);
8927 * Under windows, the default pinvoke calling convention is STDCALL but
8930 res->call_convention = MONO_CALL_C;
8933 res->ret = type_from_typename (parts [0]);
8934 for (i = 1; i < len; ++i) {
8935 res->params [i - 1] = type_from_typename (parts [i]);
8940 mono_image_lock (corlib);
8941 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8943 res = res2; /*Value is allocated in the image pool*/
8945 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8946 mono_image_unlock (corlib);
8952 mono_find_jit_icall_by_name (const char *name)
8954 MonoJitICallInfo *info;
8955 g_assert (jit_icall_hash_name);
8958 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8959 mono_icall_unlock ();
8964 mono_find_jit_icall_by_addr (gconstpointer addr)
8966 MonoJitICallInfo *info;
8967 g_assert (jit_icall_hash_addr);
8970 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8971 mono_icall_unlock ();
8977 * mono_get_jit_icall_info:
8979 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8980 * caller should access it while holding the icall lock.
8983 mono_get_jit_icall_info (void)
8985 return jit_icall_hash_name;
8989 * mono_lookup_jit_icall_symbol:
8991 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8994 mono_lookup_jit_icall_symbol (const char *name)
8996 MonoJitICallInfo *info;
8997 const char *res = NULL;
9000 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9002 res = info->c_symbol;
9003 mono_icall_unlock ();
9008 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
9011 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
9012 mono_icall_unlock ();
9016 * 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
9017 * icalls without wrappers in some cases.
9020 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
9022 MonoJitICallInfo *info;
9029 if (!jit_icall_hash_name) {
9030 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
9031 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
9034 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
9035 g_warning ("jit icall already defined \"%s\"\n", name);
9036 g_assert_not_reached ();
9039 info = g_new0 (MonoJitICallInfo, 1);
9044 info->c_symbol = c_symbol;
9045 info->no_raise = no_raise;
9048 info->wrapper = func;
9050 info->wrapper = NULL;
9053 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
9054 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
9056 mono_icall_unlock ();
9061 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
9063 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);