5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
9 * Aleksey Kliger (aleksey@xamarin.com)
11 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
12 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
14 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
25 #ifdef HAVE_SYS_TIME_H
31 #if defined (HOST_WIN32)
34 #if defined (HAVE_WCHAR_H)
38 #include "mono/utils/mono-membar.h"
39 #include <mono/metadata/object.h>
40 #include <mono/metadata/threads.h>
41 #include <mono/metadata/threads-types.h>
42 #include <mono/metadata/threadpool-ms.h>
43 #include <mono/metadata/threadpool-ms-io.h>
44 #include <mono/metadata/monitor.h>
45 #include <mono/metadata/reflection.h>
46 #include <mono/metadata/assembly.h>
47 #include <mono/metadata/tabledefs.h>
48 #include <mono/metadata/exception.h>
49 #include <mono/metadata/exception-internals.h>
50 #include <mono/metadata/file-io.h>
51 #include <mono/metadata/console-io.h>
52 #include <mono/metadata/mono-route.h>
53 #include <mono/metadata/socket-io.h>
54 #include <mono/metadata/mono-endian.h>
55 #include <mono/metadata/tokentype.h>
56 #include <mono/metadata/domain-internals.h>
57 #include <mono/metadata/metadata-internals.h>
58 #include <mono/metadata/class-internals.h>
59 #include <mono/metadata/reflection-internals.h>
60 #include <mono/metadata/marshal.h>
61 #include <mono/metadata/gc-internals.h>
62 #include <mono/metadata/mono-gc.h>
63 #include <mono/metadata/rand.h>
64 #include <mono/metadata/sysmath.h>
65 #include <mono/metadata/string-icalls.h>
66 #include <mono/metadata/debug-helpers.h>
67 #include <mono/metadata/process.h>
68 #include <mono/metadata/environment.h>
69 #include <mono/metadata/profiler-private.h>
70 #include <mono/metadata/locales.h>
71 #include <mono/metadata/filewatcher.h>
72 #include <mono/metadata/security.h>
73 #include <mono/metadata/mono-config.h>
74 #include <mono/metadata/cil-coff.h>
75 #include <mono/metadata/number-formatter.h>
76 #include <mono/metadata/security-manager.h>
77 #include <mono/metadata/security-core-clr.h>
78 #include <mono/metadata/mono-perfcounters.h>
79 #include <mono/metadata/mono-debug.h>
80 #include <mono/metadata/mono-ptr-array.h>
81 #include <mono/metadata/verify-internals.h>
82 #include <mono/metadata/runtime.h>
83 #include <mono/metadata/file-mmap.h>
84 #include <mono/metadata/seq-points-data.h>
85 #include <mono/io-layer/io-layer.h>
86 #include <mono/utils/monobitset.h>
87 #include <mono/utils/mono-time.h>
88 #include <mono/utils/mono-proclib.h>
89 #include <mono/utils/mono-string.h>
90 #include <mono/utils/mono-error-internals.h>
91 #include <mono/utils/mono-mmap.h>
92 #include <mono/utils/mono-io-portability.h>
93 #include <mono/utils/mono-digest.h>
94 #include <mono/utils/bsearch.h>
95 #include <mono/utils/mono-os-mutex.h>
96 #include <mono/utils/mono-threads.h>
98 #if defined (HOST_WIN32)
102 #include "decimal-ms.h"
103 #include "number-ms.h"
105 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
106 #include <sys/utsname.h>
109 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
111 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
113 /* Lazy class loading functions */
114 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
115 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
116 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
119 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
122 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
124 static inline MonoBoolean
125 is_generic_parameter (MonoType *type)
127 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
131 mono_class_init_checked (MonoClass *klass, MonoError *error)
133 mono_error_init (error);
135 if (!mono_class_init (klass))
136 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
139 ICALL_EXPORT MonoObject *
140 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
146 MonoObject *result = NULL;
148 ac = (MonoClass *)arr->obj.vtable->klass;
150 esize = mono_array_element_size (ac);
151 ea = (gpointer*)((char*)arr->vector + (pos * esize));
153 if (ac->element_class->valuetype) {
154 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
155 mono_error_set_pending_exception (&error);
157 result = (MonoObject *)*ea;
161 ICALL_EXPORT MonoObject *
162 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
168 MONO_CHECK_ARG_NULL (idxs, NULL);
171 ic = (MonoClass *)io->obj.vtable->klass;
173 ac = (MonoClass *)arr->obj.vtable->klass;
175 g_assert (ic->rank == 1);
176 if (io->bounds != NULL || io->max_length != ac->rank) {
177 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
181 ind = (gint32 *)io->vector;
183 if (arr->bounds == NULL) {
184 if (*ind < 0 || *ind >= arr->max_length) {
185 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
189 return ves_icall_System_Array_GetValueImpl (arr, *ind);
192 for (i = 0; i < ac->rank; i++) {
193 if ((ind [i] < arr->bounds [i].lower_bound) ||
194 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
195 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
200 pos = ind [0] - arr->bounds [0].lower_bound;
201 for (i = 1; i < ac->rank; i++)
202 pos = pos * arr->bounds [i].length + ind [i] -
203 arr->bounds [i].lower_bound;
205 return ves_icall_System_Array_GetValueImpl (arr, pos);
209 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
212 MonoClass *ac, *vc, *ec;
221 mono_error_init (&error);
224 vc = value->vtable->klass;
228 ac = arr->obj.vtable->klass;
229 ec = ac->element_class;
231 esize = mono_array_element_size (ac);
232 ea = (gpointer*)((char*)arr->vector + (pos * esize));
233 va = (gpointer*)((char*)value + sizeof (MonoObject));
235 if (mono_class_is_nullable (ec)) {
236 mono_nullable_init ((guint8*)ea, value, ec);
241 mono_gc_bzero_atomic (ea, esize);
245 #define NO_WIDENING_CONVERSION G_STMT_START{\
246 mono_set_pending_exception (mono_get_exception_argument ( \
247 "value", "not a widening conversion")); \
251 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
252 if (esize < vsize + (extra)) { \
253 mono_set_pending_exception (mono_get_exception_argument ( \
254 "value", "not a widening conversion")); \
259 #define INVALID_CAST G_STMT_START{ \
260 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
261 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
265 /* Check element (destination) type. */
266 switch (ec->byval_arg.type) {
267 case MONO_TYPE_STRING:
268 switch (vc->byval_arg.type) {
269 case MONO_TYPE_STRING:
275 case MONO_TYPE_BOOLEAN:
276 switch (vc->byval_arg.type) {
277 case MONO_TYPE_BOOLEAN:
290 NO_WIDENING_CONVERSION;
299 if (!ec->valuetype) {
300 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
301 if (mono_error_set_pending_exception (&error))
305 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
309 if (mono_object_isinst_checked (value, ec, &error)) {
310 if (ec->has_references)
311 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
313 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
316 if (mono_error_set_pending_exception (&error))
322 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
324 et = ec->byval_arg.type;
325 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
326 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
328 vt = vc->byval_arg.type;
329 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
330 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
332 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
338 case MONO_TYPE_CHAR: \
339 CHECK_WIDENING_CONVERSION(0); \
340 *(etype *) ea = (etype) u64; \
342 /* You can't assign a signed value to an unsigned array. */ \
347 /* You can't assign a floating point number to an integer array. */ \
350 NO_WIDENING_CONVERSION; \
354 #define ASSIGN_SIGNED(etype) G_STMT_START{\
360 CHECK_WIDENING_CONVERSION(0); \
361 *(etype *) ea = (etype) i64; \
363 /* You can assign an unsigned value to a signed array if the array's */ \
364 /* element size is larger than the value size. */ \
369 case MONO_TYPE_CHAR: \
370 CHECK_WIDENING_CONVERSION(1); \
371 *(etype *) ea = (etype) u64; \
373 /* You can't assign a floating point number to an integer array. */ \
376 NO_WIDENING_CONVERSION; \
380 #define ASSIGN_REAL(etype) G_STMT_START{\
384 CHECK_WIDENING_CONVERSION(0); \
385 *(etype *) ea = (etype) r64; \
387 /* All integer values fit into a floating point array, so we don't */ \
388 /* need to CHECK_WIDENING_CONVERSION here. */ \
393 *(etype *) ea = (etype) i64; \
399 case MONO_TYPE_CHAR: \
400 *(etype *) ea = (etype) u64; \
407 u64 = *(guint8 *) va;
410 u64 = *(guint16 *) va;
413 u64 = *(guint32 *) va;
416 u64 = *(guint64 *) va;
422 i64 = *(gint16 *) va;
425 i64 = *(gint32 *) va;
428 i64 = *(gint64 *) va;
431 r64 = *(gfloat *) va;
434 r64 = *(gdouble *) va;
437 u64 = *(guint16 *) va;
439 case MONO_TYPE_BOOLEAN:
440 /* Boolean is only compatible with itself. */
453 NO_WIDENING_CONVERSION;
460 /* If we can't do a direct copy, let's try a widening conversion. */
463 ASSIGN_UNSIGNED (guint16);
465 ASSIGN_UNSIGNED (guint8);
467 ASSIGN_UNSIGNED (guint16);
469 ASSIGN_UNSIGNED (guint32);
471 ASSIGN_UNSIGNED (guint64);
473 ASSIGN_SIGNED (gint8);
475 ASSIGN_SIGNED (gint16);
477 ASSIGN_SIGNED (gint32);
479 ASSIGN_SIGNED (gint64);
481 ASSIGN_REAL (gfloat);
483 ASSIGN_REAL (gdouble);
487 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
491 #undef NO_WIDENING_CONVERSION
492 #undef CHECK_WIDENING_CONVERSION
493 #undef ASSIGN_UNSIGNED
499 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
505 MONO_CHECK_ARG_NULL (idxs,);
507 ic = idxs->obj.vtable->klass;
508 ac = arr->obj.vtable->klass;
510 g_assert (ic->rank == 1);
511 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
512 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
516 ind = (gint32 *)idxs->vector;
518 if (arr->bounds == NULL) {
519 if (*ind < 0 || *ind >= arr->max_length) {
520 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
524 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
528 for (i = 0; i < ac->rank; i++)
529 if ((ind [i] < arr->bounds [i].lower_bound) ||
530 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
531 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
535 pos = ind [0] - arr->bounds [0].lower_bound;
536 for (i = 1; i < ac->rank; i++)
537 pos = pos * arr->bounds [i].length + ind [i] -
538 arr->bounds [i].lower_bound;
540 ves_icall_System_Array_SetValueImpl (arr, value, pos);
543 ICALL_EXPORT MonoArray *
544 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
547 MonoClass *aklass, *klass;
550 gboolean bounded = FALSE;
552 MONO_CHECK_ARG_NULL (type, NULL);
553 MONO_CHECK_ARG_NULL (lengths, NULL);
555 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
557 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
559 for (i = 0; i < mono_array_length (lengths); i++) {
560 if (mono_array_get (lengths, gint32, i) < 0) {
561 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
566 klass = mono_class_from_mono_type (type->type);
567 mono_class_init_checked (klass, &error);
568 if (mono_error_set_pending_exception (&error))
571 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
572 /* vectors are not the same as one dimensional arrays with no-zero bounds */
577 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
579 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
580 for (i = 0; i < aklass->rank; ++i) {
581 sizes [i] = mono_array_get (lengths, guint32, i);
583 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
585 sizes [i + aklass->rank] = 0;
588 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
589 mono_error_set_pending_exception (&error);
594 ICALL_EXPORT MonoArray *
595 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
598 MonoClass *aklass, *klass;
601 gboolean bounded = FALSE;
603 MONO_CHECK_ARG_NULL (type, NULL);
604 MONO_CHECK_ARG_NULL (lengths, NULL);
606 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
608 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
610 for (i = 0; i < mono_array_length (lengths); i++) {
611 if ((mono_array_get (lengths, gint64, i) < 0) ||
612 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
613 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
618 klass = mono_class_from_mono_type (type->type);
619 mono_class_init_checked (klass, &error);
620 if (mono_error_set_pending_exception (&error))
623 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
624 /* vectors are not the same as one dimensional arrays with no-zero bounds */
629 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
631 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
632 for (i = 0; i < aklass->rank; ++i) {
633 sizes [i] = mono_array_get (lengths, guint64, i);
635 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
637 sizes [i + aklass->rank] = 0;
640 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
641 mono_error_set_pending_exception (&error);
647 ves_icall_System_Array_GetRank (MonoObject *arr)
649 return arr->vtable->klass->rank;
653 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
655 gint32 rank = arr->obj.vtable->klass->rank;
658 if ((dimension < 0) || (dimension >= rank)) {
659 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
663 if (arr->bounds == NULL)
664 length = arr->max_length;
666 length = arr->bounds [dimension].length;
668 #ifdef MONO_BIG_ARRAYS
669 if (length > G_MAXINT32) {
670 mono_set_pending_exception (mono_get_exception_overflow ());
678 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
680 gint32 rank = arr->obj.vtable->klass->rank;
682 if ((dimension < 0) || (dimension >= rank)) {
683 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
687 if (arr->bounds == NULL)
688 return arr->max_length;
690 return arr->bounds [dimension].length;
694 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
696 gint32 rank = arr->obj.vtable->klass->rank;
698 if ((dimension < 0) || (dimension >= rank)) {
699 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
703 if (arr->bounds == NULL)
706 return arr->bounds [dimension].lower_bound;
710 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
712 int sz = mono_array_element_size (mono_object_class (arr));
713 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
716 ICALL_EXPORT 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_MonoType_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1216 mtype->type = &obj->vtable->klass->byval_arg;
1217 g_assert (mtype->type->type);
1221 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1223 MONO_CHECK_ARG_NULL (obj, 0);
1226 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1227 mono_error_set_pending_exception (&error);
1232 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1233 MonoReflectionMethod *method,
1234 MonoArray *opt_param_types)
1236 MONO_CHECK_ARG_NULL (method, 0);
1239 gint32 result = mono_image_create_method_token (
1240 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1241 mono_error_set_pending_exception (&error);
1246 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1249 mono_image_create_pefile (mb, file, &error);
1250 mono_error_set_pending_exception (&error);
1254 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1257 mono_image_build_metadata (mb, &error);
1258 mono_error_set_pending_exception (&error);
1262 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1264 mono_image_register_token (mb->dynamic_image, token, obj);
1267 ICALL_EXPORT MonoObject*
1268 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1272 mono_loader_lock ();
1273 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1274 mono_loader_unlock ();
1279 ICALL_EXPORT MonoReflectionModule*
1280 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1283 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1284 mono_error_set_pending_exception (&error);
1289 * ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class:
1290 * @tb: a TypeBuilder object
1293 * Creates the generic class after all generic parameters have been added.
1296 ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class (MonoReflectionTypeBuilder *tb)
1299 (void) mono_reflection_create_generic_class (tb, &error);
1300 mono_error_set_pending_exception (&error);
1303 #ifndef DISABLE_REFLECTION_EMIT
1304 ICALL_EXPORT MonoArray*
1305 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
1308 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
1309 mono_error_set_pending_exception (&error);
1315 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1317 MonoMethod **dest = (MonoMethod **)data;
1319 /* skip unmanaged frames */
1324 if (!strcmp (m->klass->name_space, "System.Reflection"))
1333 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1335 MonoMethod **dest = (MonoMethod **)data;
1337 /* skip unmanaged frames */
1341 if (m->wrapper_type != MONO_WRAPPER_NONE)
1349 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1360 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1362 MonoMethod **dest = (MonoMethod **)data;
1364 /* skip unmanaged frames */
1368 if (m->wrapper_type != MONO_WRAPPER_NONE)
1376 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1377 || (!strcmp (m->klass->name_space, "System"))))
1387 static MonoReflectionType *
1388 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1390 MonoMethod *m, *dest;
1392 MonoType *type = NULL;
1393 MonoAssembly *assembly = NULL;
1394 gboolean type_resolve = FALSE;
1395 MonoImage *rootimage = NULL;
1397 mono_error_init (error);
1400 * We must compute the calling assembly as type loading must happen under a metadata context.
1401 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1402 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1404 m = mono_method_get_last_managed ();
1406 if (m && m->klass->image != mono_defaults.corlib) {
1407 /* Happens with inlining */
1409 /* Ugly hack: type_from_parsed_name is called from
1410 * System.Type.internal_from_name, which is called most
1411 * directly from System.Type.GetType(string,bool,bool) but
1412 * also indirectly from places such as
1413 * System.Type.GetType(string,func,func) (via
1414 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1415 * so we need to skip over all of those to find the true caller.
1417 * It would be nice if we had stack marks.
1419 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1425 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1426 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1427 * to crash. This only seems to happen in some strange remoting
1428 * scenarios and I was unable to figure out what's happening there.
1429 * Dec 10, 2005 - Martin.
1433 assembly = dest->klass->image->assembly;
1434 type_resolve = TRUE;
1435 rootimage = assembly->image;
1437 g_warning (G_STRLOC);
1440 if (info->assembly.name)
1441 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1444 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1445 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1446 return_val_if_nok (error, NULL);
1450 // Say we're looking for System.Generic.Dict<int, Local>
1451 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1452 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1453 // is messed up when we go to construct the Local as the type arg...
1455 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1456 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1457 if (!info->assembly.name && !type) {
1459 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1460 return_val_if_nok (error, NULL);
1462 if (assembly && !type && type_resolve) {
1463 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1464 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1465 return_val_if_nok (error, NULL);
1471 return mono_type_get_object_checked (mono_domain_get (), type, error);
1474 ICALL_EXPORT MonoReflectionType*
1475 ves_icall_System_Type_internal_from_name (MonoString *name,
1476 MonoBoolean throwOnError,
1477 MonoBoolean ignoreCase)
1480 char *str = mono_string_to_utf8 (name);
1481 MonoTypeNameParse info;
1482 MonoReflectionType *type;
1485 parsedOk = mono_reflection_parse_type (str, &info);
1487 /* mono_reflection_parse_type() mangles the string */
1489 mono_reflection_free_type_info (&info);
1491 mono_error_init (&error);
1492 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1493 mono_error_set_pending_exception (&error);
1499 type = type_from_parsed_name (&info, ignoreCase, &error);
1501 mono_reflection_free_type_info (&info);
1504 if (!mono_error_ok (&error)) {
1506 mono_error_set_pending_exception (&error);
1508 mono_error_cleanup (&error);
1513 MonoException *e = NULL;
1516 e = mono_get_exception_type_load (name, NULL);
1519 mono_set_pending_exception (e);
1528 ICALL_EXPORT MonoReflectionType*
1529 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1532 MonoReflectionType *ret;
1533 MonoDomain *domain = mono_domain_get ();
1535 ret = mono_type_get_object_checked (domain, handle, &error);
1536 mono_error_set_pending_exception (&error);
1541 /* System.TypeCode */
1560 TYPECODE_STRING = 18
1563 ICALL_EXPORT guint32
1564 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1566 int t = type->type->type;
1568 if (type->type->byref)
1569 return TYPECODE_OBJECT;
1573 case MONO_TYPE_VOID:
1574 return TYPECODE_OBJECT;
1575 case MONO_TYPE_BOOLEAN:
1576 return TYPECODE_BOOLEAN;
1578 return TYPECODE_BYTE;
1580 return TYPECODE_SBYTE;
1582 return TYPECODE_UINT16;
1584 return TYPECODE_INT16;
1585 case MONO_TYPE_CHAR:
1586 return TYPECODE_CHAR;
1590 return TYPECODE_OBJECT;
1592 return TYPECODE_UINT32;
1594 return TYPECODE_INT32;
1596 return TYPECODE_UINT64;
1598 return TYPECODE_INT64;
1600 return TYPECODE_SINGLE;
1602 return TYPECODE_DOUBLE;
1603 case MONO_TYPE_VALUETYPE: {
1604 MonoClass *klass = type->type->data.klass;
1606 if (klass->enumtype) {
1607 t = mono_class_enum_basetype (klass)->type;
1609 } else if (mono_is_corlib_image (klass->image)) {
1610 if (strcmp (klass->name_space, "System") == 0) {
1611 if (strcmp (klass->name, "Decimal") == 0)
1612 return TYPECODE_DECIMAL;
1613 else if (strcmp (klass->name, "DateTime") == 0)
1614 return TYPECODE_DATETIME;
1617 return TYPECODE_OBJECT;
1619 case MONO_TYPE_STRING:
1620 return TYPECODE_STRING;
1621 case MONO_TYPE_SZARRAY:
1622 case MONO_TYPE_ARRAY:
1623 case MONO_TYPE_OBJECT:
1625 case MONO_TYPE_MVAR:
1626 case MONO_TYPE_TYPEDBYREF:
1627 return TYPECODE_OBJECT;
1628 case MONO_TYPE_CLASS:
1630 MonoClass *klass = type->type->data.klass;
1631 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1632 if (strcmp (klass->name, "DBNull") == 0)
1633 return TYPECODE_DBNULL;
1636 return TYPECODE_OBJECT;
1637 case MONO_TYPE_GENERICINST:
1638 return TYPECODE_OBJECT;
1640 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1646 mono_type_is_primitive (MonoType *type)
1648 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1649 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1653 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1655 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1656 return mono_class_enum_basetype (type->data.klass);
1657 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1658 return mono_class_enum_basetype (type->data.generic_class->container_class);
1662 ICALL_EXPORT guint32
1663 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1668 g_assert (type != NULL);
1670 klass = mono_class_from_mono_type (type->type);
1671 klassc = mono_class_from_mono_type (c->type);
1673 if (type->type->byref ^ c->type->byref)
1676 if (type->type->byref) {
1677 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1678 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1680 klass = mono_class_from_mono_type (t);
1681 klassc = mono_class_from_mono_type (ot);
1683 if (mono_type_is_primitive (t)) {
1684 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1685 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1686 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1687 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1688 return t->type == ot->type;
1690 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1693 if (klass->valuetype)
1694 return klass == klassc;
1695 return klass->valuetype == klassc->valuetype;
1698 return mono_class_is_assignable_from (klass, klassc);
1701 ICALL_EXPORT guint32
1702 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1705 MonoClass *klass = mono_class_from_mono_type (type->type);
1706 mono_class_init_checked (klass, &error);
1707 if (!is_ok (&error)) {
1708 mono_error_set_pending_exception (&error);
1711 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1712 mono_error_set_pending_exception (&error);
1716 ICALL_EXPORT guint32
1717 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1719 MonoClass *klass = mono_class_from_mono_type (type->type);
1720 return klass->flags;
1723 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1724 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1727 MonoClass *klass = field->field->parent;
1728 MonoMarshalType *info;
1732 if (klass->generic_container ||
1733 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1736 ftype = mono_field_get_type (field->field);
1737 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1740 info = mono_marshal_load_type_info (klass);
1742 for (i = 0; i < info->num_fields; ++i) {
1743 if (info->fields [i].field == field->field) {
1744 if (!info->fields [i].mspec)
1747 MonoReflectionMarshalAsAttribute* obj;
1748 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1749 if (!mono_error_ok (&error))
1750 mono_error_set_pending_exception (&error);
1759 ICALL_EXPORT MonoReflectionField*
1760 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1763 gboolean found = FALSE;
1770 klass = handle->parent;
1772 klass = mono_class_from_mono_type (type);
1774 /* Check that the field belongs to the class */
1775 for (k = klass; k; k = k->parent) {
1776 if (k == handle->parent) {
1783 /* The managed code will throw the exception */
1787 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1788 mono_error_set_pending_exception (&error);
1792 ICALL_EXPORT MonoArray*
1793 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1796 MonoType *type = mono_field_get_type_checked (field->field, &error);
1799 if (!mono_error_ok (&error)) {
1800 mono_error_set_pending_exception (&error);
1804 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1805 mono_error_set_pending_exception (&error);
1810 vell_icall_get_method_attributes (MonoMethod *method)
1812 return method->flags;
1816 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1819 MonoReflectionType *rt;
1820 MonoDomain *domain = mono_domain_get ();
1821 MonoMethodSignature* sig;
1823 sig = mono_method_signature_checked (method, &error);
1824 if (!mono_error_ok (&error)) {
1825 mono_error_set_pending_exception (&error);
1829 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1830 if (!mono_error_ok (&error)) {
1831 mono_error_set_pending_exception (&error);
1835 MONO_STRUCT_SETREF (info, parent, rt);
1837 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1838 if (!mono_error_ok (&error)) {
1839 mono_error_set_pending_exception (&error);
1843 MONO_STRUCT_SETREF (info, ret, rt);
1845 info->attrs = method->flags;
1846 info->implattrs = method->iflags;
1847 if (sig->call_convention == MONO_CALL_DEFAULT)
1848 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1850 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1855 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1858 ICALL_EXPORT MonoArray*
1859 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1862 MonoDomain *domain = mono_domain_get ();
1864 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1865 mono_error_set_pending_exception (&error);
1869 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1870 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1873 MonoDomain *domain = mono_domain_get ();
1874 MonoReflectionMarshalAsAttribute* res = NULL;
1875 MonoMarshalSpec **mspecs;
1878 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1879 mono_method_get_marshal_info (method, mspecs);
1882 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1883 if (!mono_error_ok (&error)) {
1884 mono_error_set_pending_exception (&error);
1889 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1891 mono_metadata_free_marshal_spec (mspecs [i]);
1898 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1900 MonoClass *parent = field->field->parent;
1901 if (!parent->size_inited)
1902 mono_class_init (parent);
1903 mono_class_setup_fields_locking (parent);
1905 return field->field->offset - sizeof (MonoObject);
1908 ICALL_EXPORT MonoReflectionType*
1909 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1912 MonoReflectionType *ret;
1915 parent = declaring? field->field->parent: field->klass;
1917 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1918 mono_error_set_pending_exception (&error);
1924 ICALL_EXPORT MonoObject *
1925 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1928 MonoClass *fklass = field->klass;
1929 MonoClassField *cf = field->field;
1930 MonoDomain *domain = mono_object_domain (field);
1932 if (fklass->image->assembly->ref_only) {
1933 mono_set_pending_exception (mono_get_exception_invalid_operation (
1934 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1938 if (mono_security_core_clr_enabled () &&
1939 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1940 mono_error_set_pending_exception (&error);
1944 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1945 mono_error_set_pending_exception (&error);
1950 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1953 MonoClassField *cf = field->field;
1957 if (field->klass->image->assembly->ref_only) {
1958 mono_set_pending_exception (mono_get_exception_invalid_operation (
1959 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1963 if (mono_security_core_clr_enabled () &&
1964 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1965 mono_error_set_pending_exception (&error);
1969 type = mono_field_get_type_checked (cf, &error);
1970 if (!mono_error_ok (&error)) {
1971 mono_error_set_pending_exception (&error);
1975 v = (gchar *) value;
1977 switch (type->type) {
1980 case MONO_TYPE_BOOLEAN:
1983 case MONO_TYPE_CHAR:
1992 case MONO_TYPE_VALUETYPE:
1995 v += sizeof (MonoObject);
1997 case MONO_TYPE_STRING:
1998 case MONO_TYPE_OBJECT:
1999 case MONO_TYPE_CLASS:
2000 case MONO_TYPE_ARRAY:
2001 case MONO_TYPE_SZARRAY:
2004 case MONO_TYPE_GENERICINST: {
2005 MonoGenericClass *gclass = type->data.generic_class;
2006 g_assert (!gclass->context.class_inst->is_open);
2008 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
2009 MonoClass *nklass = mono_class_from_mono_type (type);
2010 MonoObject *nullable;
2013 * Convert the boxed vtype into a Nullable structure.
2014 * This is complicated by the fact that Nullables have
2015 * a variable structure.
2017 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2018 if (!mono_error_ok (&error)) {
2019 mono_error_set_pending_exception (&error);
2023 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2025 v = (gchar *)mono_object_unbox (nullable);
2028 if (gclass->container_class->valuetype && (v != NULL))
2029 v += sizeof (MonoObject);
2033 g_error ("type 0x%x not handled in "
2034 "ves_icall_FieldInfo_SetValueInternal", type->type);
2039 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2040 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2041 if (!is_ok (&error)) {
2042 mono_error_set_pending_exception (&error);
2045 if (!vtable->initialized) {
2046 if (!mono_runtime_class_init_full (vtable, &error)) {
2047 mono_error_set_pending_exception (&error);
2051 mono_field_static_set_value (vtable, cf, v);
2053 mono_field_set_value (obj, cf, v);
2058 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2067 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2068 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2072 if (MONO_TYPE_IS_REFERENCE (f->type))
2073 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2075 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2078 ICALL_EXPORT MonoObject *
2079 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2081 MonoObject *o = NULL;
2082 MonoClassField *field = rfield->field;
2084 MonoDomain *domain = mono_object_domain (rfield);
2086 MonoTypeEnum def_type;
2087 const char *def_value;
2091 mono_class_init (field->parent);
2093 t = mono_field_get_type_checked (field, &error);
2094 if (!mono_error_ok (&error)) {
2095 mono_error_set_pending_exception (&error);
2099 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2100 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2104 if (image_is_dynamic (field->parent->image)) {
2105 MonoClass *klass = field->parent;
2106 int fidx = field - klass->fields;
2108 g_assert (fidx >= 0 && fidx < klass->field.count);
2109 g_assert (klass->ext);
2110 g_assert (klass->ext->field_def_values);
2111 def_type = klass->ext->field_def_values [fidx].def_type;
2112 def_value = klass->ext->field_def_values [fidx].data;
2113 if (def_type == MONO_TYPE_END) {
2114 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2118 def_value = mono_class_get_field_default_value (field, &def_type);
2119 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2121 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2126 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2130 case MONO_TYPE_BOOLEAN:
2133 case MONO_TYPE_CHAR:
2141 case MONO_TYPE_R8: {
2144 /* boxed value type */
2145 t = g_new0 (MonoType, 1);
2147 klass = mono_class_from_mono_type (t);
2149 o = mono_object_new_checked (domain, klass, &error);
2150 if (!mono_error_ok (&error)) {
2151 mono_error_set_pending_exception (&error);
2154 v = ((gchar *) o) + sizeof (MonoObject);
2155 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2156 if (mono_error_set_pending_exception (&error))
2160 case MONO_TYPE_STRING:
2161 case MONO_TYPE_CLASS:
2162 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2163 if (mono_error_set_pending_exception (&error))
2167 g_assert_not_reached ();
2173 ICALL_EXPORT MonoReflectionType*
2174 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2177 MonoReflectionType *ret;
2180 type = mono_field_get_type_checked (ref_field->field, &error);
2181 if (!mono_error_ok (&error)) {
2182 mono_error_set_pending_exception (&error);
2186 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2187 if (!mono_error_ok (&error)) {
2188 mono_error_set_pending_exception (&error);
2195 /* From MonoProperty.cs */
2197 PInfo_Attributes = 1,
2198 PInfo_GetMethod = 1 << 1,
2199 PInfo_SetMethod = 1 << 2,
2200 PInfo_ReflectedType = 1 << 3,
2201 PInfo_DeclaringType = 1 << 4,
2206 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2209 MonoReflectionType *rt;
2210 MonoReflectionMethod *rm;
2211 MonoDomain *domain = mono_object_domain (property);
2212 const MonoProperty *pproperty = property->property;
2214 if ((req_info & PInfo_ReflectedType) != 0) {
2215 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2216 if (mono_error_set_pending_exception (&error))
2219 MONO_STRUCT_SETREF (info, parent, rt);
2221 if ((req_info & PInfo_DeclaringType) != 0) {
2222 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2223 if (mono_error_set_pending_exception (&error))
2226 MONO_STRUCT_SETREF (info, declaring_type, rt);
2229 if ((req_info & PInfo_Name) != 0)
2230 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2232 if ((req_info & PInfo_Attributes) != 0)
2233 info->attrs = pproperty->attrs;
2235 if ((req_info & PInfo_GetMethod) != 0) {
2236 if (pproperty->get &&
2237 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2238 pproperty->get->klass == property->klass)) {
2239 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2240 if (mono_error_set_pending_exception (&error))
2246 MONO_STRUCT_SETREF (info, get, rm);
2248 if ((req_info & PInfo_SetMethod) != 0) {
2249 if (pproperty->set &&
2250 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2251 pproperty->set->klass == property->klass)) {
2252 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2253 if (mono_error_set_pending_exception (&error))
2259 MONO_STRUCT_SETREF (info, set, rm);
2262 * There may be other methods defined for properties, though, it seems they are not exposed
2263 * in the reflection API
2268 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2271 MonoReflectionType *rt;
2272 MonoReflectionMethod *rm;
2273 MonoDomain *domain = mono_object_domain (event);
2275 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2276 if (mono_error_set_pending_exception (&error))
2279 MONO_STRUCT_SETREF (info, reflected_type, rt);
2281 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2282 if (mono_error_set_pending_exception (&error))
2285 MONO_STRUCT_SETREF (info, declaring_type, rt);
2287 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2288 info->attrs = event->event->attrs;
2290 if (event->event->add) {
2291 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2292 if (mono_error_set_pending_exception (&error))
2298 MONO_STRUCT_SETREF (info, add_method, rm);
2300 if (event->event->remove) {
2301 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2302 if (mono_error_set_pending_exception (&error))
2308 MONO_STRUCT_SETREF (info, remove_method, rm);
2310 if (event->event->raise) {
2311 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2312 if (mono_error_set_pending_exception (&error))
2318 MONO_STRUCT_SETREF (info, raise_method, rm);
2320 #ifndef MONO_SMALL_CONFIG
2321 if (event->event->other) {
2323 while (event->event->other [n])
2325 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2326 if (mono_error_set_pending_exception (&error))
2328 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2330 for (i = 0; i < n; i++) {
2331 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2332 if (mono_error_set_pending_exception (&error))
2334 mono_array_setref (info->other_methods, i, rm);
2341 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2346 mono_class_setup_interfaces (klass, error);
2347 if (!mono_error_ok (error))
2350 for (i = 0; i < klass->interface_count; i++) {
2351 ic = klass->interfaces [i];
2352 g_hash_table_insert (ifaces, ic, ic);
2354 collect_interfaces (ic, ifaces, error);
2355 if (!mono_error_ok (error))
2361 MonoArray *iface_array;
2362 MonoGenericContext *context;
2366 } FillIfaceArrayData;
2369 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2371 MonoReflectionType *rt;
2372 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2373 MonoClass *ic = (MonoClass *)key;
2374 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2376 if (!mono_error_ok (data->error))
2379 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2380 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2381 if (!mono_error_ok (data->error))
2385 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2386 if (!mono_error_ok (data->error))
2389 mono_array_setref (data->iface_array, data->next_idx++, rt);
2392 mono_metadata_free_type (inflated);
2396 get_interfaces_hash (gconstpointer v1)
2398 MonoClass *k = (MonoClass*)v1;
2400 return k->type_token;
2403 ICALL_EXPORT MonoArray*
2404 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2407 MonoClass *klass = mono_class_from_mono_type (type->type);
2409 FillIfaceArrayData data = { 0 };
2412 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2414 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2415 data.context = mono_class_get_context (klass);
2416 klass = klass->generic_class->container_class;
2419 for (parent = klass; parent; parent = parent->parent) {
2420 mono_class_setup_interfaces (parent, &error);
2421 if (!mono_error_ok (&error))
2423 collect_interfaces (parent, iface_hash, &error);
2424 if (!mono_error_ok (&error))
2428 data.error = &error;
2429 data.domain = mono_object_domain (type);
2431 len = g_hash_table_size (iface_hash);
2433 g_hash_table_destroy (iface_hash);
2434 if (!data.domain->empty_types) {
2435 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0, &error);
2436 if (!is_ok (&error))
2439 return data.domain->empty_types;
2442 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len, &error);
2443 if (!is_ok (&error))
2445 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2446 if (!mono_error_ok (&error))
2449 g_hash_table_destroy (iface_hash);
2450 return data.iface_array;
2453 g_hash_table_destroy (iface_hash);
2454 mono_error_set_pending_exception (&error);
2459 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2461 gboolean variance_used;
2462 MonoClass *klass = mono_class_from_mono_type (type->type);
2463 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2464 MonoReflectionMethod *member;
2467 int i = 0, len, ioffset;
2471 mono_class_init_checked (klass, &error);
2472 if (mono_error_set_pending_exception (&error))
2474 mono_class_init_checked (iclass, &error);
2475 if (mono_error_set_pending_exception (&error))
2478 mono_class_setup_vtable (klass);
2480 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2484 len = mono_class_num_methods (iclass);
2485 domain = mono_object_domain (type);
2486 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2487 if (mono_error_set_pending_exception (&error))
2489 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2490 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2491 if (mono_error_set_pending_exception (&error))
2493 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2495 while ((method = mono_class_get_methods (iclass, &iter))) {
2496 member = mono_method_get_object_checked (domain, method, iclass, &error);
2497 if (mono_error_set_pending_exception (&error))
2499 mono_array_setref (*methods, i, member);
2500 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2501 if (mono_error_set_pending_exception (&error))
2503 mono_array_setref (*targets, i, member);
2510 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2513 MonoClass *klass = mono_class_from_mono_type (type->type);
2515 mono_class_init_checked (klass, &error);
2516 if (mono_error_set_pending_exception (&error))
2519 if (image_is_dynamic (klass->image)) {
2520 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2521 *packing = tb->packing_size;
2522 *size = tb->class_size;
2524 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2528 ICALL_EXPORT MonoReflectionType*
2529 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2532 MonoReflectionType *ret;
2535 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2536 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2537 mono_error_set_pending_exception (&error);
2541 klass = mono_class_from_mono_type (type->type);
2542 mono_class_init_checked (klass, &error);
2543 if (mono_error_set_pending_exception (&error))
2547 // GetElementType should only return a type for:
2548 // Array Pointer PassedByRef
2549 if (type->type->byref)
2550 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2551 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2552 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2553 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2554 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2558 mono_error_set_pending_exception (&error);
2563 ICALL_EXPORT MonoReflectionType*
2564 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2567 MonoReflectionType *ret;
2569 if (type->type->byref)
2572 MonoClass *klass = mono_class_from_mono_type (type->type);
2576 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2577 mono_error_set_pending_exception (&error);
2582 ICALL_EXPORT MonoBoolean
2583 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2585 return type->type->type == MONO_TYPE_PTR;
2588 ICALL_EXPORT MonoBoolean
2589 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2591 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)));
2594 ICALL_EXPORT MonoBoolean
2595 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2597 return type->type->byref;
2600 ICALL_EXPORT MonoBoolean
2601 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2604 MonoClass *klass = mono_class_from_mono_type (type->type);
2605 mono_class_init_checked (klass, &error);
2606 if (mono_error_set_pending_exception (&error))
2609 return mono_class_is_com_object (klass);
2612 ICALL_EXPORT guint32
2613 ves_icall_reflection_get_token (MonoObject* obj)
2616 guint32 result = mono_reflection_get_token_checked (obj, &error);
2617 mono_error_set_pending_exception (&error);
2621 ICALL_EXPORT MonoReflectionModule*
2622 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2625 MonoReflectionModule *result = NULL;
2626 MonoClass *klass = mono_class_from_mono_type (type->type);
2627 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2628 mono_error_set_pending_exception (&error);
2632 ICALL_EXPORT MonoReflectionAssembly*
2633 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2636 MonoDomain *domain = mono_domain_get ();
2637 MonoClass *klass = mono_class_from_mono_type (type->type);
2638 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2639 mono_error_set_pending_exception (&error);
2643 ICALL_EXPORT MonoReflectionType*
2644 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2647 MonoReflectionType *ret;
2648 MonoDomain *domain = mono_domain_get ();
2651 if (type->type->byref)
2653 if (type->type->type == MONO_TYPE_VAR) {
2654 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2655 klass = param ? param->owner.klass : NULL;
2656 } else if (type->type->type == MONO_TYPE_MVAR) {
2657 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2658 klass = param ? param->owner.method->klass : NULL;
2660 klass = mono_class_from_mono_type (type->type)->nested_in;
2666 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2667 mono_error_set_pending_exception (&error);
2672 ICALL_EXPORT MonoString*
2673 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2675 MonoDomain *domain = mono_domain_get ();
2676 MonoClass *klass = mono_class_from_mono_type (type->type);
2678 if (type->type->byref) {
2679 char *n = g_strdup_printf ("%s&", klass->name);
2680 MonoString *res = mono_string_new (domain, n);
2686 return mono_string_new (domain, klass->name);
2690 ICALL_EXPORT MonoString*
2691 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2693 MonoDomain *domain = mono_domain_get ();
2694 MonoClass *klass = mono_class_from_mono_type (type->type);
2696 while (klass->nested_in)
2697 klass = klass->nested_in;
2699 if (klass->name_space [0] == '\0')
2702 return mono_string_new (domain, klass->name_space);
2706 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2710 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2711 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2715 klass = mono_class_from_mono_type (type->type);
2721 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2723 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2726 ICALL_EXPORT MonoArray*
2727 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2730 MonoReflectionType *rt;
2732 MonoClass *klass, *pklass;
2733 MonoDomain *domain = mono_object_domain (type);
2736 klass = mono_class_from_mono_type (type->type);
2738 if (klass->generic_container) {
2739 MonoGenericContainer *container = klass->generic_container;
2740 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2741 if (mono_error_set_pending_exception (&error))
2743 for (i = 0; i < container->type_argc; ++i) {
2744 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2746 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2747 if (mono_error_set_pending_exception (&error))
2750 mono_array_setref (res, i, rt);
2752 } else if (klass->generic_class) {
2753 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2754 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2755 if (mono_error_set_pending_exception (&error))
2757 for (i = 0; i < inst->type_argc; ++i) {
2758 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2759 if (mono_error_set_pending_exception (&error))
2762 mono_array_setref (res, i, rt);
2770 ICALL_EXPORT gboolean
2771 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2775 if (!IS_MONOTYPE (type))
2778 if (type->type->byref)
2781 klass = mono_class_from_mono_type (type->type);
2782 return klass->generic_container != NULL;
2785 ICALL_EXPORT MonoReflectionType*
2786 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2789 MonoReflectionType *ret;
2792 if (type->type->byref)
2795 klass = mono_class_from_mono_type (type->type);
2797 if (klass->generic_container) {
2798 return type; /* check this one */
2800 if (klass->generic_class) {
2801 MonoClass *generic_class = klass->generic_class->container_class;
2804 tb = mono_class_get_ref_info (generic_class);
2806 if (generic_class->wastypebuilder && tb)
2807 return (MonoReflectionType *)tb;
2809 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2810 mono_error_set_pending_exception (&error);
2818 ICALL_EXPORT MonoReflectionType*
2819 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2822 MonoReflectionType *ret;
2824 MonoType *geninst, **types;
2827 g_assert (IS_MONOTYPE (type));
2828 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2829 if (mono_error_set_pending_exception (&error))
2832 count = mono_array_length (type_array);
2833 types = g_new0 (MonoType *, count);
2835 for (i = 0; i < count; i++) {
2836 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2837 types [i] = t->type;
2840 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2843 mono_error_set_pending_exception (&error);
2847 klass = mono_class_from_mono_type (geninst);
2849 /*we might inflate to the GTD*/
2850 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2851 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2855 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2856 mono_error_set_pending_exception (&error);
2861 ICALL_EXPORT gboolean
2862 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2866 if (!IS_MONOTYPE (type))
2869 if (type->type->byref)
2872 klass = mono_class_from_mono_type (type->type);
2873 return klass->generic_class != NULL || klass->generic_container != NULL;
2877 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2879 if (!IS_MONOTYPE (type))
2882 if (is_generic_parameter (type->type))
2883 return mono_type_get_generic_param_num (type->type);
2887 ICALL_EXPORT GenericParameterAttributes
2888 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2890 g_assert (IS_MONOTYPE (type));
2891 g_assert (is_generic_parameter (type->type));
2892 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2895 ICALL_EXPORT MonoArray *
2896 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2899 MonoReflectionType *rt;
2900 MonoGenericParamInfo *param_info;
2906 g_assert (IS_MONOTYPE (type));
2908 domain = mono_object_domain (type);
2909 param_info = mono_generic_param_info (type->type->data.generic_param);
2910 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2913 res = mono_array_new_checked (domain, mono_defaults.monotype_class, count, &error);
2914 if (mono_error_set_pending_exception (&error))
2916 for (i = 0; i < count; i++) {
2917 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2918 if (mono_error_set_pending_exception (&error))
2921 mono_array_setref (res, i, rt);
2928 ICALL_EXPORT MonoBoolean
2929 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2931 return is_generic_parameter (type->type);
2934 ICALL_EXPORT MonoBoolean
2935 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2937 return is_generic_parameter (tb->type.type);
2941 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2942 MonoReflectionType *t)
2944 enumtype->type = t->type;
2947 ICALL_EXPORT MonoReflectionMethod*
2948 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2949 MonoReflectionMethod* generic)
2956 MonoReflectionMethod *ret = NULL;
2958 domain = ((MonoObject *)type)->vtable->domain;
2960 klass = mono_class_from_mono_type (type->type);
2961 mono_class_init_checked (klass, &error);
2962 if (mono_error_set_pending_exception (&error))
2966 while ((method = mono_class_get_methods (klass, &iter))) {
2967 if (method->token == generic->method->token) {
2968 ret = mono_method_get_object_checked (domain, method, klass, &error);
2969 if (mono_error_set_pending_exception (&error))
2977 ICALL_EXPORT MonoReflectionMethod *
2978 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2981 MonoType *type = ref_type->type;
2983 MonoReflectionMethod *ret = NULL;
2985 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2986 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2989 if (type->type == MONO_TYPE_VAR)
2992 method = mono_type_get_generic_param_owner (type)->owner.method;
2995 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2996 if (!mono_error_ok (&error))
2997 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3001 ICALL_EXPORT MonoBoolean
3002 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
3004 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3008 ICALL_EXPORT MonoBoolean
3009 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
3011 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3016 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
3018 MonoDomain *domain = mono_domain_get ();
3019 MonoImage *image = method->method->klass->image;
3020 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
3021 MonoTableInfo *tables = image->tables;
3022 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
3023 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
3024 guint32 im_cols [MONO_IMPLMAP_SIZE];
3025 guint32 scope_token;
3026 const char *import = NULL;
3027 const char *scope = NULL;
3029 if (image_is_dynamic (image)) {
3030 MonoReflectionMethodAux *method_aux =
3031 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
3033 import = method_aux->dllentry;
3034 scope = method_aux->dll;
3037 if (!import || !scope) {
3038 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
3043 if (piinfo->implmap_idx) {
3044 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
3046 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
3047 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
3048 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
3049 scope = mono_metadata_string_heap (image, scope_token);
3053 *flags = piinfo->piflags;
3054 *entry_point = mono_string_new (domain, import);
3055 *dll_name = mono_string_new (domain, scope);
3058 ICALL_EXPORT MonoReflectionMethod *
3059 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3061 MonoMethodInflated *imethod;
3063 MonoReflectionMethod *ret = NULL;
3066 if (method->method->is_generic)
3069 if (!method->method->is_inflated)
3072 imethod = (MonoMethodInflated *) method->method;
3074 result = imethod->declaring;
3075 /* Not a generic method. */
3076 if (!result->is_generic)
3079 if (image_is_dynamic (method->method->klass->image)) {
3080 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3081 MonoReflectionMethod *res;
3084 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3085 * the dynamic case as well ?
3087 mono_image_lock ((MonoImage*)image);
3088 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3089 mono_image_unlock ((MonoImage*)image);
3095 if (imethod->context.class_inst) {
3096 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3097 /*Generic methods gets the context of the GTD.*/
3098 if (mono_class_get_context (klass)) {
3099 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3100 if (!mono_error_ok (&error))
3105 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3107 if (!mono_error_ok (&error))
3108 mono_error_set_pending_exception (&error);
3112 ICALL_EXPORT gboolean
3113 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3115 return mono_method_signature (method->method)->generic_param_count != 0;
3118 ICALL_EXPORT gboolean
3119 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3121 return method->method->is_generic;
3124 ICALL_EXPORT MonoArray*
3125 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3128 MonoReflectionType *rt;
3133 domain = mono_object_domain (method);
3135 if (method->method->is_inflated) {
3136 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3139 count = inst->type_argc;
3140 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3141 if (mono_error_set_pending_exception (&error))
3144 for (i = 0; i < count; i++) {
3145 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3146 if (mono_error_set_pending_exception (&error))
3149 mono_array_setref (res, i, rt);
3156 count = mono_method_signature (method->method)->generic_param_count;
3157 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3158 if (mono_error_set_pending_exception (&error))
3161 for (i = 0; i < count; i++) {
3162 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3163 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3164 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3166 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3167 if (mono_error_set_pending_exception (&error))
3170 mono_array_setref (res, i, rt);
3176 ICALL_EXPORT MonoObject *
3177 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3181 * Invoke from reflection is supposed to always be a virtual call (the API
3182 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3183 * greater flexibility.
3185 MonoMethod *m = method->method;
3186 MonoMethodSignature *sig = mono_method_signature (m);
3189 void *obj = this_arg;
3193 if (mono_security_core_clr_enabled () &&
3194 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3195 mono_error_set_pending_exception (&error);
3199 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3200 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3201 mono_error_cleanup (&error); /* FIXME does this make sense? */
3202 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3207 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3208 if (!is_ok (&error)) {
3209 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3212 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3213 char *target_name = mono_type_get_full_name (m->klass);
3214 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3215 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3217 g_free (target_name);
3221 m = mono_object_get_virtual_method (this_arg, m);
3222 /* must pass the pointer to the value for valuetype methods */
3223 if (m->klass->valuetype)
3224 obj = mono_object_unbox (this_arg);
3225 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3226 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3231 if (sig->ret->byref) {
3232 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"));
3236 pcount = params? mono_array_length (params): 0;
3237 if (pcount != sig->param_count) {
3238 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3242 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3243 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."));
3247 image = m->klass->image;
3248 if (image->assembly->ref_only) {
3249 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."));
3253 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3254 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3258 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3262 intptr_t *lower_bounds;
3263 pcount = mono_array_length (params);
3264 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3265 /* Note: the synthetized array .ctors have int32 as argument type */
3266 for (i = 0; i < pcount; ++i)
3267 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3269 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3270 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3271 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3272 if (!mono_error_ok (&error)) {
3273 mono_error_set_pending_exception (&error);
3277 for (i = 0; i < mono_array_length (arr); ++i) {
3278 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3279 if (!mono_error_ok (&error)) {
3280 mono_error_set_pending_exception (&error);
3283 mono_array_setref_fast (arr, i, subarray);
3285 return (MonoObject*)arr;
3288 if (m->klass->rank == pcount) {
3289 /* Only lengths provided. */
3290 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3291 if (!mono_error_ok (&error)) {
3292 mono_error_set_pending_exception (&error);
3296 return (MonoObject*)arr;
3298 g_assert (pcount == (m->klass->rank * 2));
3299 /* The arguments are lower-bound-length pairs */
3300 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3302 for (i = 0; i < pcount / 2; ++i) {
3303 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3304 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3307 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3308 if (!mono_error_ok (&error)) {
3309 mono_error_set_pending_exception (&error);
3313 return (MonoObject*)arr;
3316 return mono_runtime_invoke_array (m, obj, params, NULL);
3319 #ifndef DISABLE_REMOTING
3320 ICALL_EXPORT MonoObject *
3321 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3324 MonoDomain *domain = mono_object_domain (method);
3325 MonoMethod *m = method->method;
3326 MonoMethodSignature *sig = mono_method_signature (m);
3327 MonoArray *out_args;
3329 int i, j, outarg_count = 0;
3331 if (m->klass == mono_defaults.object_class) {
3332 if (!strcmp (m->name, "FieldGetter")) {
3333 MonoClass *k = this_arg->vtable->klass;
3337 /* If this is a proxy, then it must be a CBO */
3338 if (k == mono_defaults.transparent_proxy_class) {
3339 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3340 this_arg = tp->rp->unwrapped_server;
3341 g_assert (this_arg);
3342 k = this_arg->vtable->klass;
3345 name = mono_array_get (params, MonoString *, 1);
3346 str = mono_string_to_utf8 (name);
3349 MonoClassField* field = mono_class_get_field_from_name (k, str);
3352 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3353 if (field_klass->valuetype) {
3354 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3355 if (mono_error_set_pending_exception (&error))
3358 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3360 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3361 if (mono_error_set_pending_exception (&error))
3363 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3364 mono_array_setref (out_args, 0, result);
3371 g_assert_not_reached ();
3373 } else if (!strcmp (m->name, "FieldSetter")) {
3374 MonoClass *k = this_arg->vtable->klass;
3380 /* If this is a proxy, then it must be a CBO */
3381 if (k == mono_defaults.transparent_proxy_class) {
3382 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3383 this_arg = tp->rp->unwrapped_server;
3384 g_assert (this_arg);
3385 k = this_arg->vtable->klass;
3388 name = mono_array_get (params, MonoString *, 1);
3389 str = mono_string_to_utf8 (name);
3392 MonoClassField* field = mono_class_get_field_from_name (k, str);
3395 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3396 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3398 if (field_klass->valuetype) {
3399 size = mono_type_size (field->type, &align);
3400 g_assert (size == mono_class_value_size (field_klass, NULL));
3401 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3403 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3406 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3407 if (mono_error_set_pending_exception (&error))
3409 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3418 g_assert_not_reached ();
3423 for (i = 0; i < mono_array_length (params); i++) {
3424 if (sig->params [i]->byref)
3428 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3429 if (mono_error_set_pending_exception (&error))
3432 /* handle constructors only for objects already allocated */
3433 if (!strcmp (method->method->name, ".ctor"))
3434 g_assert (this_arg);
3436 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3437 g_assert (!method->method->klass->valuetype);
3438 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3440 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3441 if (sig->params [i]->byref) {
3443 arg = mono_array_get (params, gpointer, i);
3444 mono_array_setref (out_args, j, arg);
3449 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3456 read_enum_value (const char *mem, int type)
3459 case MONO_TYPE_BOOLEAN:
3461 return *(guint8*)mem;
3463 return *(gint8*)mem;
3464 case MONO_TYPE_CHAR:
3466 return read16 (mem);
3468 return (gint16) read16 (mem);
3470 return read32 (mem);
3472 return (gint32) read32 (mem);
3475 return read64 (mem);
3477 g_assert_not_reached ();
3483 write_enum_value (char *mem, int type, guint64 value)
3487 case MONO_TYPE_I1: {
3488 guint8 *p = (guint8*)mem;
3494 case MONO_TYPE_CHAR: {
3495 guint16 *p = (guint16 *)mem;
3500 case MONO_TYPE_I4: {
3501 guint32 *p = (guint32 *)mem;
3506 case MONO_TYPE_I8: {
3507 guint64 *p = (guint64 *)mem;
3512 g_assert_not_reached ();
3517 ICALL_EXPORT MonoObject *
3518 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3526 domain = mono_object_domain (enumType);
3527 enumc = mono_class_from_mono_type (enumType->type);
3529 mono_class_init_checked (enumc, &error);
3530 if (mono_error_set_pending_exception (&error))
3533 etype = mono_class_enum_basetype (enumc);
3535 res = mono_object_new_checked (domain, enumc, &error);
3536 if (mono_error_set_pending_exception (&error))
3538 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3543 ICALL_EXPORT MonoBoolean
3544 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3546 int size = mono_class_value_size (a->vtable->klass, NULL);
3547 guint64 a_val = 0, b_val = 0;
3549 memcpy (&a_val, mono_object_unbox (a), size);
3550 memcpy (&b_val, mono_object_unbox (b), size);
3552 return (a_val & b_val) == b_val;
3555 ICALL_EXPORT MonoObject *
3556 ves_icall_System_Enum_get_value (MonoObject *eobj)
3568 g_assert (eobj->vtable->klass->enumtype);
3570 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3571 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3572 if (mono_error_set_pending_exception (&error))
3574 dst = (char *)res + sizeof (MonoObject);
3575 src = (char *)eobj + sizeof (MonoObject);
3576 size = mono_class_value_size (enumc, NULL);
3578 memcpy (dst, src, size);
3583 ICALL_EXPORT MonoReflectionType *
3584 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3587 MonoReflectionType *ret;
3591 klass = mono_class_from_mono_type (type->type);
3592 mono_class_init_checked (klass, &error);
3593 if (mono_error_set_pending_exception (&error))
3596 etype = mono_class_enum_basetype (klass);
3598 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3602 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3603 mono_error_set_pending_exception (&error);
3609 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3611 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3612 gpointer odata = (char *)other + sizeof (MonoObject);
3613 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3614 g_assert (basetype);
3619 if (eobj->vtable->klass != other->vtable->klass)
3622 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3623 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3624 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3627 return me > other ? 1 : -1; \
3630 switch (basetype->type) {
3632 COMPARE_ENUM_VALUES (guint8);
3634 COMPARE_ENUM_VALUES (gint8);
3635 case MONO_TYPE_CHAR:
3637 COMPARE_ENUM_VALUES (guint16);
3639 COMPARE_ENUM_VALUES (gint16);
3641 COMPARE_ENUM_VALUES (guint32);
3643 COMPARE_ENUM_VALUES (gint32);
3645 COMPARE_ENUM_VALUES (guint64);
3647 COMPARE_ENUM_VALUES (gint64);
3651 #undef COMPARE_ENUM_VALUES
3652 /* indicates that the enum was of an unsupported unerlying type */
3657 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3659 gpointer data = (char *)eobj + sizeof (MonoObject);
3660 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3661 g_assert (basetype);
3663 switch (basetype->type) {
3664 case MONO_TYPE_I1: {
3665 gint8 value = *((gint8*)data);
3666 return ((int)value ^ (int)value << 8);
3669 return *((guint8*)data);
3670 case MONO_TYPE_CHAR:
3672 return *((guint16*)data);
3674 case MONO_TYPE_I2: {
3675 gint16 value = *((gint16*)data);
3676 return ((int)(guint16)value | (((int)value) << 16));
3679 return *((guint32*)data);
3681 return *((gint32*)data);
3683 case MONO_TYPE_I8: {
3684 gint64 value = *((gint64*)data);
3685 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3688 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3693 ICALL_EXPORT MonoBoolean
3694 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3697 MonoDomain *domain = mono_object_domain (type);
3698 MonoClass *enumc = mono_class_from_mono_type (type->type);
3699 guint j = 0, nvalues;
3701 MonoClassField *field;
3703 guint64 field_value, previous_value = 0;
3704 gboolean sorted = TRUE;
3706 mono_class_init_checked (enumc, &error);
3707 if (mono_error_set_pending_exception (&error))
3711 if (!enumc->enumtype) {
3712 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3716 base_type = mono_class_enum_basetype (enumc)->type;
3718 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3719 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3720 if (mono_error_set_pending_exception (&error))
3722 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3723 if (mono_error_set_pending_exception (&error))
3727 while ((field = mono_class_get_fields (enumc, &iter))) {
3729 MonoTypeEnum def_type;
3731 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3733 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3735 if (mono_field_is_deleted (field))
3737 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3739 p = mono_class_get_field_default_value (field, &def_type);
3740 /* len = */ mono_metadata_decode_blob_size (p, &p);
3742 field_value = read_enum_value (p, base_type);
3743 mono_array_set (*values, guint64, j, field_value);
3745 if (previous_value > field_value)
3748 previous_value = field_value;
3756 BFLAGS_IgnoreCase = 1,
3757 BFLAGS_DeclaredOnly = 2,
3758 BFLAGS_Instance = 4,
3760 BFLAGS_Public = 0x10,
3761 BFLAGS_NonPublic = 0x20,
3762 BFLAGS_FlattenHierarchy = 0x40,
3763 BFLAGS_InvokeMethod = 0x100,
3764 BFLAGS_CreateInstance = 0x200,
3765 BFLAGS_GetField = 0x400,
3766 BFLAGS_SetField = 0x800,
3767 BFLAGS_GetProperty = 0x1000,
3768 BFLAGS_SetProperty = 0x2000,
3769 BFLAGS_ExactBinding = 0x10000,
3770 BFLAGS_SuppressChangeType = 0x20000,
3771 BFLAGS_OptionalParamBinding = 0x40000
3774 ICALL_EXPORT MonoArray*
3775 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3779 MonoClass *startklass, *klass, *refklass;
3784 char *utf8_name = NULL;
3785 int (*compare_func) (const char *s1, const char *s2) = NULL;
3786 MonoClassField *field;
3787 MonoPtrArray tmp_array;
3789 domain = ((MonoObject *)type)->vtable->domain;
3790 if (type->type->byref) {
3791 MonoArray *result = mono_array_new_checked (domain, mono_defaults.field_info_class, 0, &error);
3792 mono_error_set_pending_exception (&error);
3796 klass = startklass = mono_class_from_mono_type (type->type);
3797 refklass = mono_class_from_mono_type (reftype->type);
3799 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3802 if (mono_class_has_failure (klass)) {
3803 mono_ptr_array_destroy (tmp_array);
3804 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3809 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3810 guint32 flags = mono_field_get_flags (field);
3812 if (mono_field_is_deleted_with_flags (field, flags))
3814 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3815 if (bflags & BFLAGS_Public)
3817 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3818 if (bflags & BFLAGS_NonPublic) {
3825 if (flags & FIELD_ATTRIBUTE_STATIC) {
3826 if (bflags & BFLAGS_Static)
3827 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3830 if (bflags & BFLAGS_Instance)
3838 if (utf8_name == NULL) {
3839 utf8_name = mono_string_to_utf8 (name);
3840 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3843 if (compare_func (mono_field_get_name (field), utf8_name))
3847 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3848 if (!mono_error_ok (&error))
3850 mono_ptr_array_append (tmp_array, member);
3852 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3855 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array), &error);
3856 if (!is_ok (&error))
3859 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3860 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3862 mono_ptr_array_destroy (tmp_array);
3864 if (utf8_name != NULL)
3869 mono_ptr_array_destroy (tmp_array);
3870 mono_error_set_pending_exception (&error);
3875 method_nonpublic (MonoMethod* method, gboolean start_klass)
3877 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3878 case METHOD_ATTRIBUTE_ASSEM:
3879 return (start_klass || mono_defaults.generic_ilist_class);
3880 case METHOD_ATTRIBUTE_PRIVATE:
3882 case METHOD_ATTRIBUTE_PUBLIC:
3890 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3893 MonoClass *startklass;
3897 /*FIXME, use MonoBitSet*/
3898 guint32 method_slots_default [8];
3899 guint32 *method_slots = NULL;
3900 int (*compare_func) (const char *s1, const char *s2) = NULL;
3902 array = g_ptr_array_new ();
3907 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3909 /* An optimization for calls made from Delegate:CreateDelegate () */
3910 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3911 method = mono_get_delegate_invoke (klass);
3914 g_ptr_array_add (array, method);
3918 mono_class_setup_methods (klass);
3919 mono_class_setup_vtable (klass);
3920 if (mono_class_has_failure (klass))
3923 if (is_generic_parameter (&klass->byval_arg))
3924 nslots = mono_class_get_vtable_size (klass->parent);
3926 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3927 if (nslots >= sizeof (method_slots_default) * 8) {
3928 method_slots = g_new0 (guint32, nslots / 32 + 1);
3930 method_slots = method_slots_default;
3931 memset (method_slots, 0, sizeof (method_slots_default));
3934 mono_class_setup_methods (klass);
3935 mono_class_setup_vtable (klass);
3936 if (mono_class_has_failure (klass))
3940 while ((method = mono_class_get_methods (klass, &iter))) {
3942 if (method->slot != -1) {
3943 g_assert (method->slot < nslots);
3944 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3946 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3947 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3950 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3952 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3953 if (bflags & BFLAGS_Public)
3955 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3961 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3962 if (bflags & BFLAGS_Static)
3963 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3966 if (bflags & BFLAGS_Instance)
3974 if (compare_func (name, method->name))
3979 g_ptr_array_add (array, method);
3981 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3983 if (method_slots != method_slots_default)
3984 g_free (method_slots);
3989 if (method_slots != method_slots_default)
3990 g_free (method_slots);
3991 g_ptr_array_free (array, TRUE);
3993 if (mono_class_has_failure (klass)) {
3994 *ex = mono_class_get_exception_for_failure (klass);
3996 *ex = mono_get_exception_execution_engine ("Unknown error");
4001 ICALL_EXPORT MonoArray*
4002 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4004 static MonoClass *MethodInfo_array;
4008 MonoVTable *array_vtable;
4009 MonoException *ex = NULL;
4010 const char *mname = NULL;
4011 GPtrArray *method_array;
4012 MonoClass *klass, *refklass;
4015 mono_error_init (&error);
4017 if (!MethodInfo_array) {
4018 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
4019 mono_memory_barrier ();
4020 MethodInfo_array = klass;
4023 klass = mono_class_from_mono_type (type->type);
4024 refklass = mono_class_from_mono_type (reftype->type);
4025 domain = ((MonoObject *)type)->vtable->domain;
4026 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
4027 if (!is_ok (&error)) {
4028 mono_error_set_pending_exception (&error);
4031 if (type->type->byref) {
4032 res = mono_array_new_specific_checked (array_vtable, 0, &error);
4033 mono_error_set_pending_exception (&error);
4039 mname = mono_string_to_utf8 (name);
4041 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
4042 g_free ((char*)mname);
4044 mono_set_pending_exception (ex);
4048 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
4049 if (!mono_error_ok (&error)) {
4050 mono_error_set_pending_exception (&error);
4054 for (i = 0; i < method_array->len; ++i) {
4055 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
4056 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
4057 if (!mono_error_ok (&error))
4059 mono_array_setref (res, i, rm);
4063 g_ptr_array_free (method_array, TRUE);
4064 if (!mono_error_ok (&error))
4065 mono_set_pending_exception (mono_error_convert_to_exception (&error));
4069 ICALL_EXPORT MonoArray*
4070 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4073 MonoClass *startklass, *klass, *refklass;
4074 MonoArray *res = NULL;
4078 gpointer iter = NULL;
4079 MonoPtrArray tmp_array;
4082 domain = ((MonoObject *)type)->vtable->domain;
4083 if (type->type->byref) {
4084 res = mono_array_new_cached (domain, mono_defaults.method_info_class, 0, &error);
4085 mono_error_set_pending_exception (&error);
4089 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
4092 klass = startklass = mono_class_from_mono_type (type->type);
4093 refklass = mono_class_from_mono_type (reftype->type);
4095 mono_class_setup_methods (klass);
4096 if (mono_class_has_failure (klass)) {
4097 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
4102 while ((method = mono_class_get_methods (klass, &iter))) {
4104 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
4106 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4107 if (bflags & BFLAGS_Public)
4110 if (bflags & BFLAGS_NonPublic)
4116 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4117 if (bflags & BFLAGS_Static)
4118 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4121 if (bflags & BFLAGS_Instance)
4127 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
4128 if (mono_error_set_pending_exception (&error))
4131 mono_ptr_array_append (tmp_array, member);
4134 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array), &error);
4135 if (mono_error_set_pending_exception (&error))
4138 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4139 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4142 mono_ptr_array_destroy (tmp_array);
4148 property_hash (gconstpointer data)
4150 MonoProperty *prop = (MonoProperty*)data;
4152 return g_str_hash (prop->name);
4156 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
4158 if (method1->is_inflated)
4159 method1 = ((MonoMethodInflated*) method1)->declaring;
4160 if (method2->is_inflated)
4161 method2 = ((MonoMethodInflated*) method2)->declaring;
4163 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4167 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4169 // Properties are hide-by-name-and-signature
4170 if (!g_str_equal (prop1->name, prop2->name))
4173 /* If we see a property in a generic method, we want to
4174 compare the generic signatures, not the inflated signatures
4175 because we might conflate two properties that were
4179 public T this[T t] { getter { return t; } } // method 1
4180 public U this[U u] { getter { return u; } } // method 2
4183 If we see int Foo<int,int>::Item[int] we need to know if
4184 the indexer came from method 1 or from method 2, and we
4185 shouldn't conflate them. (Bugzilla 36283)
4187 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
4190 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4197 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4202 return method_nonpublic (accessor, start_klass);
4205 ICALL_EXPORT MonoArray*
4206 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4210 MonoClass *startklass, *klass;
4216 gchar *propname = NULL;
4217 int (*compare_func) (const char *s1, const char *s2) = NULL;
4219 GHashTable *properties = NULL;
4220 MonoPtrArray tmp_array;
4222 mono_error_init (&error);
4224 domain = ((MonoObject *)type)->vtable->domain;
4225 if (type->type->byref) {
4226 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), 0, &error);
4227 mono_error_set_pending_exception (&error);
4231 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4233 klass = startklass = mono_class_from_mono_type (type->type);
4236 propname = mono_string_to_utf8 (name);
4237 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4240 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4242 mono_class_setup_methods (klass);
4243 mono_class_setup_vtable (klass);
4244 if (mono_class_has_failure (klass))
4248 while ((prop = mono_class_get_properties (klass, &iter))) {
4254 flags = method->flags;
4257 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4258 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4259 if (bflags & BFLAGS_Public)
4261 } else if (bflags & BFLAGS_NonPublic) {
4262 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4263 property_accessor_nonpublic(prop->set, startklass == klass)) {
4270 if (flags & METHOD_ATTRIBUTE_STATIC) {
4271 if (bflags & BFLAGS_Static)
4272 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4275 if (bflags & BFLAGS_Instance)
4284 if (compare_func (propname, prop->name))
4288 if (g_hash_table_lookup (properties, prop))
4291 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4294 mono_ptr_array_append (tmp_array, pr);
4296 g_hash_table_insert (properties, prop, prop);
4298 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4301 g_hash_table_destroy (properties);
4304 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array), &error);
4305 if (!is_ok (&error))
4307 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4308 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4310 mono_ptr_array_destroy (tmp_array);
4317 if (mono_class_has_failure (klass)) {
4318 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4323 g_hash_table_destroy (properties);
4326 mono_ptr_array_destroy (tmp_array);
4328 mono_error_set_pending_exception (&error);
4334 event_hash (gconstpointer data)
4336 MonoEvent *event = (MonoEvent*)data;
4338 return g_str_hash (event->name);
4342 event_equal (MonoEvent *event1, MonoEvent *event2)
4344 // Events are hide-by-name
4345 return g_str_equal (event1->name, event2->name);
4348 ICALL_EXPORT MonoArray*
4349 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4353 MonoClass *startklass, *klass;
4359 char *utf8_name = NULL;
4360 int (*compare_func) (const char *s1, const char *s2) = NULL;
4361 GHashTable *events = NULL;
4362 MonoPtrArray tmp_array;
4364 mono_error_init (&error);
4366 domain = mono_object_domain (type);
4367 if (type->type->byref) {
4368 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), 0, &error);
4369 mono_error_set_pending_exception (&error);
4373 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4375 klass = startklass = mono_class_from_mono_type (type->type);
4377 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4379 mono_class_setup_methods (klass);
4380 mono_class_setup_vtable (klass);
4381 if (mono_class_has_failure (klass))
4385 while ((event = mono_class_get_events (klass, &iter))) {
4387 method = event->add;
4389 method = event->remove;
4391 method = event->raise;
4393 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4394 if (bflags & BFLAGS_Public)
4396 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4397 if (bflags & BFLAGS_NonPublic)
4402 if (bflags & BFLAGS_NonPublic)
4408 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4409 if (bflags & BFLAGS_Static)
4410 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4413 if (bflags & BFLAGS_Instance)
4418 if (bflags & BFLAGS_Instance)
4424 if (utf8_name == NULL) {
4425 utf8_name = mono_string_to_utf8 (name);
4426 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4429 if (compare_func (event->name, utf8_name))
4433 if (g_hash_table_lookup (events, event))
4436 MonoReflectionEvent *ev_obj;
4437 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4440 mono_ptr_array_append (tmp_array, ev_obj);
4442 g_hash_table_insert (events, event, event);
4444 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4447 g_hash_table_destroy (events);
4449 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array), &error);
4450 if (!is_ok (&error))
4453 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4454 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4456 mono_ptr_array_destroy (tmp_array);
4458 if (utf8_name != NULL)
4464 if (mono_class_has_failure (klass)) {
4465 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4471 g_hash_table_destroy (events);
4472 if (utf8_name != NULL)
4475 mono_ptr_array_destroy (tmp_array);
4477 mono_error_set_pending_exception (&error);
4481 ICALL_EXPORT MonoArray*
4482 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4485 MonoReflectionType *rt;
4488 MonoArray *res = NULL;
4493 MonoPtrArray tmp_array;
4495 mono_error_init (&error);
4497 domain = ((MonoObject *)type)->vtable->domain;
4498 if (type->type->byref) {
4499 MonoArray *result = mono_array_new_cached (domain, mono_defaults.monotype_class, 0, &error);
4500 mono_error_set_pending_exception (&error);
4503 klass = mono_class_from_mono_type (type->type);
4506 * If a nested type is generic, return its generic type definition.
4507 * Note that this means that the return value is essentially the set
4508 * of nested types of the generic type definition of @klass.
4510 * A note in MSDN claims that a generic type definition can have
4511 * nested types that aren't generic. In any case, the container of that
4512 * nested type would be the generic type definition.
4514 if (klass->generic_class)
4515 klass = klass->generic_class->container_class;
4517 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4519 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4521 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4522 if (bflags & BFLAGS_Public)
4525 if (bflags & BFLAGS_NonPublic)
4533 str = mono_string_to_utf8 (name);
4534 mono_identifier_unescape_type_name_chars (str);
4537 if (strcmp (nested->name, str))
4541 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4542 if (!is_ok (&error))
4545 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4548 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array), &error);
4549 if (!is_ok (&error))
4552 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4553 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4556 mono_ptr_array_destroy (tmp_array);
4560 mono_error_set_pending_exception (&error);
4564 ICALL_EXPORT MonoReflectionType*
4565 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4568 MonoReflectionType *ret;
4570 MonoType *type = NULL;
4571 MonoTypeNameParse info;
4572 gboolean type_resolve;
4574 /* On MS.NET, this does not fire a TypeResolve event */
4575 type_resolve = TRUE;
4576 str = mono_string_to_utf8 (name);
4577 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4578 if (!mono_reflection_parse_type (str, &info)) {
4580 mono_reflection_free_type_info (&info);
4582 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4585 /*g_print ("failed parse\n");*/
4589 if (info.assembly.name) {
4591 mono_reflection_free_type_info (&info);
4593 /* 1.0 and 2.0 throw different exceptions */
4594 if (mono_defaults.generic_ilist_class)
4595 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4597 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4603 if (module != NULL) {
4604 if (module->image) {
4605 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4606 if (!is_ok (&error)) {
4608 mono_reflection_free_type_info (&info);
4609 mono_error_set_pending_exception (&error);
4616 if (assembly_is_dynamic (assembly->assembly)) {
4617 /* Enumerate all modules */
4618 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4622 if (abuilder->modules) {
4623 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4624 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4625 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4626 if (!is_ok (&error)) {
4628 mono_reflection_free_type_info (&info);
4629 mono_error_set_pending_exception (&error);
4637 if (!type && abuilder->loaded_modules) {
4638 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4639 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4640 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4641 if (!is_ok (&error)) {
4643 mono_reflection_free_type_info (&info);
4644 mono_error_set_pending_exception (&error);
4653 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4654 if (!is_ok (&error)) {
4656 mono_reflection_free_type_info (&info);
4657 mono_error_set_pending_exception (&error);
4662 mono_reflection_free_type_info (&info);
4664 MonoException *e = NULL;
4667 e = mono_get_exception_type_load (name, NULL);
4670 mono_set_pending_exception (e);
4674 if (type->type == MONO_TYPE_CLASS) {
4675 MonoClass *klass = mono_type_get_class (type);
4677 /* need to report exceptions ? */
4678 if (throwOnError && mono_class_has_failure (klass)) {
4679 /* report SecurityException (or others) that occured when loading the assembly */
4680 MonoException *exc = mono_class_get_exception_for_failure (klass);
4681 mono_set_pending_exception (exc);
4686 /* g_print ("got it\n"); */
4687 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4688 mono_error_set_pending_exception (&error);
4694 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4697 gchar *shadow_ini_file;
4700 /* Check for shadow-copied assembly */
4701 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4702 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4704 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4705 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4711 g_free (shadow_ini_file);
4712 if (content != NULL) {
4715 *filename = content;
4722 ICALL_EXPORT MonoString *
4723 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4725 MonoDomain *domain = mono_object_domain (assembly);
4726 MonoAssembly *mass = assembly->assembly;
4727 MonoString *res = NULL;
4732 if (g_path_is_absolute (mass->image->name)) {
4733 absolute = g_strdup (mass->image->name);
4734 dirname = g_path_get_dirname (absolute);
4736 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4737 dirname = g_strdup (mass->basedir);
4740 replace_shadow_path (domain, dirname, &absolute);
4745 for (i = strlen (absolute) - 1; i >= 0; i--)
4746 if (absolute [i] == '\\')
4751 uri = g_filename_to_uri (absolute, NULL, NULL);
4753 const char *prepend = "file://";
4755 if (*absolute == '/' && *(absolute + 1) == '/') {
4758 prepend = "file:///";
4761 uri = g_strconcat (prepend, absolute, NULL);
4765 res = mono_string_new (domain, uri);
4772 ICALL_EXPORT MonoBoolean
4773 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4775 MonoAssembly *mass = assembly->assembly;
4777 return mass->in_gac;
4780 ICALL_EXPORT MonoReflectionAssembly*
4781 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4786 MonoImageOpenStatus status;
4787 MonoReflectionAssembly* result = NULL;
4789 name = mono_string_to_utf8 (mname);
4790 res = mono_assembly_load_with_partial_name (name, &status);
4796 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4798 mono_error_set_pending_exception (&error);
4802 ICALL_EXPORT MonoString *
4803 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4805 MonoDomain *domain = mono_object_domain (assembly);
4808 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4813 ICALL_EXPORT MonoBoolean
4814 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4816 return assembly->assembly->ref_only;
4819 ICALL_EXPORT MonoString *
4820 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4822 MonoDomain *domain = mono_object_domain (assembly);
4824 return mono_string_new (domain, assembly->assembly->image->version);
4827 ICALL_EXPORT MonoReflectionMethod*
4828 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4831 MonoReflectionMethod *res = NULL;
4834 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4838 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4839 if (!mono_error_ok (&error))
4842 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4845 if (!mono_error_ok (&error))
4846 mono_error_set_pending_exception (&error);
4850 ICALL_EXPORT MonoReflectionModule*
4851 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4854 MonoReflectionModule *result = NULL;
4855 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4856 if (!mono_error_ok (&error))
4857 mono_error_set_pending_exception (&error);
4861 ICALL_EXPORT MonoArray*
4862 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4865 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4866 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4867 if (mono_error_set_pending_exception (&error))
4872 for (i = 0; i < table->rows; ++i) {
4873 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4874 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4880 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4882 static MonoMethod *create_version = NULL;
4886 mono_error_init (error);
4889 if (!create_version) {
4890 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4891 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4892 g_assert (create_version);
4893 mono_method_desc_free (desc);
4899 args [3] = &revision;
4900 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4901 return_val_if_nok (error, NULL);
4903 mono_runtime_invoke_checked (create_version, result, args, error);
4904 return_val_if_nok (error, NULL);
4909 ICALL_EXPORT MonoArray*
4910 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4914 MonoDomain *domain = mono_object_domain (assembly);
4916 static MonoMethod *create_culture = NULL;
4917 MonoImage *image = assembly->assembly->image;
4921 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4924 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4925 if (mono_error_set_pending_exception (&error))
4929 if (count > 0 && !create_culture) {
4930 MonoMethodDesc *desc = mono_method_desc_new (
4931 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4932 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4933 g_assert (create_culture);
4934 mono_method_desc_free (desc);
4937 for (i = 0; i < count; i++) {
4938 MonoObject *version;
4939 MonoReflectionAssemblyName *aname;
4940 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4942 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4944 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4945 domain, mono_class_get_assembly_name_class (), &error);
4946 if (mono_error_set_pending_exception (&error))
4949 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4951 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4952 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4953 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4954 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4955 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4956 aname->versioncompat = 1; /* SameMachine (default) */
4957 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4959 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4960 if (mono_error_set_pending_exception (&error))
4963 MONO_OBJECT_SETREF (aname, version, version);
4965 if (create_culture) {
4967 MonoBoolean assembly_ref = 1;
4968 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4969 args [1] = &assembly_ref;
4971 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4972 if (mono_error_set_pending_exception (&error))
4975 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4978 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4979 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4980 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4982 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4983 /* public key token isn't copied - the class library will
4984 automatically generate it from the public key if required */
4985 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4986 if (mono_error_set_pending_exception (&error))
4989 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4990 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4992 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4993 if (mono_error_set_pending_exception (&error))
4996 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4997 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
5000 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
5001 if (mono_error_set_pending_exception (&error))
5004 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5007 /* note: this function doesn't return the codebase on purpose (i.e. it can
5008 be used under partial trust as path information isn't present). */
5010 mono_array_setref (result, i, aname);
5015 /* move this in some file in mono/util/ */
5017 g_concat_dir_and_file (const char *dir, const char *file)
5019 g_return_val_if_fail (dir != NULL, NULL);
5020 g_return_val_if_fail (file != NULL, NULL);
5023 * If the directory name doesn't have a / on the end, we need
5024 * to add one so we get a proper path to the file
5026 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
5027 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
5029 return g_strconcat (dir, file, NULL);
5033 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
5036 char *n = mono_string_to_utf8 (name);
5037 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5039 guint32 cols [MONO_MANIFEST_SIZE];
5040 guint32 impl, file_idx;
5044 for (i = 0; i < table->rows; ++i) {
5045 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5046 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5047 if (strcmp (val, n) == 0)
5051 if (i == table->rows)
5054 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
5057 * this code should only be called after obtaining the
5058 * ResourceInfo and handling the other cases.
5060 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
5061 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
5063 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
5068 module = assembly->assembly->image;
5071 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
5072 if (mono_error_set_pending_exception (&error))
5074 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
5076 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
5079 ICALL_EXPORT gboolean
5080 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
5083 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5085 guint32 cols [MONO_MANIFEST_SIZE];
5086 guint32 file_cols [MONO_FILE_SIZE];
5090 n = mono_string_to_utf8 (name);
5091 for (i = 0; i < table->rows; ++i) {
5092 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5093 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5094 if (strcmp (val, n) == 0)
5098 if (i == table->rows)
5101 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
5102 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
5105 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
5106 case MONO_IMPLEMENTATION_FILE:
5107 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5108 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5109 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
5110 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
5111 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
5112 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
5115 info->location = RESOURCE_LOCATION_EMBEDDED;
5118 case MONO_IMPLEMENTATION_ASSEMBLYREF:
5119 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5120 mono_assembly_load_reference (assembly->assembly->image, i - 1);
5121 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
5122 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
5123 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
5125 mono_set_pending_exception (ex);
5128 MonoReflectionAssembly *assm_obj;
5129 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5131 mono_error_set_pending_exception (&error);
5134 MONO_OBJECT_SETREF (info, assembly, assm_obj);
5136 /* Obtain info recursively */
5137 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5138 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5141 case MONO_IMPLEMENTATION_EXP_TYPE:
5142 g_assert_not_reached ();
5150 ICALL_EXPORT MonoObject*
5151 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
5154 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5155 MonoArray *result = NULL;
5160 /* check hash if needed */
5162 n = mono_string_to_utf8 (name);
5163 for (i = 0; i < table->rows; ++i) {
5164 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5165 if (strcmp (val, n) == 0) {
5168 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5169 fn = mono_string_new (mono_object_domain (assembly), n);
5171 return (MonoObject*)fn;
5179 for (i = 0; i < table->rows; ++i) {
5180 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5184 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
5185 if (mono_error_set_pending_exception (&error))
5190 for (i = 0; i < table->rows; ++i) {
5191 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5192 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5193 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5194 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5199 return (MonoObject*)result;
5202 ICALL_EXPORT MonoArray*
5203 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5206 MonoDomain *domain = mono_domain_get();
5209 int i, j, file_count = 0;
5210 MonoImage **modules;
5211 guint32 module_count, real_module_count;
5212 MonoTableInfo *table;
5213 guint32 cols [MONO_FILE_SIZE];
5214 MonoImage *image = assembly->assembly->image;
5216 g_assert (image != NULL);
5217 g_assert (!assembly_is_dynamic (assembly->assembly));
5219 table = &image->tables [MONO_TABLE_FILE];
5220 file_count = table->rows;
5222 modules = image->modules;
5223 module_count = image->module_count;
5225 real_module_count = 0;
5226 for (i = 0; i < module_count; ++i)
5228 real_module_count ++;
5230 klass = mono_class_get_module_class ();
5231 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5232 if (mono_error_set_pending_exception (&error))
5235 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5236 if (mono_error_set_pending_exception (&error))
5239 mono_array_setref (res, 0, image_obj);
5241 for (i = 0; i < module_count; ++i)
5243 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5244 if (mono_error_set_pending_exception (&error))
5246 mono_array_setref (res, j, rm);
5250 for (i = 0; i < file_count; ++i, ++j) {
5251 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5252 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5253 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5254 if (mono_error_set_pending_exception (&error))
5256 mono_array_setref (res, j, rm);
5259 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5261 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5262 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5265 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5266 if (mono_error_set_pending_exception (&error))
5268 mono_array_setref (res, j, rm);
5275 ICALL_EXPORT MonoReflectionMethod*
5276 ves_icall_GetCurrentMethod (void)
5278 MonoReflectionMethod *res = NULL;
5281 MonoMethod *m = mono_method_get_last_managed ();
5284 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5288 while (m->is_inflated)
5289 m = ((MonoMethodInflated*)m)->declaring;
5291 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5292 mono_error_set_pending_exception (&error);
5298 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5301 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5304 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5305 //method is inflated, we should inflate it on the other class
5306 MonoGenericContext ctx;
5307 ctx.method_inst = inflated->context.method_inst;
5308 ctx.class_inst = inflated->context.class_inst;
5309 if (klass->generic_class)
5310 ctx.class_inst = klass->generic_class->context.class_inst;
5311 else if (klass->generic_container)
5312 ctx.class_inst = klass->generic_container->context.class_inst;
5313 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5314 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5318 mono_class_setup_methods (method->klass);
5319 if (mono_class_has_failure (method->klass))
5321 for (i = 0; i < method->klass->method.count; ++i) {
5322 if (method->klass->methods [i] == method) {
5327 mono_class_setup_methods (klass);
5328 if (mono_class_has_failure (klass))
5330 g_assert (offset >= 0 && offset < klass->method.count);
5331 return klass->methods [offset];
5334 ICALL_EXPORT MonoReflectionMethod*
5335 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5337 MonoReflectionMethod *res = NULL;
5341 klass = mono_class_from_mono_type (type);
5342 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5344 if (method->klass != klass) {
5345 method = mono_method_get_equivalent_method (method, klass);
5350 klass = method->klass;
5351 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5352 mono_error_set_pending_exception (&error);
5356 ICALL_EXPORT MonoReflectionMethodBody*
5357 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5360 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5361 mono_error_set_pending_exception (&error);
5365 ICALL_EXPORT MonoReflectionAssembly*
5366 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5369 MonoReflectionAssembly *result;
5370 MonoMethod *dest = NULL;
5372 mono_stack_walk_no_il (get_executing, &dest);
5374 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5376 mono_error_set_pending_exception (&error);
5381 ICALL_EXPORT MonoReflectionAssembly*
5382 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5385 MonoReflectionAssembly *result;
5386 MonoDomain* domain = mono_domain_get ();
5388 if (!domain->entry_assembly)
5391 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5393 mono_error_set_pending_exception (&error);
5397 ICALL_EXPORT MonoReflectionAssembly*
5398 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5403 MonoReflectionAssembly *result;
5406 mono_stack_walk_no_il (get_executing, &dest);
5408 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5412 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5415 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5417 mono_error_set_pending_exception (&error);
5421 ICALL_EXPORT MonoString *
5422 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5423 gboolean assembly_qualified)
5425 MonoDomain *domain = mono_object_domain (object);
5426 MonoTypeNameFormat format;
5431 format = assembly_qualified ?
5432 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5433 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5435 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5437 name = mono_type_get_name_full (object->type, format);
5441 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5446 res = mono_string_new (domain, name);
5453 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5456 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5458 mono_class_init_checked (klass, &error);
5459 mono_error_set_pending_exception (&error);
5460 return mono_security_core_clr_class_level (klass);
5464 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5466 MonoClassField *field = rfield->field;
5467 return mono_security_core_clr_field_level (field, TRUE);
5471 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5473 MonoMethod *method = rfield->method;
5474 return mono_security_core_clr_method_level (method, TRUE);
5478 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)
5480 static MonoMethod *create_culture = NULL;
5484 const char *pkey_ptr;
5486 MonoBoolean assembly_ref = 0;
5488 mono_error_init (error);
5490 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5491 aname->major = name->major;
5492 aname->minor = name->minor;
5493 aname->build = name->build;
5494 aname->flags = name->flags;
5495 aname->revision = name->revision;
5496 aname->hashalg = name->hash_alg;
5497 aname->versioncompat = 1; /* SameMachine (default) */
5498 aname->processor_architecture = name->arch;
5500 if (by_default_version) {
5501 MonoObject *version;
5503 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5504 return_if_nok (error);
5506 MONO_OBJECT_SETREF (aname, version, version);
5510 if (absolute != NULL && *absolute != '\0') {
5511 const gchar *prepend = "file://";
5514 codebase = g_strdup (absolute);
5519 for (i = strlen (codebase) - 1; i >= 0; i--)
5520 if (codebase [i] == '\\')
5523 if (*codebase == '/' && *(codebase + 1) == '/') {
5526 prepend = "file:///";
5530 result = g_strconcat (prepend, codebase, NULL);
5536 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5540 if (!create_culture) {
5541 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5542 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5543 g_assert (create_culture);
5544 mono_method_desc_free (desc);
5547 if (name->culture) {
5548 args [0] = mono_string_new (domain, name->culture);
5549 args [1] = &assembly_ref;
5551 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5552 return_if_nok (error);
5554 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5557 if (name->public_key) {
5558 pkey_ptr = (char*)name->public_key;
5559 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5561 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5562 return_if_nok (error);
5563 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5564 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5565 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5566 } else if (default_publickey) {
5567 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5568 return_if_nok (error);
5569 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5570 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5573 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5574 if (name->public_key_token [0]) {
5578 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5579 return_if_nok (error);
5581 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5582 p = mono_array_addr (keyToken, char, 0);
5584 for (i = 0, j = 0; i < 8; i++) {
5585 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5586 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5589 } else if (default_token) {
5590 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5591 return_if_nok (error);
5592 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5596 ICALL_EXPORT MonoString *
5597 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5599 MonoDomain *domain = mono_object_domain (assembly);
5600 MonoAssembly *mass = assembly->assembly;
5604 name = mono_stringify_assembly_name (&mass->aname);
5605 res = mono_string_new (domain, name);
5612 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5616 MonoAssembly *mass = assembly->assembly;
5618 if (g_path_is_absolute (mass->image->name)) {
5619 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5620 mono_error_set_pending_exception (&error);
5623 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5625 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5626 mono_error_set_pending_exception (&error);
5632 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5636 MonoImageOpenStatus status = MONO_IMAGE_OK;
5639 MonoAssemblyName name;
5642 filename = mono_string_to_utf8 (fname);
5644 dirname = g_path_get_dirname (filename);
5645 replace_shadow_path (mono_domain_get (), dirname, &filename);
5648 image = mono_image_open (filename, &status);
5654 if (status == MONO_IMAGE_IMAGE_INVALID)
5655 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5657 exc = mono_get_exception_file_not_found2 (NULL, fname);
5658 mono_set_pending_exception (exc);
5662 res = mono_assembly_fill_assembly_name (image, &name);
5664 mono_image_close (image);
5666 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5670 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5671 mono_error_set_pending_exception (&error);
5673 mono_image_close (image);
5677 ICALL_EXPORT MonoBoolean
5678 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5679 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5681 MonoBoolean result = FALSE;
5682 MonoDeclSecurityEntry entry;
5684 /* SecurityAction.RequestMinimum */
5685 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5686 *minimum = entry.blob;
5687 *minLength = entry.size;
5690 /* SecurityAction.RequestOptional */
5691 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5692 *optional = entry.blob;
5693 *optLength = entry.size;
5696 /* SecurityAction.RequestRefuse */
5697 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5698 *refused = entry.blob;
5699 *refLength = entry.size;
5707 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5709 guint32 attrs, visibility;
5711 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5712 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5713 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5716 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5722 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5724 MonoReflectionType *rt;
5727 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5730 mono_error_init (error);
5732 /* we start the count from 1 because we skip the special type <Module> */
5735 for (i = 1; i < tdef->rows; ++i) {
5736 if (mono_module_type_is_visible (tdef, image, i + 1))
5740 count = tdef->rows - 1;
5742 res = mono_array_new_checked (domain, mono_defaults.monotype_class, count, error);
5743 return_val_if_nok (error, NULL);
5744 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5745 return_val_if_nok (error, NULL);
5747 for (i = 1; i < tdef->rows; ++i) {
5748 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5749 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5752 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5753 return_val_if_nok (error, NULL);
5755 mono_array_setref (res, count, rt);
5757 MonoException *ex = mono_error_convert_to_exception (error);
5758 mono_array_setref (*exceptions, count, ex);
5767 ICALL_EXPORT MonoArray*
5768 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5771 MonoArray *res = NULL;
5772 MonoArray *exceptions = NULL;
5773 MonoImage *image = NULL;
5774 MonoTableInfo *table = NULL;
5777 int i, len, ex_count;
5779 domain = mono_object_domain (assembly);
5781 g_assert (!assembly_is_dynamic (assembly->assembly));
5782 image = assembly->assembly->image;
5783 table = &image->tables [MONO_TABLE_FILE];
5784 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5785 if (mono_error_set_pending_exception (&error))
5788 /* Append data from all modules in the assembly */
5789 for (i = 0; i < table->rows; ++i) {
5790 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5791 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5796 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5797 if (mono_error_set_pending_exception (&error))
5801 /* Append the new types to the end of the array */
5802 if (mono_array_length (res2) > 0) {
5804 MonoArray *res3, *ex3;
5806 len1 = mono_array_length (res);
5807 len2 = mono_array_length (res2);
5809 res3 = mono_array_new_checked (domain, mono_defaults.monotype_class, len1 + len2, &error);
5810 if (mono_error_set_pending_exception (&error))
5812 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5813 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5816 ex3 = mono_array_new_checked (domain, mono_defaults.monotype_class, len1 + len2, &error);
5817 if (mono_error_set_pending_exception (&error))
5819 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5820 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5827 /* the ReflectionTypeLoadException must have all the types (Types property),
5828 * NULL replacing types which throws an exception. The LoaderException must
5829 * contain all exceptions for NULL items.
5832 len = mono_array_length (res);
5835 for (i = 0; i < len; i++) {
5836 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5840 klass = mono_type_get_class (t->type);
5841 if ((klass != NULL) && mono_class_has_failure (klass)) {
5842 /* keep the class in the list */
5843 list = g_list_append (list, klass);
5844 /* and replace Type with NULL */
5845 mono_array_setref (res, i, NULL);
5852 if (list || ex_count) {
5854 MonoException *exc = NULL;
5855 MonoArray *exl = NULL;
5856 int j, length = g_list_length (list) + ex_count;
5858 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5859 if (mono_error_set_pending_exception (&error)) {
5863 /* Types for which mono_class_get_checked () succeeded */
5864 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5865 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5866 mono_array_setref (exl, i, exc);
5868 /* Types for which it don't */
5869 for (j = 0; j < mono_array_length (exceptions); ++j) {
5870 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5872 g_assert (i < length);
5873 mono_array_setref (exl, i, exc);
5880 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5881 if (!is_ok (&error)) {
5882 mono_error_set_pending_exception (&error);
5885 mono_set_pending_exception (exc);
5892 ICALL_EXPORT gboolean
5893 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5896 MonoAssemblyName aname;
5897 MonoDomain *domain = mono_object_domain (name);
5899 gboolean is_version_defined;
5900 gboolean is_token_defined;
5902 aname.public_key = NULL;
5903 val = mono_string_to_utf8 (assname);
5904 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5905 g_free ((guint8*) aname.public_key);
5910 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5911 mono_error_set_pending_exception (&error);
5913 mono_assembly_name_free (&aname);
5914 g_free ((guint8*) aname.public_key);
5920 ICALL_EXPORT MonoReflectionType*
5921 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5924 MonoReflectionType *ret;
5925 MonoDomain *domain = mono_object_domain (module);
5928 g_assert (module->image);
5930 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5931 /* These images do not have a global type */
5934 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5935 if (!mono_error_ok (&error)) {
5936 mono_error_set_pending_exception (&error);
5940 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5941 if (!mono_error_ok (&error)) {
5942 mono_error_set_pending_exception (&error);
5950 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5952 /*if (module->image)
5953 mono_image_close (module->image);*/
5956 ICALL_EXPORT MonoString*
5957 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5959 MonoDomain *domain = mono_object_domain (module);
5961 g_assert (module->image);
5962 return mono_string_new (domain, module->image->guid);
5965 ICALL_EXPORT gpointer
5966 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5969 if (module->image && module->image->is_module_handle)
5970 return module->image->raw_data;
5973 return (gpointer) (-1);
5977 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5979 if (image_is_dynamic (image)) {
5980 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5981 *pe_kind = dyn->pe_kind;
5982 *machine = dyn->machine;
5985 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5986 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5991 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5993 return (image->md_version_major << 16) | (image->md_version_minor);
5996 ICALL_EXPORT MonoArray*
5997 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
6000 MonoArray *exceptions;
6003 if (!module->image) {
6004 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.monotype_class, 0, &error);
6005 mono_error_set_pending_exception (&error);
6010 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
6011 if (mono_error_set_pending_exception (&error))
6014 for (i = 0; i < mono_array_length (exceptions); ++i) {
6015 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
6017 mono_set_pending_exception (ex);
6026 mono_memberref_is_method (MonoImage *image, guint32 token)
6028 if (!image_is_dynamic (image)) {
6029 guint32 cols [MONO_MEMBERREF_SIZE];
6031 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
6032 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
6033 mono_metadata_decode_blob_size (sig, &sig);
6034 return (*sig != 0x6);
6037 MonoClass *handle_class;
6039 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
6040 mono_error_cleanup (&error); /* just probing, ignore error */
6044 return mono_defaults.methodhandle_class == handle_class;
6049 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
6052 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
6053 mono_array_addr (type_args, MonoType*, 0));
6055 context->class_inst = NULL;
6057 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
6058 mono_array_addr (method_args, MonoType*, 0));
6060 context->method_inst = NULL;
6063 ICALL_EXPORT MonoType*
6064 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6067 int table = mono_metadata_token_table (token);
6068 int index = mono_metadata_token_index (token);
6069 MonoGenericContext context;
6072 *resolve_error = ResolveTokenError_Other;
6074 /* Validate token */
6075 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
6076 (table != MONO_TABLE_TYPESPEC)) {
6077 *resolve_error = ResolveTokenError_BadTable;
6081 if (image_is_dynamic (image)) {
6082 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
6083 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6084 mono_error_cleanup (&error);
6085 return klass ? &klass->byval_arg : NULL;
6088 init_generic_context_from_args (&context, type_args, method_args);
6089 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6090 mono_error_cleanup (&error);
6091 return klass ? &klass->byval_arg : NULL;
6094 if ((index <= 0) || (index > image->tables [table].rows)) {
6095 *resolve_error = ResolveTokenError_OutOfRange;
6099 init_generic_context_from_args (&context, type_args, method_args);
6100 klass = mono_class_get_checked (image, token, &error);
6102 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
6103 if (!mono_error_ok (&error)) {
6104 mono_error_set_pending_exception (&error);
6109 return &klass->byval_arg;
6114 ICALL_EXPORT MonoMethod*
6115 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6118 int table = mono_metadata_token_table (token);
6119 int index = mono_metadata_token_index (token);
6120 MonoGenericContext context;
6123 *resolve_error = ResolveTokenError_Other;
6125 /* Validate token */
6126 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
6127 (table != MONO_TABLE_MEMBERREF)) {
6128 *resolve_error = ResolveTokenError_BadTable;
6132 if (image_is_dynamic (image)) {
6133 if (table == MONO_TABLE_METHOD) {
6134 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6135 mono_error_cleanup (&error);
6139 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
6140 *resolve_error = ResolveTokenError_BadTable;
6144 init_generic_context_from_args (&context, type_args, method_args);
6145 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6146 mono_error_cleanup (&error);
6150 if ((index <= 0) || (index > image->tables [table].rows)) {
6151 *resolve_error = ResolveTokenError_OutOfRange;
6154 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6155 *resolve_error = ResolveTokenError_BadTable;
6159 init_generic_context_from_args (&context, type_args, method_args);
6160 method = mono_get_method_checked (image, token, NULL, &context, &error);
6161 mono_error_set_pending_exception (&error);
6166 ICALL_EXPORT MonoString*
6167 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6170 int index = mono_metadata_token_index (token);
6172 *resolve_error = ResolveTokenError_Other;
6174 /* Validate token */
6175 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6176 *resolve_error = ResolveTokenError_BadTable;
6180 if (image_is_dynamic (image)) {
6181 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6182 mono_error_cleanup (&error);
6186 if ((index <= 0) || (index >= image->heap_us.size)) {
6187 *resolve_error = ResolveTokenError_OutOfRange;
6191 /* FIXME: What to do if the index points into the middle of a string ? */
6193 return mono_ldstr (mono_domain_get (), image, index);
6196 ICALL_EXPORT MonoClassField*
6197 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6201 int table = mono_metadata_token_table (token);
6202 int index = mono_metadata_token_index (token);
6203 MonoGenericContext context;
6204 MonoClassField *field;
6206 *resolve_error = ResolveTokenError_Other;
6208 /* Validate token */
6209 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6210 *resolve_error = ResolveTokenError_BadTable;
6214 if (image_is_dynamic (image)) {
6215 if (table == MONO_TABLE_FIELD) {
6216 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6217 mono_error_cleanup (&error);
6221 if (mono_memberref_is_method (image, token)) {
6222 *resolve_error = ResolveTokenError_BadTable;
6226 init_generic_context_from_args (&context, type_args, method_args);
6227 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6228 mono_error_cleanup (&error);
6232 if ((index <= 0) || (index > image->tables [table].rows)) {
6233 *resolve_error = ResolveTokenError_OutOfRange;
6236 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6237 *resolve_error = ResolveTokenError_BadTable;
6241 init_generic_context_from_args (&context, type_args, method_args);
6242 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6243 mono_error_set_pending_exception (&error);
6249 ICALL_EXPORT MonoObject*
6250 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6254 int table = mono_metadata_token_table (token);
6256 *error = ResolveTokenError_Other;
6259 case MONO_TABLE_TYPEDEF:
6260 case MONO_TABLE_TYPEREF:
6261 case MONO_TABLE_TYPESPEC: {
6262 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6264 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6265 mono_error_set_pending_exception (&merror);
6272 case MONO_TABLE_METHOD:
6273 case MONO_TABLE_METHODSPEC: {
6274 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6276 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6277 mono_error_set_pending_exception (&merror);
6283 case MONO_TABLE_FIELD: {
6284 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6286 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6287 mono_error_set_pending_exception (&merror);
6293 case MONO_TABLE_MEMBERREF:
6294 if (mono_memberref_is_method (image, token)) {
6295 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6297 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6298 mono_error_set_pending_exception (&merror);
6305 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6307 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6308 mono_error_set_pending_exception (&merror);
6317 *error = ResolveTokenError_BadTable;
6323 ICALL_EXPORT MonoArray*
6324 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6327 int table = mono_metadata_token_table (token);
6328 int idx = mono_metadata_token_index (token);
6329 MonoTableInfo *tables = image->tables;
6334 *resolve_error = ResolveTokenError_OutOfRange;
6336 /* FIXME: Support other tables ? */
6337 if (table != MONO_TABLE_STANDALONESIG)
6340 if (image_is_dynamic (image))
6343 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6346 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6348 ptr = mono_metadata_blob_heap (image, sig);
6349 len = mono_metadata_decode_blob_size (ptr, &ptr);
6351 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6352 if (mono_error_set_pending_exception (&error))
6354 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6358 ICALL_EXPORT MonoReflectionType*
6359 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6362 MonoReflectionType *ret;
6364 int isbyref = 0, rank;
6365 char *str = mono_string_to_utf8 (smodifiers);
6368 klass = mono_class_from_mono_type (tb->type.type);
6370 /* logic taken from mono_reflection_parse_type(): keep in sync */
6374 if (isbyref) { /* only one level allowed by the spec */
6383 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6384 mono_error_set_pending_exception (&error);
6388 klass = mono_ptr_class_get (&klass->byval_arg);
6389 mono_class_init (klass);
6400 else if (*p != '*') { /* '*' means unknown lower bound */
6411 klass = mono_array_class_get (klass, rank);
6412 mono_class_init (klass);
6421 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6422 mono_error_set_pending_exception (&error);
6427 ICALL_EXPORT MonoBoolean
6428 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6434 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6440 check_for_invalid_type (MonoClass *klass, MonoError *error)
6445 mono_error_init (error);
6447 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6450 name = mono_type_get_full_name (klass);
6451 str = mono_string_new (mono_domain_get (), name);
6453 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6456 ICALL_EXPORT MonoReflectionType *
6457 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6460 MonoReflectionType *ret;
6461 MonoClass *klass, *aklass;
6463 klass = mono_class_from_mono_type (type->type);
6464 check_for_invalid_type (klass, &error);
6465 mono_error_set_pending_exception (&error);
6467 if (rank == 0) //single dimentional array
6468 aklass = mono_array_class_get (klass, 1);
6470 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6472 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6473 mono_error_set_pending_exception (&error);
6478 ICALL_EXPORT MonoReflectionType *
6479 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6482 MonoReflectionType *ret;
6485 klass = mono_class_from_mono_type (type->type);
6486 mono_class_init_checked (klass, &error);
6487 if (mono_error_set_pending_exception (&error))
6490 check_for_invalid_type (klass, &error);
6491 if (mono_error_set_pending_exception (&error))
6494 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6495 mono_error_set_pending_exception (&error);
6500 ICALL_EXPORT MonoReflectionType *
6501 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6504 MonoReflectionType *ret;
6505 MonoClass *klass, *pklass;
6507 klass = mono_class_from_mono_type (type->type);
6508 mono_class_init_checked (klass, &error);
6509 if (mono_error_set_pending_exception (&error))
6511 check_for_invalid_type (klass, &error);
6512 if (mono_error_set_pending_exception (&error))
6515 pklass = mono_ptr_class_get (type->type);
6517 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6518 mono_error_set_pending_exception (&error);
6523 ICALL_EXPORT MonoObject *
6524 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6525 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6528 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6529 MonoObject *delegate;
6531 MonoMethod *method = info->method;
6533 mono_class_init_checked (delegate_class, &error);
6534 if (mono_error_set_pending_exception (&error))
6537 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6538 /* FIXME improve this exception message */
6539 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6541 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6542 mono_error_set_pending_exception (&error);
6546 if (mono_security_core_clr_enabled ()) {
6547 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6548 if (throwOnBindFailure)
6549 mono_error_set_pending_exception (&error);
6551 mono_error_cleanup (&error);
6556 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6557 if (mono_error_set_pending_exception (&error))
6560 if (method_is_dynamic (method)) {
6561 /* Creating a trampoline would leak memory */
6562 func = mono_compile_method (method);
6564 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6565 method = mono_object_get_virtual_method (target, method);
6566 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6567 if (mono_error_set_pending_exception (&error))
6569 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6572 mono_delegate_ctor_with_method (delegate, target, func, method);
6577 ICALL_EXPORT MonoMulticastDelegate *
6578 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6581 MonoMulticastDelegate *ret;
6583 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6585 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6586 if (mono_error_set_pending_exception (&error))
6589 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6594 ICALL_EXPORT MonoReflectionMethod*
6595 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6597 MonoReflectionMethod *ret = NULL;
6599 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6600 mono_error_set_pending_exception (&error);
6606 static inline gint32
6607 mono_array_get_byte_length (MonoArray *array)
6613 klass = array->obj.vtable->klass;
6615 if (array->bounds == NULL)
6616 length = array->max_length;
6619 for (i = 0; i < klass->rank; ++ i)
6620 length *= array->bounds [i].length;
6623 switch (klass->element_class->byval_arg.type) {
6626 case MONO_TYPE_BOOLEAN:
6630 case MONO_TYPE_CHAR:
6638 return length * sizeof (gpointer);
6649 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6651 return mono_array_get_byte_length (array);
6655 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6657 return mono_array_get (array, gint8, idx);
6661 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6663 mono_array_set (array, gint8, idx, value);
6666 ICALL_EXPORT MonoBoolean
6667 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6669 guint8 *src_buf, *dest_buf;
6672 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6676 g_assert (count >= 0);
6678 /* This is called directly from the class libraries without going through the managed wrapper */
6679 MONO_CHECK_ARG_NULL (src, FALSE);
6680 MONO_CHECK_ARG_NULL (dest, FALSE);
6682 /* watch out for integer overflow */
6683 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6686 src_buf = (guint8 *)src->vector + src_offset;
6687 dest_buf = (guint8 *)dest->vector + dest_offset;
6690 memcpy (dest_buf, src_buf, count);
6692 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6697 #ifndef DISABLE_REMOTING
6698 ICALL_EXPORT MonoObject *
6699 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6702 MonoDomain *domain = mono_object_domain (this_obj);
6704 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6705 MonoTransparentProxy *tp;
6709 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6710 if (mono_error_set_pending_exception (&error))
6713 tp = (MonoTransparentProxy*) res;
6715 MONO_OBJECT_SETREF (tp, rp, rp);
6716 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6717 klass = mono_class_from_mono_type (type);
6719 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6720 mono_class_setup_vtable (klass);
6721 if (mono_class_has_failure (klass)) {
6722 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6726 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6727 if (!is_ok (&error)) {
6728 mono_error_set_pending_exception (&error);
6731 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6732 if (!is_ok (&error)) {
6733 mono_error_set_pending_exception (&error);
6737 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6741 ICALL_EXPORT MonoReflectionType *
6742 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6745 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6746 mono_error_set_pending_exception (&error);
6752 /* System.Environment */
6755 ves_icall_System_Environment_get_UserName (void)
6757 /* using glib is more portable */
6758 return mono_string_new (mono_domain_get (), g_get_user_name ());
6762 ICALL_EXPORT MonoString *
6763 ves_icall_System_Environment_get_MachineName (void)
6765 #if defined (HOST_WIN32)
6770 len = MAX_COMPUTERNAME_LENGTH + 1;
6771 buf = g_new (gunichar2, len);
6774 if (GetComputerName (buf, (PDWORD) &len)) {
6776 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6777 mono_error_set_pending_exception (&error);
6782 #elif !defined(DISABLE_SOCKETS)
6786 #if defined _SC_HOST_NAME_MAX
6787 n = sysconf (_SC_HOST_NAME_MAX);
6791 buf = g_malloc (n+1);
6793 if (gethostname (buf, n) == 0){
6795 result = mono_string_new (mono_domain_get (), buf);
6802 return mono_string_new (mono_domain_get (), "mono");
6807 ves_icall_System_Environment_get_Platform (void)
6809 #if defined (TARGET_WIN32)
6812 #elif defined(__MACH__)
6815 // Notice that the value is hidden from user code, and only exposed
6816 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6817 // define and making assumptions based on Unix/128/4 values before there
6818 // was a MacOS define. Lots of code would assume that not-Unix meant
6819 // Windows, but in this case, it would be OSX.
6828 ICALL_EXPORT MonoString *
6829 ves_icall_System_Environment_get_NewLine (void)
6831 #if defined (HOST_WIN32)
6832 return mono_string_new (mono_domain_get (), "\r\n");
6834 return mono_string_new (mono_domain_get (), "\n");
6838 ICALL_EXPORT MonoBoolean
6839 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6841 #if SIZEOF_VOID_P == 8
6845 gboolean isWow64Process = FALSE;
6846 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6847 return (MonoBoolean)isWow64Process;
6849 #elif defined(HAVE_SYS_UTSNAME_H)
6850 struct utsname name;
6852 if (uname (&name) >= 0) {
6853 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6860 ICALL_EXPORT MonoString *
6861 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6869 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6870 value = g_getenv (utf8_name);
6877 return mono_string_new (mono_domain_get (), value);
6881 * There is no standard way to get at environ.
6884 #ifndef __MINGW32_VERSION
6885 #if defined(__APPLE__)
6886 #if defined (TARGET_OSX)
6887 /* Apple defines this in crt_externs.h but doesn't provide that header for
6888 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6889 * in fact exist on all implementations (so far)
6891 gchar ***_NSGetEnviron(void);
6892 #define environ (*_NSGetEnviron())
6894 static char *mono_environ[1] = { NULL };
6895 #define environ mono_environ
6896 #endif /* defined (TARGET_OSX) */
6904 ICALL_EXPORT MonoArray *
6905 ves_icall_System_Environment_GetCoomandLineArgs (void)
6908 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6909 mono_error_set_pending_exception (&error);
6913 ICALL_EXPORT MonoArray *
6914 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6926 env_strings = GetEnvironmentStrings();
6929 env_string = env_strings;
6930 while (*env_string != '\0') {
6931 /* weird case that MS seems to skip */
6932 if (*env_string != '=')
6934 while (*env_string != '\0')
6940 domain = mono_domain_get ();
6941 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6942 if (mono_error_set_pending_exception (&error))
6947 env_string = env_strings;
6948 while (*env_string != '\0') {
6949 /* weird case that MS seems to skip */
6950 if (*env_string != '=') {
6951 equal_str = wcschr(env_string, '=');
6952 g_assert(equal_str);
6954 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6955 if (mono_error_set_pending_exception (&error))
6958 mono_array_setref (names, n, str);
6961 while (*env_string != '\0')
6966 FreeEnvironmentStrings (env_strings);
6980 for (e = environ; *e != 0; ++ e)
6983 domain = mono_domain_get ();
6984 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6985 if (mono_error_set_pending_exception (&error))
6989 for (e = environ; *e != 0; ++ e) {
6990 parts = g_strsplit (*e, "=", 2);
6992 str = mono_string_new (domain, *parts);
6993 mono_array_setref (names, n, str);
7006 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
7008 #if !GLIB_CHECK_VERSION(2,4,0)
7009 #define g_setenv(a,b,c) setenv(a,b,c)
7010 #define g_unsetenv(a) unsetenv(a)
7014 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
7017 gunichar2 *utf16_name, *utf16_value;
7019 gchar *utf8_name, *utf8_value;
7024 utf16_name = mono_string_to_utf16 (name);
7025 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7026 SetEnvironmentVariable (utf16_name, NULL);
7027 g_free (utf16_name);
7031 utf16_value = mono_string_to_utf16 (value);
7033 SetEnvironmentVariable (utf16_name, utf16_value);
7035 g_free (utf16_name);
7036 g_free (utf16_value);
7038 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
7040 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7041 g_unsetenv (utf8_name);
7046 utf8_value = mono_string_to_utf8_checked (value, &error);
7047 if (!mono_error_ok (&error)) {
7049 mono_error_set_pending_exception (&error);
7052 g_setenv (utf8_name, utf8_value, TRUE);
7055 g_free (utf8_value);
7060 ves_icall_System_Environment_Exit (int result)
7062 mono_environment_exitcode_set (result);
7064 /* FIXME: There are some cleanup hangs that should be worked out, but
7065 * if the program is going to exit, everything will be cleaned up when
7066 * NaCl exits anyway.
7068 #ifndef __native_client__
7069 if (!mono_runtime_try_shutdown ())
7070 mono_thread_exit ();
7072 /* Suspend all managed threads since the runtime is going away */
7073 mono_thread_suspend_all_other_threads ();
7075 mono_runtime_quit ();
7078 /* we may need to do some cleanup here... */
7082 ICALL_EXPORT MonoString*
7083 ves_icall_System_Environment_GetGacPath (void)
7085 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
7088 ICALL_EXPORT MonoString*
7089 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
7091 #if defined (HOST_WIN32)
7092 #ifndef CSIDL_FLAG_CREATE
7093 #define CSIDL_FLAG_CREATE 0x8000
7096 WCHAR path [MAX_PATH];
7097 /* Create directory if no existing */
7098 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
7103 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
7104 mono_error_set_pending_exception (&error);
7108 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7110 return mono_string_new (mono_domain_get (), "");
7113 ICALL_EXPORT MonoArray *
7114 ves_icall_System_Environment_GetLogicalDrives (void)
7117 gunichar2 buf [256], *ptr, *dname;
7119 guint initial_size = 127, size = 128;
7122 MonoString *drivestr;
7123 MonoDomain *domain = mono_domain_get ();
7129 while (size > initial_size) {
7130 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
7131 if (size > initial_size) {
7134 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7135 initial_size = size;
7149 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7150 if (mono_error_set_pending_exception (&error))
7157 while (*u16) { u16++; len ++; }
7158 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7159 if (mono_error_set_pending_exception (&error))
7162 mono_array_setref (result, ndrives++, drivestr);
7173 ICALL_EXPORT MonoString *
7174 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7177 gunichar2 volume_name [MAX_PATH + 1];
7179 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7181 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
7182 mono_error_set_pending_exception (&error);
7186 ICALL_EXPORT MonoString *
7187 ves_icall_System_Environment_InternalGetHome (void)
7189 return mono_string_new (mono_domain_get (), g_get_home_dir ());
7192 static const char *encodings [] = {
7194 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7195 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7196 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7198 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7199 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7200 "x_unicode_2_0_utf_7",
7202 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7203 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7205 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7208 "unicodefffe", "utf_16be",
7215 * Returns the internal codepage, if the value of "int_code_page" is
7216 * 1 at entry, and we can not compute a suitable code page number,
7217 * returns the code page as a string
7219 ICALL_EXPORT MonoString*
7220 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
7225 char *codepage = NULL;
7227 int want_name = *int_code_page;
7230 *int_code_page = -1;
7232 g_get_charset (&cset);
7233 c = codepage = strdup (cset);
7234 for (c = codepage; *c; c++){
7235 if (isascii (*c) && isalpha (*c))
7240 /* g_print ("charset: %s\n", cset); */
7242 /* handle some common aliases */
7245 for (i = 0; p != 0; ){
7248 p = encodings [++i];
7251 if (strcmp (p, codepage) == 0){
7252 *int_code_page = code;
7255 p = encodings [++i];
7258 if (strstr (codepage, "utf_8") != NULL)
7259 *int_code_page |= 0x10000000;
7262 if (want_name && *int_code_page == -1)
7263 return mono_string_new (mono_domain_get (), cset);
7268 ICALL_EXPORT MonoBoolean
7269 ves_icall_System_Environment_get_HasShutdownStarted (void)
7271 if (mono_runtime_is_shutting_down ())
7274 if (mono_domain_is_unloading (mono_domain_get ()))
7281 ves_icall_System_Environment_BroadcastSettingChange (void)
7284 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7290 ves_icall_System_Environment_get_TickCount (void)
7292 /* this will overflow after ~24 days */
7293 return (gint32) (mono_msec_boottime () & 0xffffffff);
7297 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7303 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
7304 MonoReflectionMethod *method,
7305 MonoArray *out_args)
7307 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
7310 #ifndef DISABLE_REMOTING
7311 ICALL_EXPORT MonoBoolean
7312 ves_icall_IsTransparentProxy (MonoObject *proxy)
7317 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7323 ICALL_EXPORT MonoReflectionMethod *
7324 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7325 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7327 MonoReflectionMethod *ret = NULL;
7332 MonoMethod **vtable;
7333 MonoMethod *res = NULL;
7335 MONO_CHECK_ARG_NULL (rtype, NULL);
7336 MONO_CHECK_ARG_NULL (rmethod, NULL);
7338 method = rmethod->method;
7339 klass = mono_class_from_mono_type (rtype->type);
7340 mono_class_init_checked (klass, &error);
7341 if (mono_error_set_pending_exception (&error))
7344 if (MONO_CLASS_IS_INTERFACE (klass))
7347 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7350 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7351 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7357 mono_class_setup_vtable (klass);
7358 vtable = klass->vtable;
7360 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7361 gboolean variance_used = FALSE;
7362 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7363 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7365 res = vtable [offs + method->slot];
7367 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7370 if (method->slot != -1)
7371 res = vtable [method->slot];
7377 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7378 mono_error_set_pending_exception (&error);
7383 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7389 klass = mono_class_from_mono_type (type->type);
7390 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7391 if (!is_ok (&error)) {
7392 mono_error_set_pending_exception (&error);
7396 mono_vtable_set_is_remote (vtable, enable);
7399 #else /* DISABLE_REMOTING */
7402 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7404 g_assert_not_reached ();
7409 ICALL_EXPORT MonoObject *
7410 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7417 domain = mono_object_domain (type);
7418 klass = mono_class_from_mono_type (type->type);
7419 mono_class_init_checked (klass, &error);
7420 if (mono_error_set_pending_exception (&error))
7423 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7424 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7428 if (klass->rank >= 1) {
7429 g_assert (klass->rank == 1);
7430 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7431 mono_error_set_pending_exception (&error);
7434 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7435 if (!is_ok (&error)) {
7436 mono_error_set_pending_exception (&error);
7439 /* Bypass remoting object creation check */
7440 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7441 mono_error_set_pending_exception (&error);
7447 ICALL_EXPORT MonoString *
7448 ves_icall_System_IO_get_temp_path (void)
7450 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7453 #ifndef PLATFORM_NO_DRIVEINFO
7454 ICALL_EXPORT MonoBoolean
7455 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7456 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7460 ULARGE_INTEGER wapi_free_bytes_avail;
7461 ULARGE_INTEGER wapi_total_number_of_bytes;
7462 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7464 *error = ERROR_SUCCESS;
7465 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7466 &wapi_total_number_of_free_bytes);
7469 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7470 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7471 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7473 *free_bytes_avail = 0;
7474 *total_number_of_bytes = 0;
7475 *total_number_of_free_bytes = 0;
7476 *error = GetLastError ();
7482 ICALL_EXPORT guint32
7483 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7485 return GetDriveType (mono_string_chars (root_path_name));
7489 ICALL_EXPORT gpointer
7490 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7492 return mono_compile_method (method);
7495 ICALL_EXPORT MonoString *
7496 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7501 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7503 #if defined (HOST_WIN32)
7504 /* Avoid mixing '/' and '\\' */
7507 for (i = strlen (path) - 1; i >= 0; i--)
7508 if (path [i] == '/')
7512 mcpath = mono_string_new (mono_domain_get (), path);
7519 get_bundled_app_config (void)
7521 const gchar *app_config;
7524 gchar *config_file_name, *config_file_path;
7525 gsize len, config_file_path_length, config_ext_length;
7528 domain = mono_domain_get ();
7529 file = domain->setup->configuration_file;
7530 if (!file || file->length == 0)
7533 // Retrieve config file and remove the extension
7534 config_file_name = mono_string_to_utf8 (file);
7535 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7536 if (!config_file_path)
7537 config_file_path = config_file_name;
7539 config_file_path_length = strlen (config_file_path);
7540 config_ext_length = strlen (".config");
7541 if (config_file_path_length <= config_ext_length)
7544 len = config_file_path_length - config_ext_length;
7545 module = (gchar *)g_malloc0 (len + 1);
7546 memcpy (module, config_file_path, len);
7547 // Get the config file from the module name
7548 app_config = mono_config_string_for_assembly_file (module);
7551 if (config_file_name != config_file_path)
7552 g_free (config_file_name);
7553 g_free (config_file_path);
7558 return mono_string_new (mono_domain_get (), app_config);
7562 get_bundled_machine_config (void)
7564 const gchar *machine_config;
7566 machine_config = mono_get_machine_config ();
7568 if (!machine_config)
7571 return mono_string_new (mono_domain_get (), machine_config);
7574 ICALL_EXPORT MonoString *
7575 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7580 path = g_path_get_dirname (mono_get_config_dir ());
7582 #if defined (HOST_WIN32)
7583 /* Avoid mixing '/' and '\\' */
7586 for (i = strlen (path) - 1; i >= 0; i--)
7587 if (path [i] == '/')
7591 ipath = mono_string_new (mono_domain_get (), path);
7597 ICALL_EXPORT gboolean
7598 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7600 MonoPEResourceDataEntry *entry;
7603 if (!assembly || !result || !size)
7608 image = assembly->assembly->image;
7609 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7613 *result = mono_image_rva_map (image, entry->rde_data_offset);
7618 *size = entry->rde_size;
7623 ICALL_EXPORT MonoBoolean
7624 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7626 return mono_is_debugger_attached ();
7629 ICALL_EXPORT MonoBoolean
7630 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7632 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7633 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7639 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7641 if (mono_get_runtime_callbacks ()->debug_log)
7642 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7646 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7648 #if defined (HOST_WIN32)
7649 OutputDebugString (mono_string_chars (message));
7651 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7655 /* Only used for value types */
7656 ICALL_EXPORT MonoObject *
7657 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7664 domain = mono_object_domain (type);
7665 klass = mono_class_from_mono_type (type->type);
7666 mono_class_init_checked (klass, &error);
7667 if (mono_error_set_pending_exception (&error))
7670 if (mono_class_is_nullable (klass))
7671 /* No arguments -> null */
7674 result = mono_object_new_checked (domain, klass, &error);
7675 mono_error_set_pending_exception (&error);
7679 ICALL_EXPORT MonoReflectionMethod *
7680 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7682 MonoReflectionMethod *ret = NULL;
7685 MonoClass *klass, *parent;
7686 MonoGenericContext *generic_inst = NULL;
7687 MonoMethod *method = m->method;
7688 MonoMethod *result = NULL;
7691 if (method->klass == NULL)
7694 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7695 MONO_CLASS_IS_INTERFACE (method->klass) ||
7696 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7699 slot = mono_method_get_vtable_slot (method);
7703 klass = method->klass;
7704 if (klass->generic_class) {
7705 generic_inst = mono_class_get_context (klass);
7706 klass = klass->generic_class->container_class;
7710 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7711 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7712 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7713 or klass is the generic container class and generic_inst is the instantiation.
7715 when we go to the parent, if the parent is an open constructed type, we need to
7716 replace the type parameters by the definitions from the generic_inst, and then take it
7717 apart again into the klass and the generic_inst.
7719 For cases like this:
7720 class C<T> : B<T, int> {
7721 public override void Foo () { ... }
7723 class B<U,V> : A<HashMap<U,V>> {
7724 public override void Foo () { ... }
7727 public virtual void Foo () { ... }
7730 if at each iteration the parent isn't open, we can skip inflating it. if at some
7731 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7734 MonoGenericContext *parent_inst = NULL;
7735 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7736 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7737 if (!mono_error_ok (&error)) {
7738 mono_error_set_pending_exception (&error);
7742 if (parent->generic_class) {
7743 parent_inst = mono_class_get_context (parent);
7744 parent = parent->generic_class->container_class;
7747 mono_class_setup_vtable (parent);
7748 if (parent->vtable_size <= slot)
7751 generic_inst = parent_inst;
7754 klass = klass->parent;
7757 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7758 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7759 if (!mono_error_ok (&error)) {
7760 mono_error_set_pending_exception (&error);
7764 generic_inst = NULL;
7766 if (klass->generic_class) {
7767 generic_inst = mono_class_get_context (klass);
7768 klass = klass->generic_class->container_class;
7774 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7775 if (!mono_error_ok (&error)) {
7776 mono_error_set_pending_exception (&error);
7781 if (klass == method->klass)
7784 /*This is possible if definition == FALSE.
7785 * Do it here to be really sure we don't read invalid memory.
7787 if (slot >= klass->vtable_size)
7790 mono_class_setup_vtable (klass);
7792 result = klass->vtable [slot];
7793 if (result == NULL) {
7794 /* It is an abstract method */
7795 gpointer iter = NULL;
7796 while ((result = mono_class_get_methods (klass, &iter)))
7797 if (result->slot == slot)
7804 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7805 mono_error_set_pending_exception (&error);
7809 ICALL_EXPORT MonoString*
7810 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7812 MonoMethod *method = m->method;
7814 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7819 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7821 iter->sig = *(MonoMethodSignature**)argsp;
7823 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7824 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7827 /* FIXME: it's not documented what start is exactly... */
7831 iter->args = argsp + sizeof (gpointer);
7833 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7835 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7838 ICALL_EXPORT MonoTypedRef
7839 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7841 guint32 i, arg_size;
7845 i = iter->sig->sentinelpos + iter->next_arg;
7847 g_assert (i < iter->sig->param_count);
7849 res.type = iter->sig->params [i];
7850 res.klass = mono_class_from_mono_type (res.type);
7851 arg_size = mono_type_stack_size (res.type, &align);
7852 #if defined(__arm__) || defined(__mips__)
7853 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7855 res.value = iter->args;
7856 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7857 /* Values are stored as 8 byte register sized objects, but 'value'
7858 * is dereferenced as a pointer in other routines.
7860 res.value = (char*)res.value + 4;
7862 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7863 if (arg_size <= sizeof (gpointer)) {
7865 int padding = arg_size - mono_type_size (res.type, &dummy);
7866 res.value = (guint8*)res.value + padding;
7869 iter->args = (char*)iter->args + arg_size;
7872 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7877 ICALL_EXPORT MonoTypedRef
7878 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7880 guint32 i, arg_size;
7884 i = iter->sig->sentinelpos + iter->next_arg;
7886 g_assert (i < iter->sig->param_count);
7888 while (i < iter->sig->param_count) {
7889 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7891 res.type = iter->sig->params [i];
7892 res.klass = mono_class_from_mono_type (res.type);
7893 /* FIXME: endianess issue... */
7894 arg_size = mono_type_stack_size (res.type, &align);
7895 #if defined(__arm__) || defined(__mips__)
7896 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7898 res.value = iter->args;
7899 iter->args = (char*)iter->args + arg_size;
7901 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7904 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7912 ICALL_EXPORT MonoType*
7913 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7917 i = iter->sig->sentinelpos + iter->next_arg;
7919 g_assert (i < iter->sig->param_count);
7921 return iter->sig->params [i];
7924 ICALL_EXPORT MonoObject*
7925 mono_TypedReference_ToObject (MonoTypedRef* tref)
7928 MonoObject *result = NULL;
7929 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7930 MonoObject** objp = (MonoObject **)tref->value;
7934 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7935 mono_error_set_pending_exception (&error);
7939 ICALL_EXPORT MonoTypedRef
7940 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7943 MonoReflectionField *f;
7945 MonoType *ftype = NULL;
7949 memset (&res, 0, sizeof (res));
7952 g_assert (mono_array_length (fields) > 0);
7954 klass = target->vtable->klass;
7956 for (i = 0; i < mono_array_length (fields); ++i) {
7957 f = mono_array_get (fields, MonoReflectionField*, i);
7959 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7962 if (f->field->parent != klass) {
7963 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7967 p = (guint8*)target + f->field->offset;
7969 p += f->field->offset - sizeof (MonoObject);
7970 klass = mono_class_from_mono_type (f->field->type);
7971 ftype = f->field->type;
7975 res.klass = mono_class_from_mono_type (ftype);
7982 prelink_method (MonoMethod *method, MonoError *error)
7984 const char *exc_class, *exc_arg;
7986 mono_error_init (error);
7987 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7989 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7991 mono_error_set_exception_instance (error,
7992 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7995 /* create the wrapper, too? */
7999 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
8003 prelink_method (method->method, &error);
8004 mono_error_set_pending_exception (&error);
8008 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
8011 MonoClass *klass = mono_class_from_mono_type (type->type);
8013 gpointer iter = NULL;
8015 mono_class_init_checked (klass, &error);
8016 if (mono_error_set_pending_exception (&error))
8019 while ((m = mono_class_get_methods (klass, &iter))) {
8020 prelink_method (m, &error);
8021 if (mono_error_set_pending_exception (&error))
8026 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
8028 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
8029 gint32 const **exponents,
8030 gunichar2 const **digitLowerTable,
8031 gunichar2 const **digitUpperTable,
8032 gint64 const **tenPowersList,
8033 gint32 const **decHexDigits)
8035 *mantissas = Formatter_MantissaBitsTable;
8036 *exponents = Formatter_TensExponentTable;
8037 *digitLowerTable = Formatter_DigitLowerTable;
8038 *digitUpperTable = Formatter_DigitUpperTable;
8039 *tenPowersList = Formatter_TenPowersList;
8040 *decHexDigits = Formatter_DecHexDigits;
8044 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
8045 * and avoid useless allocations.
8048 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
8050 MonoReflectionType *rt;
8054 mono_error_init (error);
8055 for (i = 0; i < type->num_mods; ++i) {
8056 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
8061 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
8062 return_val_if_nok (error, NULL);
8064 for (i = 0; i < type->num_mods; ++i) {
8065 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
8066 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
8067 return_val_if_nok (error, NULL);
8069 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8070 return_val_if_nok (error, NULL);
8072 mono_array_setref (res, count, rt);
8079 ICALL_EXPORT MonoArray*
8080 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
8083 MonoType *type = param->ClassImpl->type;
8084 MonoClass *member_class = mono_object_class (param->MemberImpl);
8085 MonoMethod *method = NULL;
8088 MonoMethodSignature *sig;
8091 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8092 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8093 method = rmethod->method;
8094 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
8095 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8096 if (!(method = prop->property->get))
8097 method = prop->property->set;
8100 char *type_name = mono_type_get_full_name (member_class);
8101 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
8102 MonoException *ex = mono_get_exception_not_supported (msg);
8105 mono_set_pending_exception (ex);
8109 image = method->klass->image;
8110 pos = param->PositionImpl;
8111 sig = mono_method_signature (method);
8115 type = sig->params [pos];
8117 res = type_array_from_modifiers (image, type, optional, &error);
8118 mono_error_set_pending_exception (&error);
8123 get_property_type (MonoProperty *prop)
8125 MonoMethodSignature *sig;
8127 sig = mono_method_signature (prop->get);
8129 } else if (prop->set) {
8130 sig = mono_method_signature (prop->set);
8131 return sig->params [sig->param_count - 1];
8136 ICALL_EXPORT MonoArray*
8137 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
8140 MonoType *type = get_property_type (property->property);
8141 MonoImage *image = property->klass->image;
8146 res = type_array_from_modifiers (image, type, optional, &error);
8147 mono_error_set_pending_exception (&error);
8152 *Construct a MonoType suited to be used to decode a constant blob object.
8154 * @type is the target type which will be constructed
8155 * @blob_type is the blob type, for example, that comes from the constant table
8156 * @real_type is the expected constructed type.
8159 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8161 type->type = blob_type;
8162 type->data.klass = NULL;
8163 if (blob_type == MONO_TYPE_CLASS)
8164 type->data.klass = mono_defaults.object_class;
8165 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8166 /* For enums, we need to use the base type */
8167 type->type = MONO_TYPE_VALUETYPE;
8168 type->data.klass = mono_class_from_mono_type (real_type);
8170 type->data.klass = mono_class_from_mono_type (real_type);
8173 ICALL_EXPORT MonoObject*
8174 property_info_get_default_value (MonoReflectionProperty *property)
8178 MonoProperty *prop = property->property;
8179 MonoType *type = get_property_type (prop);
8180 MonoDomain *domain = mono_object_domain (property);
8181 MonoTypeEnum def_type;
8182 const char *def_value;
8185 mono_class_init (prop->parent);
8187 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8188 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8192 def_value = mono_class_get_property_default_value (prop, &def_type);
8194 mono_type_from_blob_type (&blob_type, def_type, type);
8195 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8197 mono_error_set_pending_exception (&error);
8201 ICALL_EXPORT MonoBoolean
8202 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8205 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8206 MonoCustomAttrInfo *cinfo;
8209 mono_class_init_checked (attr_class, &error);
8210 if (mono_error_set_pending_exception (&error))
8213 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8214 if (!is_ok (&error)) {
8215 mono_error_set_pending_exception (&error);
8220 found = mono_custom_attrs_has_attr (cinfo, attr_class);
8222 mono_custom_attrs_free (cinfo);
8226 ICALL_EXPORT MonoArray*
8227 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8229 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8234 mono_class_init_checked (attr_class, &error);
8235 if (mono_error_set_pending_exception (&error))
8239 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8240 if (!mono_error_ok (&error)) {
8241 mono_error_set_pending_exception (&error);
8248 ICALL_EXPORT MonoArray*
8249 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8253 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8254 mono_error_set_pending_exception (&error);
8259 ICALL_EXPORT MonoString*
8260 ves_icall_Mono_Runtime_GetDisplayName (void)
8263 MonoString *display_name;
8265 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8266 display_name = mono_string_new (mono_domain_get (), info);
8268 return display_name;
8271 ICALL_EXPORT MonoString*
8272 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8275 MonoString *message;
8279 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8280 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8283 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8285 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8286 if (mono_error_set_pending_exception (&error))
8293 ICALL_EXPORT gpointer
8294 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8296 return GetCurrentProcess ();
8299 ICALL_EXPORT MonoBoolean
8300 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8302 return GetExitCodeProcess (handle, (guint32*) exitcode);
8305 ICALL_EXPORT MonoBoolean
8306 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8308 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8309 return CloseHandle (handle);
8311 return CloseProcess (handle);
8315 ICALL_EXPORT MonoBoolean
8316 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8318 return TerminateProcess (handle, exitcode);
8322 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8324 return WaitForInputIdle (handle, milliseconds);
8327 ICALL_EXPORT MonoBoolean
8328 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8330 return GetProcessWorkingSetSize (handle, min, max);
8333 ICALL_EXPORT MonoBoolean
8334 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8336 return SetProcessWorkingSetSize (handle, min, max);
8339 ICALL_EXPORT MonoBoolean
8340 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8342 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8346 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8348 return mono_process_current_pid ();
8352 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8354 return GetPriorityClass (handle);
8357 ICALL_EXPORT MonoBoolean
8358 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8360 return SetPriorityClass (handle, priorityClass);
8363 #ifndef DISABLE_ICALL_TABLES
8365 #define ICALL_TYPE(id,name,first)
8366 #define ICALL(id,name,func) Icall_ ## id,
8369 #include "metadata/icall-def.h"
8375 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8376 #define ICALL(id,name,func)
8378 #include "metadata/icall-def.h"
8384 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8385 #define ICALL(id,name,func)
8387 guint16 first_icall;
8390 static const IcallTypeDesc
8391 icall_type_descs [] = {
8392 #include "metadata/icall-def.h"
8396 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8399 #define ICALL_TYPE(id,name,first)
8402 #ifdef HAVE_ARRAY_ELEM_INIT
8403 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8404 #define MSGSTRFIELD1(line) str##line
8406 static const struct msgstrtn_t {
8407 #define ICALL(id,name,func)
8409 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8410 #include "metadata/icall-def.h"
8412 } icall_type_names_str = {
8413 #define ICALL_TYPE(id,name,first) (name),
8414 #include "metadata/icall-def.h"
8417 static const guint16 icall_type_names_idx [] = {
8418 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8419 #include "metadata/icall-def.h"
8422 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8424 static const struct msgstr_t {
8426 #define ICALL_TYPE(id,name,first)
8427 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8428 #include "metadata/icall-def.h"
8430 } icall_names_str = {
8431 #define ICALL(id,name,func) (name),
8432 #include "metadata/icall-def.h"
8435 static const guint16 icall_names_idx [] = {
8436 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8437 #include "metadata/icall-def.h"
8440 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8446 #define ICALL_TYPE(id,name,first) name,
8447 #define ICALL(id,name,func)
8448 static const char* const
8449 icall_type_names [] = {
8450 #include "metadata/icall-def.h"
8454 #define icall_type_name_get(id) (icall_type_names [(id)])
8458 #define ICALL_TYPE(id,name,first)
8459 #define ICALL(id,name,func) name,
8460 static const char* const
8462 #include "metadata/icall-def.h"
8465 #define icall_name_get(id) icall_names [(id)]
8467 #endif /* !HAVE_ARRAY_ELEM_INIT */
8471 #define ICALL_TYPE(id,name,first)
8472 #define ICALL(id,name,func) func,
8473 static const gconstpointer
8474 icall_functions [] = {
8475 #include "metadata/icall-def.h"
8479 #ifdef ENABLE_ICALL_SYMBOL_MAP
8482 #define ICALL_TYPE(id,name,first)
8483 #define ICALL(id,name,func) #func,
8484 static const gconstpointer
8485 icall_symbols [] = {
8486 #include "metadata/icall-def.h"
8491 #endif /* DISABLE_ICALL_TABLES */
8493 static mono_mutex_t icall_mutex;
8494 static GHashTable *icall_hash = NULL;
8495 static GHashTable *jit_icall_hash_name = NULL;
8496 static GHashTable *jit_icall_hash_addr = NULL;
8499 mono_icall_init (void)
8501 #ifndef DISABLE_ICALL_TABLES
8504 /* check that tables are sorted: disable in release */
8507 const char *prev_class = NULL;
8508 const char *prev_method;
8510 for (i = 0; i < Icall_type_num; ++i) {
8511 const IcallTypeDesc *desc;
8514 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8515 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8516 prev_class = icall_type_name_get (i);
8517 desc = &icall_type_descs [i];
8518 num_icalls = icall_desc_num_icalls (desc);
8519 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8520 for (j = 0; j < num_icalls; ++j) {
8521 const char *methodn = icall_name_get (desc->first_icall + j);
8522 if (prev_method && strcmp (prev_method, methodn) >= 0)
8523 g_print ("method %s should come before method %s\n", methodn, prev_method);
8524 prev_method = methodn;
8530 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8531 mono_os_mutex_init (&icall_mutex);
8535 mono_icall_lock (void)
8537 mono_locks_os_acquire (&icall_mutex, IcallLock);
8541 mono_icall_unlock (void)
8543 mono_locks_os_release (&icall_mutex, IcallLock);
8547 mono_icall_cleanup (void)
8549 g_hash_table_destroy (icall_hash);
8550 g_hash_table_destroy (jit_icall_hash_name);
8551 g_hash_table_destroy (jit_icall_hash_addr);
8552 mono_os_mutex_destroy (&icall_mutex);
8556 * mono_add_internal_call:
8557 * @name: method specification to surface to the managed world
8558 * @method: pointer to a C method to invoke when the method is called
8560 * This method surfaces the C function pointed by @method as a method
8561 * that has been surfaced in managed code with the method specified in
8562 * @name as an internal call.
8564 * Internal calls are surfaced to all app domains loaded and they are
8565 * accessibly by a type with the specified name.
8567 * You must provide a fully qualified type name, that is namespaces
8568 * and type name, followed by a colon and the method name, with an
8569 * optional signature to bind.
8571 * For example, the following are all valid declarations:
8573 * "MyApp.Services.ScriptService:Accelerate"
8574 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8576 * You use method parameters in cases where there might be more than
8577 * one surface method to managed code. That way you can register different
8578 * internal calls for different method overloads.
8580 * The internal calls are invoked with no marshalling. This means that .NET
8581 * types like System.String are exposed as `MonoString *` parameters. This is
8582 * different than the way that strings are surfaced in P/Invoke.
8584 * For more information on how the parameters are marshalled, see the
8585 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8588 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8589 * reference for more information on the format of method descriptions.
8592 mono_add_internal_call (const char *name, gconstpointer method)
8596 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8598 mono_icall_unlock ();
8601 #ifndef DISABLE_ICALL_TABLES
8603 #ifdef HAVE_ARRAY_ELEM_INIT
8605 compare_method_imap (const void *key, const void *elem)
8607 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8608 return strcmp (key, method_name);
8612 find_method_icall (const IcallTypeDesc *imap, const char *name)
8614 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);
8617 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8621 compare_class_imap (const void *key, const void *elem)
8623 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8624 return strcmp (key, class_name);
8627 static const IcallTypeDesc*
8628 find_class_icalls (const char *name)
8630 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);
8633 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8636 #else /* HAVE_ARRAY_ELEM_INIT */
8639 compare_method_imap (const void *key, const void *elem)
8641 const char** method_name = (const char**)elem;
8642 return strcmp (key, *method_name);
8646 find_method_icall (const IcallTypeDesc *imap, const char *name)
8648 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8651 return (gpointer)icall_functions [(nameslot - icall_names)];
8655 compare_class_imap (const void *key, const void *elem)
8657 const char** class_name = (const char**)elem;
8658 return strcmp (key, *class_name);
8661 static const IcallTypeDesc*
8662 find_class_icalls (const char *name)
8664 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8667 return &icall_type_descs [nameslot - icall_type_names];
8670 #endif /* HAVE_ARRAY_ELEM_INIT */
8672 #endif /* DISABLE_ICALL_TABLES */
8675 * we should probably export this as an helper (handle nested types).
8676 * Returns the number of chars written in buf.
8679 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8681 int nspacelen, cnamelen;
8682 nspacelen = strlen (klass->name_space);
8683 cnamelen = strlen (klass->name);
8684 if (nspacelen + cnamelen + 2 > bufsize)
8687 memcpy (buf, klass->name_space, nspacelen);
8688 buf [nspacelen ++] = '.';
8690 memcpy (buf + nspacelen, klass->name, cnamelen);
8691 buf [nspacelen + cnamelen] = 0;
8692 return nspacelen + cnamelen;
8695 #ifdef DISABLE_ICALL_TABLES
8697 no_icall_table (void)
8699 g_assert_not_reached ();
8704 mono_lookup_internal_call (MonoMethod *method)
8709 int typelen = 0, mlen, siglen;
8711 #ifndef DISABLE_ICALL_TABLES
8712 const IcallTypeDesc *imap = NULL;
8715 g_assert (method != NULL);
8717 if (method->is_inflated)
8718 method = ((MonoMethodInflated *) method)->declaring;
8720 if (method->klass->nested_in) {
8721 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8725 mname [pos++] = '/';
8728 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8734 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8739 #ifndef DISABLE_ICALL_TABLES
8740 imap = find_class_icalls (mname);
8743 mname [typelen] = ':';
8744 mname [typelen + 1] = ':';
8746 mlen = strlen (method->name);
8747 memcpy (mname + typelen + 2, method->name, mlen);
8748 sigstart = mname + typelen + 2 + mlen;
8751 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8752 siglen = strlen (tmpsig);
8753 if (typelen + mlen + siglen + 6 > sizeof (mname))
8756 memcpy (sigstart + 1, tmpsig, siglen);
8757 sigstart [siglen + 1] = ')';
8758 sigstart [siglen + 2] = 0;
8763 res = g_hash_table_lookup (icall_hash, mname);
8765 mono_icall_unlock ();;
8768 /* try without signature */
8770 res = g_hash_table_lookup (icall_hash, mname);
8772 mono_icall_unlock ();
8776 #ifdef DISABLE_ICALL_TABLES
8777 mono_icall_unlock ();
8778 /* Fail only when the result is actually used */
8779 /* mono_marshal_get_native_wrapper () depends on this */
8780 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8781 return ves_icall_System_String_ctor_RedirectToCreateString;
8783 return no_icall_table;
8785 /* it wasn't found in the static call tables */
8787 mono_icall_unlock ();
8790 res = find_method_icall (imap, sigstart - mlen);
8792 mono_icall_unlock ();
8795 /* try _with_ signature */
8797 res = find_method_icall (imap, sigstart - mlen);
8799 mono_icall_unlock ();
8803 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8804 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8805 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8806 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8807 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");
8808 g_print ("If you see other errors or faults after this message they are probably related\n");
8809 g_print ("and you need to fix your mono install first.\n");
8811 mono_icall_unlock ();
8817 #ifdef ENABLE_ICALL_SYMBOL_MAP
8819 func_cmp (gconstpointer key, gconstpointer p)
8821 return (gsize)key - (gsize)*(gsize*)p;
8826 * mono_lookup_icall_symbol:
8828 * Given the icall METHOD, returns its C symbol.
8831 mono_lookup_icall_symbol (MonoMethod *m)
8833 #ifdef DISABLE_ICALL_TABLES
8834 g_assert_not_reached ();
8837 #ifdef ENABLE_ICALL_SYMBOL_MAP
8841 static gconstpointer *functions_sorted;
8842 static const char**symbols_sorted;
8843 static gboolean inited;
8848 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8849 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8850 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8851 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8852 /* Bubble sort the two arrays */
8856 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8857 if (functions_sorted [i] > functions_sorted [i + 1]) {
8860 tmp = functions_sorted [i];
8861 functions_sorted [i] = functions_sorted [i + 1];
8862 functions_sorted [i + 1] = tmp;
8863 tmp = symbols_sorted [i];
8864 symbols_sorted [i] = symbols_sorted [i + 1];
8865 symbols_sorted [i + 1] = tmp;
8872 func = mono_lookup_internal_call (m);
8875 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8879 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8881 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8882 g_assert_not_reached ();
8889 type_from_typename (char *type_name)
8891 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8893 if (!strcmp (type_name, "int"))
8894 klass = mono_defaults.int_class;
8895 else if (!strcmp (type_name, "ptr"))
8896 klass = mono_defaults.int_class;
8897 else if (!strcmp (type_name, "void"))
8898 klass = mono_defaults.void_class;
8899 else if (!strcmp (type_name, "int32"))
8900 klass = mono_defaults.int32_class;
8901 else if (!strcmp (type_name, "uint32"))
8902 klass = mono_defaults.uint32_class;
8903 else if (!strcmp (type_name, "int8"))
8904 klass = mono_defaults.sbyte_class;
8905 else if (!strcmp (type_name, "uint8"))
8906 klass = mono_defaults.byte_class;
8907 else if (!strcmp (type_name, "int16"))
8908 klass = mono_defaults.int16_class;
8909 else if (!strcmp (type_name, "uint16"))
8910 klass = mono_defaults.uint16_class;
8911 else if (!strcmp (type_name, "long"))
8912 klass = mono_defaults.int64_class;
8913 else if (!strcmp (type_name, "ulong"))
8914 klass = mono_defaults.uint64_class;
8915 else if (!strcmp (type_name, "float"))
8916 klass = mono_defaults.single_class;
8917 else if (!strcmp (type_name, "double"))
8918 klass = mono_defaults.double_class;
8919 else if (!strcmp (type_name, "object"))
8920 klass = mono_defaults.object_class;
8921 else if (!strcmp (type_name, "obj"))
8922 klass = mono_defaults.object_class;
8923 else if (!strcmp (type_name, "string"))
8924 klass = mono_defaults.string_class;
8925 else if (!strcmp (type_name, "bool"))
8926 klass = mono_defaults.boolean_class;
8927 else if (!strcmp (type_name, "boolean"))
8928 klass = mono_defaults.boolean_class;
8930 g_error ("%s", type_name);
8931 g_assert_not_reached ();
8933 return &klass->byval_arg;
8937 * LOCKING: Take the corlib image lock.
8939 MonoMethodSignature*
8940 mono_create_icall_signature (const char *sigstr)
8945 MonoMethodSignature *res, *res2;
8946 MonoImage *corlib = mono_defaults.corlib;
8948 mono_image_lock (corlib);
8949 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8950 mono_image_unlock (corlib);
8955 parts = g_strsplit (sigstr, " ", 256);
8964 res = mono_metadata_signature_alloc (corlib, len - 1);
8969 * Under windows, the default pinvoke calling convention is STDCALL but
8972 res->call_convention = MONO_CALL_C;
8975 res->ret = type_from_typename (parts [0]);
8976 for (i = 1; i < len; ++i) {
8977 res->params [i - 1] = type_from_typename (parts [i]);
8982 mono_image_lock (corlib);
8983 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8985 res = res2; /*Value is allocated in the image pool*/
8987 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8988 mono_image_unlock (corlib);
8994 mono_find_jit_icall_by_name (const char *name)
8996 MonoJitICallInfo *info;
8997 g_assert (jit_icall_hash_name);
9000 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9001 mono_icall_unlock ();
9006 mono_find_jit_icall_by_addr (gconstpointer addr)
9008 MonoJitICallInfo *info;
9009 g_assert (jit_icall_hash_addr);
9012 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
9013 mono_icall_unlock ();
9019 * mono_get_jit_icall_info:
9021 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
9022 * caller should access it while holding the icall lock.
9025 mono_get_jit_icall_info (void)
9027 return jit_icall_hash_name;
9031 * mono_lookup_jit_icall_symbol:
9033 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
9036 mono_lookup_jit_icall_symbol (const char *name)
9038 MonoJitICallInfo *info;
9039 const char *res = NULL;
9042 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9044 res = info->c_symbol;
9045 mono_icall_unlock ();
9050 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
9053 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
9054 mono_icall_unlock ();
9058 * 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
9059 * icalls without wrappers in some cases.
9062 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
9064 MonoJitICallInfo *info;
9071 if (!jit_icall_hash_name) {
9072 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
9073 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
9076 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
9077 g_warning ("jit icall already defined \"%s\"\n", name);
9078 g_assert_not_reached ();
9081 info = g_new0 (MonoJitICallInfo, 1);
9086 info->c_symbol = c_symbol;
9087 info->no_raise = no_raise;
9090 info->wrapper = func;
9092 info->wrapper = NULL;
9095 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
9096 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
9098 mono_icall_unlock ();
9103 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
9105 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);