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).
24 #ifdef HAVE_SYS_TIME_H
30 #if defined (HOST_WIN32)
33 #if defined (HAVE_WCHAR_H)
37 #include "mono/utils/mono-membar.h"
38 #include <mono/metadata/object.h>
39 #include <mono/metadata/threads.h>
40 #include <mono/metadata/threads-types.h>
41 #include <mono/metadata/threadpool-ms.h>
42 #include <mono/metadata/threadpool-ms-io.h>
43 #include <mono/metadata/monitor.h>
44 #include <mono/metadata/reflection.h>
45 #include <mono/metadata/assembly.h>
46 #include <mono/metadata/tabledefs.h>
47 #include <mono/metadata/exception.h>
48 #include <mono/metadata/file-io.h>
49 #include <mono/metadata/console-io.h>
50 #include <mono/metadata/mono-route.h>
51 #include <mono/metadata/socket-io.h>
52 #include <mono/metadata/mono-endian.h>
53 #include <mono/metadata/tokentype.h>
54 #include <mono/metadata/domain-internals.h>
55 #include <mono/metadata/metadata-internals.h>
56 #include <mono/metadata/class-internals.h>
57 #include <mono/metadata/reflection-internals.h>
58 #include <mono/metadata/marshal.h>
59 #include <mono/metadata/gc-internals.h>
60 #include <mono/metadata/mono-gc.h>
61 #include <mono/metadata/rand.h>
62 #include <mono/metadata/sysmath.h>
63 #include <mono/metadata/string-icalls.h>
64 #include <mono/metadata/debug-helpers.h>
65 #include <mono/metadata/process.h>
66 #include <mono/metadata/environment.h>
67 #include <mono/metadata/profiler-private.h>
68 #include <mono/metadata/locales.h>
69 #include <mono/metadata/filewatcher.h>
70 #include <mono/metadata/security.h>
71 #include <mono/metadata/mono-config.h>
72 #include <mono/metadata/cil-coff.h>
73 #include <mono/metadata/number-formatter.h>
74 #include <mono/metadata/security-manager.h>
75 #include <mono/metadata/security-core-clr.h>
76 #include <mono/metadata/mono-perfcounters.h>
77 #include <mono/metadata/mono-debug.h>
78 #include <mono/metadata/mono-ptr-array.h>
79 #include <mono/metadata/verify-internals.h>
80 #include <mono/metadata/runtime.h>
81 #include <mono/metadata/file-mmap.h>
82 #include <mono/metadata/seq-points-data.h>
83 #include <mono/io-layer/io-layer.h>
84 #include <mono/utils/monobitset.h>
85 #include <mono/utils/mono-time.h>
86 #include <mono/utils/mono-proclib.h>
87 #include <mono/utils/mono-string.h>
88 #include <mono/utils/mono-error-internals.h>
89 #include <mono/utils/mono-mmap.h>
90 #include <mono/utils/mono-io-portability.h>
91 #include <mono/utils/mono-digest.h>
92 #include <mono/utils/bsearch.h>
93 #include <mono/utils/mono-os-mutex.h>
94 #include <mono/utils/mono-threads.h>
96 #if defined (HOST_WIN32)
100 #include "decimal-ms.h"
101 #include "number-ms.h"
103 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
104 #include <sys/utsname.h>
107 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
109 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
112 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
114 static inline MonoBoolean
115 is_generic_parameter (MonoType *type)
117 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
121 mono_class_init_or_throw (MonoClass *klass)
123 if (!mono_class_init (klass))
124 mono_raise_exception (mono_class_get_exception_for_failure (klass));
127 ICALL_EXPORT MonoObject *
128 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
134 ac = (MonoClass *)arr->obj.vtable->klass;
136 esize = mono_array_element_size (ac);
137 ea = (gpointer*)((char*)arr->vector + (pos * esize));
139 if (ac->element_class->valuetype)
140 return mono_value_box (arr->obj.vtable->domain, ac->element_class, ea);
142 return (MonoObject *)*ea;
145 ICALL_EXPORT MonoObject *
146 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
152 MONO_CHECK_ARG_NULL (idxs, NULL);
155 ic = (MonoClass *)io->obj.vtable->klass;
157 ac = (MonoClass *)arr->obj.vtable->klass;
159 g_assert (ic->rank == 1);
160 if (io->bounds != NULL || io->max_length != ac->rank) {
161 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
165 ind = (gint32 *)io->vector;
167 if (arr->bounds == NULL) {
168 if (*ind < 0 || *ind >= arr->max_length) {
169 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
173 return ves_icall_System_Array_GetValueImpl (arr, *ind);
176 for (i = 0; i < ac->rank; i++) {
177 if ((ind [i] < arr->bounds [i].lower_bound) ||
178 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
179 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
184 pos = ind [0] - arr->bounds [0].lower_bound;
185 for (i = 1; i < ac->rank; i++)
186 pos = pos * arr->bounds [i].length + ind [i] -
187 arr->bounds [i].lower_bound;
189 return ves_icall_System_Array_GetValueImpl (arr, pos);
193 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
195 MonoClass *ac, *vc, *ec;
205 vc = value->vtable->klass;
209 ac = arr->obj.vtable->klass;
210 ec = ac->element_class;
212 esize = mono_array_element_size (ac);
213 ea = (gpointer*)((char*)arr->vector + (pos * esize));
214 va = (gpointer*)((char*)value + sizeof (MonoObject));
216 if (mono_class_is_nullable (ec)) {
217 mono_nullable_init ((guint8*)ea, value, ec);
222 mono_gc_bzero_atomic (ea, esize);
226 #define NO_WIDENING_CONVERSION G_STMT_START{\
227 mono_set_pending_exception (mono_get_exception_argument ( \
228 "value", "not a widening conversion")); \
232 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
233 if (esize < vsize + (extra)) { \
234 mono_set_pending_exception (mono_get_exception_argument ( \
235 "value", "not a widening conversion")); \
240 #define INVALID_CAST G_STMT_START{ \
241 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
242 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
246 /* Check element (destination) type. */
247 switch (ec->byval_arg.type) {
248 case MONO_TYPE_STRING:
249 switch (vc->byval_arg.type) {
250 case MONO_TYPE_STRING:
256 case MONO_TYPE_BOOLEAN:
257 switch (vc->byval_arg.type) {
258 case MONO_TYPE_BOOLEAN:
271 NO_WIDENING_CONVERSION;
280 if (!ec->valuetype) {
281 if (!mono_object_isinst (value, ec))
283 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
287 if (mono_object_isinst (value, ec)) {
288 if (ec->has_references)
289 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
291 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
298 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
300 et = ec->byval_arg.type;
301 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
302 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
304 vt = vc->byval_arg.type;
305 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
306 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
308 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
314 case MONO_TYPE_CHAR: \
315 CHECK_WIDENING_CONVERSION(0); \
316 *(etype *) ea = (etype) u64; \
318 /* You can't assign a signed value to an unsigned array. */ \
323 /* You can't assign a floating point number to an integer array. */ \
326 NO_WIDENING_CONVERSION; \
330 #define ASSIGN_SIGNED(etype) G_STMT_START{\
336 CHECK_WIDENING_CONVERSION(0); \
337 *(etype *) ea = (etype) i64; \
339 /* You can assign an unsigned value to a signed array if the array's */ \
340 /* element size is larger than the value size. */ \
345 case MONO_TYPE_CHAR: \
346 CHECK_WIDENING_CONVERSION(1); \
347 *(etype *) ea = (etype) u64; \
349 /* You can't assign a floating point number to an integer array. */ \
352 NO_WIDENING_CONVERSION; \
356 #define ASSIGN_REAL(etype) G_STMT_START{\
360 CHECK_WIDENING_CONVERSION(0); \
361 *(etype *) ea = (etype) r64; \
363 /* All integer values fit into a floating point array, so we don't */ \
364 /* need to CHECK_WIDENING_CONVERSION here. */ \
369 *(etype *) ea = (etype) i64; \
375 case MONO_TYPE_CHAR: \
376 *(etype *) ea = (etype) u64; \
383 u64 = *(guint8 *) va;
386 u64 = *(guint16 *) va;
389 u64 = *(guint32 *) va;
392 u64 = *(guint64 *) va;
398 i64 = *(gint16 *) va;
401 i64 = *(gint32 *) va;
404 i64 = *(gint64 *) va;
407 r64 = *(gfloat *) va;
410 r64 = *(gdouble *) va;
413 u64 = *(guint16 *) va;
415 case MONO_TYPE_BOOLEAN:
416 /* Boolean is only compatible with itself. */
429 NO_WIDENING_CONVERSION;
436 /* If we can't do a direct copy, let's try a widening conversion. */
439 ASSIGN_UNSIGNED (guint16);
441 ASSIGN_UNSIGNED (guint8);
443 ASSIGN_UNSIGNED (guint16);
445 ASSIGN_UNSIGNED (guint32);
447 ASSIGN_UNSIGNED (guint64);
449 ASSIGN_SIGNED (gint8);
451 ASSIGN_SIGNED (gint16);
453 ASSIGN_SIGNED (gint32);
455 ASSIGN_SIGNED (gint64);
457 ASSIGN_REAL (gfloat);
459 ASSIGN_REAL (gdouble);
463 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
467 #undef NO_WIDENING_CONVERSION
468 #undef CHECK_WIDENING_CONVERSION
469 #undef ASSIGN_UNSIGNED
475 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
481 MONO_CHECK_ARG_NULL (idxs,);
483 ic = idxs->obj.vtable->klass;
484 ac = arr->obj.vtable->klass;
486 g_assert (ic->rank == 1);
487 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
488 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
492 ind = (gint32 *)idxs->vector;
494 if (arr->bounds == NULL) {
495 if (*ind < 0 || *ind >= arr->max_length) {
496 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
500 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
504 for (i = 0; i < ac->rank; i++)
505 if ((ind [i] < arr->bounds [i].lower_bound) ||
506 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
507 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
511 pos = ind [0] - arr->bounds [0].lower_bound;
512 for (i = 1; i < ac->rank; i++)
513 pos = pos * arr->bounds [i].length + ind [i] -
514 arr->bounds [i].lower_bound;
516 ves_icall_System_Array_SetValueImpl (arr, value, pos);
519 ICALL_EXPORT MonoArray *
520 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
523 MonoClass *aklass, *klass;
526 gboolean bounded = FALSE;
528 MONO_CHECK_ARG_NULL (type, NULL);
529 MONO_CHECK_ARG_NULL (lengths, NULL);
531 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
533 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
535 for (i = 0; i < mono_array_length (lengths); i++) {
536 if (mono_array_get (lengths, gint32, i) < 0) {
537 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
542 klass = mono_class_from_mono_type (type->type);
543 mono_class_init_or_throw (klass);
545 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
546 /* vectors are not the same as one dimensional arrays with no-zero bounds */
551 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
553 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
554 for (i = 0; i < aklass->rank; ++i) {
555 sizes [i] = mono_array_get (lengths, guint32, i);
557 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
559 sizes [i + aklass->rank] = 0;
562 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
563 mono_error_set_pending_exception (&error);
568 ICALL_EXPORT MonoArray *
569 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
572 MonoClass *aklass, *klass;
575 gboolean bounded = FALSE;
577 MONO_CHECK_ARG_NULL (type, NULL);
578 MONO_CHECK_ARG_NULL (lengths, NULL);
580 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
582 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
584 for (i = 0; i < mono_array_length (lengths); i++) {
585 if ((mono_array_get (lengths, gint64, i) < 0) ||
586 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
587 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
592 klass = mono_class_from_mono_type (type->type);
593 mono_class_init_or_throw (klass);
595 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
596 /* vectors are not the same as one dimensional arrays with no-zero bounds */
601 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
603 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
604 for (i = 0; i < aklass->rank; ++i) {
605 sizes [i] = mono_array_get (lengths, guint64, i);
607 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
609 sizes [i + aklass->rank] = 0;
612 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
613 mono_error_set_pending_exception (&error);
619 ves_icall_System_Array_GetRank (MonoObject *arr)
621 return arr->vtable->klass->rank;
625 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
627 gint32 rank = arr->obj.vtable->klass->rank;
630 if ((dimension < 0) || (dimension >= rank)) {
631 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
635 if (arr->bounds == NULL)
636 length = arr->max_length;
638 length = arr->bounds [dimension].length;
640 #ifdef MONO_BIG_ARRAYS
641 if (length > G_MAXINT32) {
642 mono_set_pending_exception (mono_get_exception_overflow ());
650 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
652 gint32 rank = arr->obj.vtable->klass->rank;
654 if ((dimension < 0) || (dimension >= rank)) {
655 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
659 if (arr->bounds == NULL)
660 return arr->max_length;
662 return arr->bounds [dimension].length;
666 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
668 gint32 rank = arr->obj.vtable->klass->rank;
670 if ((dimension < 0) || (dimension >= rank)) {
671 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
675 if (arr->bounds == NULL)
678 return arr->bounds [dimension].lower_bound;
682 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
684 int sz = mono_array_element_size (mono_object_class (arr));
685 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
688 ICALL_EXPORT gboolean
689 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
694 MonoVTable *src_vtable;
695 MonoVTable *dest_vtable;
696 MonoClass *src_class;
697 MonoClass *dest_class;
699 src_vtable = source->obj.vtable;
700 dest_vtable = dest->obj.vtable;
702 if (src_vtable->rank != dest_vtable->rank)
705 if (source->bounds || dest->bounds)
708 /* there's no integer overflow since mono_array_length returns an unsigned integer */
709 if ((dest_idx + length > mono_array_length_fast (dest)) ||
710 (source_idx + length > mono_array_length_fast (source)))
713 src_class = src_vtable->klass->element_class;
714 dest_class = dest_vtable->klass->element_class;
717 * Handle common cases.
720 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
721 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
723 if (src_class == mono_defaults.object_class && dest_class->valuetype)
726 /* Check if we're copying a char[] <==> (u)short[] */
727 if (src_class != dest_class) {
728 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
731 /* 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. */
732 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
736 if (dest_class->valuetype) {
737 element_size = mono_array_element_size (source->obj.vtable->klass);
738 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
739 if (dest_class->has_references) {
740 mono_value_copy_array (dest, dest_idx, source_addr, length);
742 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
743 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
746 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
753 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
759 ac = (MonoClass *)arr->obj.vtable->klass;
761 esize = mono_array_element_size (ac);
762 ea = (gpointer*)((char*)arr->vector + (pos * esize));
764 mono_gc_memmove_atomic (value, ea, esize);
768 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
774 ac = (MonoClass *)arr->obj.vtable->klass;
775 ec = ac->element_class;
777 esize = mono_array_element_size (ac);
778 ea = (gpointer*)((char*)arr->vector + (pos * esize));
780 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
781 g_assert (esize == sizeof (gpointer));
782 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
784 g_assert (ec->inited);
785 g_assert (esize == mono_class_value_size (ec, NULL));
786 if (ec->has_references)
787 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
789 mono_gc_memmove_atomic (ea, value, esize);
794 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
796 MonoClass *klass = array->obj.vtable->klass;
797 guint32 size = mono_array_element_size (klass);
798 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
800 const char *field_data;
802 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
803 MonoException *exc = mono_get_exception_argument("array",
804 "Cannot initialize array of non-primitive type.");
805 mono_set_pending_exception (exc);
809 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
810 MonoException *exc = mono_get_exception_argument("field_handle",
811 "Field doesn't have an RVA");
812 mono_set_pending_exception (exc);
816 size *= array->max_length;
817 field_data = mono_field_get_data (field_handle);
819 if (size > mono_type_size (field_handle->type, &align)) {
820 MonoException *exc = mono_get_exception_argument("field_handle",
821 "Field not large enough to fill array");
822 mono_set_pending_exception (exc);
826 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
828 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
829 guint ## n *src = (guint ## n *) field_data; \
831 nEnt = (size / sizeof(guint ## n)); \
833 for (i = 0; i < nEnt; i++) { \
834 data[i] = read ## n (&src[i]); \
838 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
840 switch (type->type) {
857 memcpy (mono_array_addr (array, char, 0), field_data, size);
861 memcpy (mono_array_addr (array, char, 0), field_data, size);
866 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
868 return offsetof (MonoString, chars);
871 ICALL_EXPORT MonoObject *
872 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
874 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
878 MonoObject *ret = mono_object_clone_checked (obj, &error);
879 mono_error_set_pending_exception (&error);
886 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
891 MONO_CHECK_ARG_NULL (handle,);
893 klass = mono_class_from_mono_type (handle);
894 MONO_CHECK_ARG (handle, klass,);
896 if (klass->generic_container)
899 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
901 /* This will call the type constructor */
902 mono_runtime_class_init (vtable);
906 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
910 mono_image_check_for_module_cctor (image);
911 if (image->has_module_cctor) {
912 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
913 if (!mono_error_ok (&error)) {
914 mono_error_set_pending_exception (&error);
917 /*It's fine to raise the exception here*/
918 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
922 ICALL_EXPORT MonoBoolean
923 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
928 /* later make this configurable and per-arch */
929 int min_size = 4096 * 4 * sizeof (void*);
930 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
931 /* if we have no info we are optimistic and assume there is enough room */
935 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
939 current = (guint8 *)&stack_addr;
940 if (current > stack_addr) {
941 if ((current - stack_addr) < min_size)
944 if (current - (stack_addr - stack_size) < min_size)
950 ICALL_EXPORT MonoObject *
951 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
954 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
955 mono_error_set_pending_exception (&error);
961 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
964 MonoObject **values = NULL;
967 gint32 result = (int)(gsize)mono_defaults.int32_class;
968 MonoClassField* field;
971 klass = mono_object_class (this_obj);
973 if (mono_class_num_fields (klass) == 0)
977 * Compute the starting value of the hashcode for fields of primitive
978 * types, and return the remaining fields in an array to the managed side.
979 * This way, we can avoid costly reflection operations in managed code.
982 while ((field = mono_class_get_fields (klass, &iter))) {
983 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
985 if (mono_field_is_deleted (field))
987 /* FIXME: Add more types */
988 switch (field->type->type) {
990 result ^= *(gint32*)((guint8*)this_obj + field->offset);
992 case MONO_TYPE_STRING: {
994 s = *(MonoString**)((guint8*)this_obj + field->offset);
996 result ^= mono_string_hash (s);
1001 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1002 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1003 values [count++] = o;
1009 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1010 for (i = 0; i < count; ++i)
1011 mono_array_setref (*fields, i, values [i]);
1018 ICALL_EXPORT MonoBoolean
1019 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1022 MonoObject **values = NULL;
1024 MonoClassField* field;
1028 MONO_CHECK_ARG_NULL (that, FALSE);
1030 if (this_obj->vtable != that->vtable)
1033 klass = mono_object_class (this_obj);
1035 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1036 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1039 * Do the comparison for fields of primitive type and return a result if
1040 * possible. Otherwise, return the remaining fields in an array to the
1041 * managed side. This way, we can avoid costly reflection operations in
1046 while ((field = mono_class_get_fields (klass, &iter))) {
1047 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1049 if (mono_field_is_deleted (field))
1051 /* FIXME: Add more types */
1052 switch (field->type->type) {
1055 case MONO_TYPE_BOOLEAN:
1056 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1061 case MONO_TYPE_CHAR:
1062 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1067 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1072 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1076 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1080 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1085 case MONO_TYPE_STRING: {
1086 MonoString *s1, *s2;
1087 guint32 s1len, s2len;
1088 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1089 s2 = *(MonoString**)((guint8*)that + field->offset);
1092 if ((s1 == NULL) || (s2 == NULL))
1094 s1len = mono_string_length (s1);
1095 s2len = mono_string_length (s2);
1099 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1105 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1106 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1107 values [count++] = o;
1108 o = mono_field_get_value_object (mono_object_domain (this_obj), field, that);
1109 values [count++] = o;
1112 if (klass->enumtype)
1113 /* enums only have one non-static field */
1119 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1120 for (i = 0; i < count; ++i)
1121 mono_array_setref_fast (*fields, i, values [i]);
1128 ICALL_EXPORT MonoReflectionType *
1129 ves_icall_System_Object_GetType (MonoObject *obj)
1132 MonoReflectionType *ret;
1133 #ifndef DISABLE_REMOTING
1134 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1135 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1138 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1140 mono_error_raise_exception (&error);
1146 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1148 mtype->type = &obj->vtable->klass->byval_arg;
1149 g_assert (mtype->type->type);
1153 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1155 MONO_CHECK_ARG_NULL (obj, 0);
1157 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1161 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1162 MonoReflectionMethod *method,
1163 MonoArray *opt_param_types)
1165 MONO_CHECK_ARG_NULL (method, 0);
1167 return mono_image_create_method_token (
1168 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1172 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1174 mono_image_create_pefile (mb, file);
1178 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1180 mono_image_build_metadata (mb);
1184 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1186 mono_image_register_token (mb->dynamic_image, token, obj);
1189 ICALL_EXPORT MonoObject*
1190 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1194 mono_loader_lock ();
1195 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1196 mono_loader_unlock ();
1202 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1204 MonoMethod **dest = (MonoMethod **)data;
1206 /* skip unmanaged frames */
1222 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1224 MonoMethod **dest = (MonoMethod **)data;
1226 /* skip unmanaged frames */
1231 if (!strcmp (m->klass->name_space, "System.Reflection"))
1240 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1242 MonoMethod **dest = (MonoMethod **)data;
1244 /* skip unmanaged frames */
1248 if (m->wrapper_type != MONO_WRAPPER_NONE)
1251 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1265 static MonoReflectionType *
1266 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase)
1269 MonoReflectionType *ret;
1270 MonoMethod *m, *dest;
1272 MonoType *type = NULL;
1273 MonoAssembly *assembly = NULL;
1274 gboolean type_resolve = FALSE;
1277 * We must compute the calling assembly as type loading must happen under a metadata context.
1278 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1279 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1281 m = mono_method_get_last_managed ();
1284 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1289 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1290 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1291 * to crash. This only seems to happen in some strange remoting
1292 * scenarios and I was unable to figure out what's happening there.
1293 * Dec 10, 2005 - Martin.
1297 assembly = dest->klass->image->assembly;
1298 type_resolve = TRUE;
1300 g_warning (G_STRLOC);
1303 if (info->assembly.name)
1304 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1308 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1309 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1312 if (!info->assembly.name && !type) /* try mscorlib */
1313 type = mono_reflection_get_type (NULL, info, ignoreCase, &type_resolve);
1315 if (assembly && !type && type_resolve) {
1316 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1317 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1323 ret = mono_type_get_object_checked (mono_domain_get (), type, &error);
1324 mono_error_raise_exception (&error); /* FIXME don't raise here */
1330 MonoReflectionType *
1331 mono_type_get (const char *str)
1333 char *copy = g_strdup (str);
1334 MonoTypeNameParse info;
1335 MonoReflectionType *type;
1338 parsedOk = mono_reflection_parse_type(copy, &info);
1340 mono_reflection_free_type_info (&info);
1345 type = type_from_parsed_name (&info, FALSE);
1347 mono_reflection_free_type_info (&info);
1354 ICALL_EXPORT MonoReflectionType*
1355 ves_icall_type_from_name (MonoString *name,
1356 MonoBoolean throwOnError,
1357 MonoBoolean ignoreCase)
1359 char *str = mono_string_to_utf8 (name);
1360 MonoTypeNameParse info;
1361 MonoReflectionType *type;
1364 parsedOk = mono_reflection_parse_type (str, &info);
1366 /* mono_reflection_parse_type() mangles the string */
1368 mono_reflection_free_type_info (&info);
1371 mono_set_pending_exception (mono_get_exception_argument("typeName", "failed parse"));
1376 type = type_from_parsed_name (&info, ignoreCase);
1378 mono_reflection_free_type_info (&info);
1382 MonoException *e = NULL;
1385 e = mono_get_exception_type_load (name, NULL);
1387 mono_loader_clear_error ();
1389 mono_set_pending_exception (e);
1398 ICALL_EXPORT MonoReflectionType*
1399 ves_icall_type_from_handle (MonoType *handle)
1402 MonoReflectionType *ret;
1403 MonoDomain *domain = mono_domain_get ();
1405 ret = mono_type_get_object_checked (domain, handle, &error);
1406 mono_error_raise_exception (&error);
1411 /* System.TypeCode */
1430 TYPECODE_STRING = 18
1433 ICALL_EXPORT guint32
1434 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1436 int t = type->type->type;
1438 if (type->type->byref)
1439 return TYPECODE_OBJECT;
1443 case MONO_TYPE_VOID:
1444 return TYPECODE_OBJECT;
1445 case MONO_TYPE_BOOLEAN:
1446 return TYPECODE_BOOLEAN;
1448 return TYPECODE_BYTE;
1450 return TYPECODE_SBYTE;
1452 return TYPECODE_UINT16;
1454 return TYPECODE_INT16;
1455 case MONO_TYPE_CHAR:
1456 return TYPECODE_CHAR;
1460 return TYPECODE_OBJECT;
1462 return TYPECODE_UINT32;
1464 return TYPECODE_INT32;
1466 return TYPECODE_UINT64;
1468 return TYPECODE_INT64;
1470 return TYPECODE_SINGLE;
1472 return TYPECODE_DOUBLE;
1473 case MONO_TYPE_VALUETYPE: {
1474 MonoClass *klass = type->type->data.klass;
1476 if (klass->enumtype) {
1477 t = mono_class_enum_basetype (klass)->type;
1479 } else if (mono_is_corlib_image (klass->image)) {
1480 if (strcmp (klass->name_space, "System") == 0) {
1481 if (strcmp (klass->name, "Decimal") == 0)
1482 return TYPECODE_DECIMAL;
1483 else if (strcmp (klass->name, "DateTime") == 0)
1484 return TYPECODE_DATETIME;
1487 return TYPECODE_OBJECT;
1489 case MONO_TYPE_STRING:
1490 return TYPECODE_STRING;
1491 case MONO_TYPE_SZARRAY:
1492 case MONO_TYPE_ARRAY:
1493 case MONO_TYPE_OBJECT:
1495 case MONO_TYPE_MVAR:
1496 case MONO_TYPE_TYPEDBYREF:
1497 return TYPECODE_OBJECT;
1498 case MONO_TYPE_CLASS:
1500 MonoClass *klass = type->type->data.klass;
1501 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1502 if (strcmp (klass->name, "DBNull") == 0)
1503 return TYPECODE_DBNULL;
1506 return TYPECODE_OBJECT;
1507 case MONO_TYPE_GENERICINST:
1508 return TYPECODE_OBJECT;
1510 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1516 mono_type_is_primitive (MonoType *type)
1518 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1519 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1523 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1525 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1526 return mono_class_enum_basetype (type->data.klass);
1527 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1528 return mono_class_enum_basetype (type->data.generic_class->container_class);
1532 ICALL_EXPORT guint32
1533 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1538 g_assert (type != NULL);
1540 klass = mono_class_from_mono_type (type->type);
1541 klassc = mono_class_from_mono_type (c->type);
1543 if (type->type->byref ^ c->type->byref)
1546 if (type->type->byref) {
1547 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1548 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1550 klass = mono_class_from_mono_type (t);
1551 klassc = mono_class_from_mono_type (ot);
1553 if (mono_type_is_primitive (t)) {
1554 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1555 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1556 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1557 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1558 return t->type == ot->type;
1560 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1563 if (klass->valuetype)
1564 return klass == klassc;
1565 return klass->valuetype == klassc->valuetype;
1568 return mono_class_is_assignable_from (klass, klassc);
1571 ICALL_EXPORT guint32
1572 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1574 MonoClass *klass = mono_class_from_mono_type (type->type);
1575 mono_class_init_or_throw (klass);
1576 return mono_object_isinst (obj, klass) != NULL;
1579 ICALL_EXPORT guint32
1580 ves_icall_get_attributes (MonoReflectionType *type)
1582 MonoClass *klass = mono_class_from_mono_type (type->type);
1583 return klass->flags;
1586 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1587 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1589 MonoClass *klass = field->field->parent;
1590 MonoMarshalType *info;
1594 if (klass->generic_container ||
1595 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1598 ftype = mono_field_get_type (field->field);
1599 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1602 info = mono_marshal_load_type_info (klass);
1604 for (i = 0; i < info->num_fields; ++i) {
1605 if (info->fields [i].field == field->field) {
1606 if (!info->fields [i].mspec)
1609 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1616 ICALL_EXPORT MonoReflectionField*
1617 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1620 gboolean found = FALSE;
1627 klass = handle->parent;
1629 klass = mono_class_from_mono_type (type);
1631 /* Check that the field belongs to the class */
1632 for (k = klass; k; k = k->parent) {
1633 if (k == handle->parent) {
1640 /* The managed code will throw the exception */
1644 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1645 mono_error_raise_exception (&error);
1649 ICALL_EXPORT MonoArray*
1650 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1653 MonoType *type = mono_field_get_type_checked (field->field, &error);
1654 if (!mono_error_ok (&error)) {
1655 mono_error_set_pending_exception (&error);
1659 return type_array_from_modifiers (field->field->parent->image, type, optional);
1663 vell_icall_get_method_attributes (MonoMethod *method)
1665 return method->flags;
1669 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1672 MonoReflectionType *rt;
1673 MonoDomain *domain = mono_domain_get ();
1674 MonoMethodSignature* sig;
1676 sig = mono_method_signature_checked (method, &error);
1677 if (!mono_error_ok (&error)) {
1678 mono_error_set_pending_exception (&error);
1682 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1683 if (!mono_error_ok (&error)) {
1684 mono_error_set_pending_exception (&error);
1688 MONO_STRUCT_SETREF (info, parent, rt);
1690 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1691 if (!mono_error_ok (&error)) {
1692 mono_error_set_pending_exception (&error);
1696 MONO_STRUCT_SETREF (info, ret, rt);
1698 info->attrs = method->flags;
1699 info->implattrs = method->iflags;
1700 if (sig->call_convention == MONO_CALL_DEFAULT)
1701 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1703 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1708 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1711 ICALL_EXPORT MonoArray*
1712 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1714 MonoDomain *domain = mono_domain_get ();
1716 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1719 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1720 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1722 MonoDomain *domain = mono_domain_get ();
1723 MonoReflectionMarshalAsAttribute* res = NULL;
1724 MonoMarshalSpec **mspecs;
1727 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1728 mono_method_get_marshal_info (method, mspecs);
1731 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1733 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1735 mono_metadata_free_marshal_spec (mspecs [i]);
1742 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1744 MonoClass *parent = field->field->parent;
1745 if (!parent->size_inited)
1746 mono_class_init (parent);
1747 mono_class_setup_fields_locking (parent);
1749 return field->field->offset - sizeof (MonoObject);
1752 ICALL_EXPORT MonoReflectionType*
1753 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1756 MonoReflectionType *ret;
1759 parent = declaring? field->field->parent: field->klass;
1761 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1762 mono_error_raise_exception (&error);
1768 ICALL_EXPORT MonoObject *
1769 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1771 MonoClass *fklass = field->klass;
1772 MonoClassField *cf = field->field;
1773 MonoDomain *domain = mono_object_domain (field);
1775 if (fklass->image->assembly->ref_only) {
1776 mono_set_pending_exception (mono_get_exception_invalid_operation (
1777 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1781 if (mono_security_core_clr_enabled ())
1782 mono_security_core_clr_ensure_reflection_access_field (cf);
1784 return mono_field_get_value_object (domain, cf, obj);
1788 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1791 MonoClassField *cf = field->field;
1795 if (field->klass->image->assembly->ref_only) {
1796 mono_set_pending_exception (mono_get_exception_invalid_operation (
1797 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1801 if (mono_security_core_clr_enabled ())
1802 mono_security_core_clr_ensure_reflection_access_field (cf);
1804 type = mono_field_get_type_checked (cf, &error);
1805 if (!mono_error_ok (&error)) {
1806 mono_error_set_pending_exception (&error);
1810 v = (gchar *) value;
1812 switch (type->type) {
1815 case MONO_TYPE_BOOLEAN:
1818 case MONO_TYPE_CHAR:
1827 case MONO_TYPE_VALUETYPE:
1830 v += sizeof (MonoObject);
1832 case MONO_TYPE_STRING:
1833 case MONO_TYPE_OBJECT:
1834 case MONO_TYPE_CLASS:
1835 case MONO_TYPE_ARRAY:
1836 case MONO_TYPE_SZARRAY:
1839 case MONO_TYPE_GENERICINST: {
1840 MonoGenericClass *gclass = type->data.generic_class;
1841 g_assert (!gclass->context.class_inst->is_open);
1843 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1844 MonoClass *nklass = mono_class_from_mono_type (type);
1845 MonoObject *nullable;
1848 * Convert the boxed vtype into a Nullable structure.
1849 * This is complicated by the fact that Nullables have
1850 * a variable structure.
1852 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1853 if (!mono_error_ok (&error)) {
1854 mono_error_set_pending_exception (&error);
1858 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1860 v = (gchar *)mono_object_unbox (nullable);
1863 if (gclass->container_class->valuetype && (v != NULL))
1864 v += sizeof (MonoObject);
1868 g_error ("type 0x%x not handled in "
1869 "ves_icall_FieldInfo_SetValueInternal", type->type);
1874 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1875 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1876 if (!vtable->initialized)
1877 mono_runtime_class_init (vtable);
1878 mono_field_static_set_value (vtable, cf, v);
1880 mono_field_set_value (obj, cf, v);
1885 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1894 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1895 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1899 if (MONO_TYPE_IS_REFERENCE (f->type))
1900 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1902 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1905 ICALL_EXPORT MonoObject *
1906 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1908 MonoObject *o = NULL;
1909 MonoClassField *field = rfield->field;
1911 MonoDomain *domain = mono_object_domain (rfield);
1913 MonoTypeEnum def_type;
1914 const char *def_value;
1918 mono_class_init (field->parent);
1920 t = mono_field_get_type_checked (field, &error);
1921 if (!mono_error_ok (&error)) {
1922 mono_error_set_pending_exception (&error);
1926 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
1927 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1931 if (image_is_dynamic (field->parent->image)) {
1932 MonoClass *klass = field->parent;
1933 int fidx = field - klass->fields;
1935 g_assert (fidx >= 0 && fidx < klass->field.count);
1936 g_assert (klass->ext);
1937 g_assert (klass->ext->field_def_values);
1938 def_type = klass->ext->field_def_values [fidx].def_type;
1939 def_value = klass->ext->field_def_values [fidx].data;
1940 if (def_type == MONO_TYPE_END) {
1941 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1945 def_value = mono_class_get_field_default_value (field, &def_type);
1946 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
1948 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1953 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1957 case MONO_TYPE_BOOLEAN:
1960 case MONO_TYPE_CHAR:
1968 case MONO_TYPE_R8: {
1971 /* boxed value type */
1972 t = g_new0 (MonoType, 1);
1974 klass = mono_class_from_mono_type (t);
1976 o = mono_object_new_checked (domain, klass, &error);
1977 if (!mono_error_ok (&error)) {
1978 mono_error_set_pending_exception (&error);
1981 v = ((gchar *) o) + sizeof (MonoObject);
1982 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1985 case MONO_TYPE_STRING:
1986 case MONO_TYPE_CLASS:
1987 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1990 g_assert_not_reached ();
1996 ICALL_EXPORT MonoReflectionType*
1997 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2000 MonoReflectionType *ret;
2003 type = mono_field_get_type_checked (ref_field->field, &error);
2004 if (!mono_error_ok (&error)) {
2005 mono_error_set_pending_exception (&error);
2009 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2010 if (!mono_error_ok (&error)) {
2011 mono_error_set_pending_exception (&error);
2018 /* From MonoProperty.cs */
2020 PInfo_Attributes = 1,
2021 PInfo_GetMethod = 1 << 1,
2022 PInfo_SetMethod = 1 << 2,
2023 PInfo_ReflectedType = 1 << 3,
2024 PInfo_DeclaringType = 1 << 4,
2029 ves_icall_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2032 MonoReflectionType *rt;
2033 MonoReflectionMethod *rm;
2034 MonoDomain *domain = mono_object_domain (property);
2035 const MonoProperty *pproperty = property->property;
2037 if ((req_info & PInfo_ReflectedType) != 0) {
2038 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2039 mono_error_raise_exception (&error);
2041 MONO_STRUCT_SETREF (info, parent, rt);
2043 if ((req_info & PInfo_DeclaringType) != 0) {
2044 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2045 mono_error_raise_exception (&error);
2047 MONO_STRUCT_SETREF (info, declaring_type, rt);
2050 if ((req_info & PInfo_Name) != 0)
2051 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2053 if ((req_info & PInfo_Attributes) != 0)
2054 info->attrs = pproperty->attrs;
2056 if ((req_info & PInfo_GetMethod) != 0) {
2057 if (pproperty->get &&
2058 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2059 pproperty->get->klass == property->klass)) {
2060 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2061 mono_error_raise_exception (&error);
2066 MONO_STRUCT_SETREF (info, get, rm);
2068 if ((req_info & PInfo_SetMethod) != 0) {
2069 if (pproperty->set &&
2070 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2071 pproperty->set->klass == property->klass)) {
2072 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2073 mono_error_raise_exception (&error);
2078 MONO_STRUCT_SETREF (info, set, rm);
2081 * There may be other methods defined for properties, though, it seems they are not exposed
2082 * in the reflection API
2087 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2090 MonoReflectionType *rt;
2091 MonoReflectionMethod *rm;
2092 MonoDomain *domain = mono_object_domain (event);
2094 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2095 mono_error_raise_exception (&error);
2097 MONO_STRUCT_SETREF (info, reflected_type, rt);
2099 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2100 mono_error_raise_exception (&error);
2102 MONO_STRUCT_SETREF (info, declaring_type, rt);
2104 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2105 info->attrs = event->event->attrs;
2107 if (event->event->add) {
2108 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2109 mono_error_raise_exception (&error);
2114 MONO_STRUCT_SETREF (info, add_method, rm);
2116 if (event->event->remove) {
2117 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2118 mono_error_raise_exception (&error);
2123 MONO_STRUCT_SETREF (info, remove_method, rm);
2125 if (event->event->raise) {
2126 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2127 mono_error_raise_exception (&error);
2132 MONO_STRUCT_SETREF (info, raise_method, rm);
2134 #ifndef MONO_SMALL_CONFIG
2135 if (event->event->other) {
2137 while (event->event->other [n])
2139 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2141 for (i = 0; i < n; i++) {
2142 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2143 mono_error_raise_exception (&error);
2144 mono_array_setref (info->other_methods, i, rm);
2151 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2156 mono_class_setup_interfaces (klass, error);
2157 if (!mono_error_ok (error))
2160 for (i = 0; i < klass->interface_count; i++) {
2161 ic = klass->interfaces [i];
2162 g_hash_table_insert (ifaces, ic, ic);
2164 collect_interfaces (ic, ifaces, error);
2165 if (!mono_error_ok (error))
2171 MonoArray *iface_array;
2172 MonoGenericContext *context;
2176 } FillIfaceArrayData;
2179 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2181 MonoReflectionType *rt;
2182 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2183 MonoClass *ic = (MonoClass *)key;
2184 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2186 if (!mono_error_ok (data->error))
2189 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2190 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2191 if (!mono_error_ok (data->error))
2195 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2196 if (!mono_error_ok (data->error))
2199 mono_array_setref (data->iface_array, data->next_idx++, rt);
2202 mono_metadata_free_type (inflated);
2206 get_interfaces_hash (gconstpointer v1)
2208 MonoClass *k = (MonoClass*)v1;
2210 return k->type_token;
2213 ICALL_EXPORT MonoArray*
2214 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2217 MonoClass *klass = mono_class_from_mono_type (type->type);
2219 FillIfaceArrayData data = { 0 };
2222 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2224 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2225 data.context = mono_class_get_context (klass);
2226 klass = klass->generic_class->container_class;
2229 for (parent = klass; parent; parent = parent->parent) {
2230 mono_class_setup_interfaces (parent, &error);
2231 if (!mono_error_ok (&error))
2233 collect_interfaces (parent, iface_hash, &error);
2234 if (!mono_error_ok (&error))
2238 data.error = &error;
2239 data.domain = mono_object_domain (type);
2241 len = g_hash_table_size (iface_hash);
2243 g_hash_table_destroy (iface_hash);
2244 if (!data.domain->empty_types)
2245 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2246 return data.domain->empty_types;
2249 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2250 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2251 if (!mono_error_ok (&error))
2254 g_hash_table_destroy (iface_hash);
2255 return data.iface_array;
2258 g_hash_table_destroy (iface_hash);
2259 mono_error_set_pending_exception (&error);
2264 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2266 gboolean variance_used;
2267 MonoClass *klass = mono_class_from_mono_type (type->type);
2268 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2269 MonoReflectionMethod *member;
2272 int i = 0, len, ioffset;
2276 mono_class_init_or_throw (klass);
2277 mono_class_init_or_throw (iclass);
2279 mono_class_setup_vtable (klass);
2281 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2285 len = mono_class_num_methods (iclass);
2286 domain = mono_object_domain (type);
2287 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2288 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2290 while ((method = mono_class_get_methods (iclass, &iter))) {
2291 member = mono_method_get_object_checked (domain, method, iclass, &error);
2292 mono_error_raise_exception (&error);
2293 mono_array_setref (*methods, i, member);
2294 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2295 mono_error_raise_exception (&error);
2296 mono_array_setref (*targets, i, member);
2303 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2305 MonoClass *klass = mono_class_from_mono_type (type->type);
2306 mono_class_init_or_throw (klass);
2308 if (image_is_dynamic (klass->image)) {
2309 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2310 *packing = tb->packing_size;
2311 *size = tb->class_size;
2313 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2317 ICALL_EXPORT MonoReflectionType*
2318 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2321 MonoReflectionType *ret;
2324 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2325 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2326 mono_error_raise_exception (&error);
2331 klass = mono_class_from_mono_type (type->type);
2332 mono_class_init_or_throw (klass);
2334 // GetElementType should only return a type for:
2335 // Array Pointer PassedByRef
2336 if (type->type->byref)
2337 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2338 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2339 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2340 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2341 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2345 mono_error_raise_exception (&error);
2350 ICALL_EXPORT MonoReflectionType*
2351 ves_icall_get_type_parent (MonoReflectionType *type)
2354 MonoReflectionType *ret;
2356 if (type->type->byref)
2359 MonoClass *klass = mono_class_from_mono_type (type->type);
2363 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2364 mono_error_raise_exception (&error);
2369 ICALL_EXPORT MonoBoolean
2370 ves_icall_type_ispointer (MonoReflectionType *type)
2372 return type->type->type == MONO_TYPE_PTR;
2375 ICALL_EXPORT MonoBoolean
2376 ves_icall_type_isprimitive (MonoReflectionType *type)
2378 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)));
2381 ICALL_EXPORT MonoBoolean
2382 ves_icall_type_isbyref (MonoReflectionType *type)
2384 return type->type->byref;
2387 ICALL_EXPORT MonoBoolean
2388 ves_icall_type_iscomobject (MonoReflectionType *type)
2390 MonoClass *klass = mono_class_from_mono_type (type->type);
2391 mono_class_init_or_throw (klass);
2393 return mono_class_is_com_object (klass);
2396 ICALL_EXPORT MonoReflectionModule*
2397 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2399 MonoClass *klass = mono_class_from_mono_type (type->type);
2400 return mono_module_get_object (mono_object_domain (type), klass->image);
2403 ICALL_EXPORT MonoReflectionAssembly*
2404 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2406 MonoDomain *domain = mono_domain_get ();
2407 MonoClass *klass = mono_class_from_mono_type (type->type);
2408 return mono_assembly_get_object (domain, klass->image->assembly);
2411 ICALL_EXPORT MonoReflectionType*
2412 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2415 MonoReflectionType *ret;
2416 MonoDomain *domain = mono_domain_get ();
2419 if (type->type->byref)
2421 if (type->type->type == MONO_TYPE_VAR) {
2422 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2423 klass = param ? param->owner.klass : NULL;
2424 } else if (type->type->type == MONO_TYPE_MVAR) {
2425 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2426 klass = param ? param->owner.method->klass : NULL;
2428 klass = mono_class_from_mono_type (type->type)->nested_in;
2434 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2435 mono_error_raise_exception (&error);
2440 ICALL_EXPORT MonoString*
2441 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2443 MonoDomain *domain = mono_domain_get ();
2444 MonoClass *klass = mono_class_from_mono_type (type->type);
2446 if (type->type->byref) {
2447 char *n = g_strdup_printf ("%s&", klass->name);
2448 MonoString *res = mono_string_new (domain, n);
2454 return mono_string_new (domain, klass->name);
2458 ICALL_EXPORT MonoString*
2459 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2461 MonoDomain *domain = mono_domain_get ();
2462 MonoClass *klass = mono_class_from_mono_type (type->type);
2464 while (klass->nested_in)
2465 klass = klass->nested_in;
2467 if (klass->name_space [0] == '\0')
2470 return mono_string_new (domain, klass->name_space);
2474 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2478 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2479 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2483 klass = mono_class_from_mono_type (type->type);
2489 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2492 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2496 ICALL_EXPORT MonoArray*
2497 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2500 MonoReflectionType *rt;
2502 MonoClass *klass, *pklass;
2503 MonoDomain *domain = mono_object_domain (type);
2506 klass = mono_class_from_mono_type (type->type);
2508 if (klass->generic_container) {
2509 MonoGenericContainer *container = klass->generic_container;
2510 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2511 for (i = 0; i < container->type_argc; ++i) {
2512 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2514 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2515 mono_error_raise_exception (&error);
2517 mono_array_setref (res, i, rt);
2519 } else if (klass->generic_class) {
2520 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2521 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2522 for (i = 0; i < inst->type_argc; ++i) {
2523 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2524 mono_error_raise_exception (&error);
2526 mono_array_setref (res, i, rt);
2534 ICALL_EXPORT gboolean
2535 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2539 if (!IS_MONOTYPE (type))
2542 if (type->type->byref)
2545 klass = mono_class_from_mono_type (type->type);
2546 return klass->generic_container != NULL;
2549 ICALL_EXPORT MonoReflectionType*
2550 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2553 MonoReflectionType *ret;
2556 if (type->type->byref)
2559 klass = mono_class_from_mono_type (type->type);
2561 if (klass->generic_container) {
2562 return type; /* check this one */
2564 if (klass->generic_class) {
2565 MonoClass *generic_class = klass->generic_class->container_class;
2568 tb = mono_class_get_ref_info (generic_class);
2570 if (generic_class->wastypebuilder && tb)
2571 return (MonoReflectionType *)tb;
2573 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2574 mono_error_raise_exception (&error);
2582 ICALL_EXPORT MonoReflectionType*
2583 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2586 MonoReflectionType *ret;
2588 MonoType *geninst, **types;
2591 g_assert (IS_MONOTYPE (type));
2592 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2594 count = mono_array_length (type_array);
2595 types = g_new0 (MonoType *, count);
2597 for (i = 0; i < count; i++) {
2598 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2599 types [i] = t->type;
2602 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2607 klass = mono_class_from_mono_type (geninst);
2609 /*we might inflate to the GTD*/
2610 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2611 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2615 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2616 mono_error_raise_exception (&error);
2621 ICALL_EXPORT gboolean
2622 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2626 if (!IS_MONOTYPE (type))
2629 if (type->type->byref)
2632 klass = mono_class_from_mono_type (type->type);
2633 return klass->generic_class != NULL || klass->generic_container != NULL;
2637 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2639 if (!IS_MONOTYPE (type))
2642 if (is_generic_parameter (type->type))
2643 return mono_type_get_generic_param_num (type->type);
2647 ICALL_EXPORT GenericParameterAttributes
2648 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2650 g_assert (IS_MONOTYPE (type));
2651 g_assert (is_generic_parameter (type->type));
2652 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2655 ICALL_EXPORT MonoArray *
2656 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2659 MonoReflectionType *rt;
2660 MonoGenericParamInfo *param_info;
2666 g_assert (IS_MONOTYPE (type));
2668 domain = mono_object_domain (type);
2669 param_info = mono_generic_param_info (type->type->data.generic_param);
2670 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2673 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2674 for (i = 0; i < count; i++) {
2675 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2676 mono_error_raise_exception (&error);
2678 mono_array_setref (res, i, rt);
2685 ICALL_EXPORT MonoBoolean
2686 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2688 return is_generic_parameter (type->type);
2691 ICALL_EXPORT MonoBoolean
2692 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2694 return is_generic_parameter (tb->type.type);
2698 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2699 MonoReflectionType *t)
2701 enumtype->type = t->type;
2704 ICALL_EXPORT MonoReflectionMethod*
2705 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2706 MonoReflectionMethod* generic)
2713 MonoReflectionMethod *ret = NULL;
2715 domain = ((MonoObject *)type)->vtable->domain;
2717 klass = mono_class_from_mono_type (type->type);
2718 mono_class_init_or_throw (klass);
2721 while ((method = mono_class_get_methods (klass, &iter))) {
2722 if (method->token == generic->method->token) {
2723 ret = mono_method_get_object_checked (domain, method, klass, &error);
2724 mono_error_raise_exception (&error);
2731 ICALL_EXPORT MonoReflectionMethod *
2732 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2735 MonoType *type = ref_type->type;
2737 MonoReflectionMethod *ret = NULL;
2739 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2740 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2743 if (type->type == MONO_TYPE_VAR)
2746 method = mono_type_get_generic_param_owner (type)->owner.method;
2749 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2750 if (!mono_error_ok (&error))
2751 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2755 ICALL_EXPORT MonoBoolean
2756 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2758 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2762 ICALL_EXPORT MonoBoolean
2763 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2765 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2770 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2772 MonoDomain *domain = mono_domain_get ();
2773 MonoImage *image = method->method->klass->image;
2774 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2775 MonoTableInfo *tables = image->tables;
2776 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2777 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2778 guint32 im_cols [MONO_IMPLMAP_SIZE];
2779 guint32 scope_token;
2780 const char *import = NULL;
2781 const char *scope = NULL;
2783 if (image_is_dynamic (image)) {
2784 MonoReflectionMethodAux *method_aux =
2785 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2787 import = method_aux->dllentry;
2788 scope = method_aux->dll;
2791 if (!import || !scope) {
2792 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2797 if (piinfo->implmap_idx) {
2798 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2800 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2801 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2802 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2803 scope = mono_metadata_string_heap (image, scope_token);
2807 *flags = piinfo->piflags;
2808 *entry_point = mono_string_new (domain, import);
2809 *dll_name = mono_string_new (domain, scope);
2812 ICALL_EXPORT MonoReflectionMethod *
2813 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2815 MonoMethodInflated *imethod;
2817 MonoReflectionMethod *ret = NULL;
2820 if (method->method->is_generic)
2823 if (!method->method->is_inflated)
2826 imethod = (MonoMethodInflated *) method->method;
2828 result = imethod->declaring;
2829 /* Not a generic method. */
2830 if (!result->is_generic)
2833 if (image_is_dynamic (method->method->klass->image)) {
2834 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2835 MonoReflectionMethod *res;
2838 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2839 * the dynamic case as well ?
2841 mono_image_lock ((MonoImage*)image);
2842 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2843 mono_image_unlock ((MonoImage*)image);
2849 if (imethod->context.class_inst) {
2850 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2851 /*Generic methods gets the context of the GTD.*/
2852 if (mono_class_get_context (klass)) {
2853 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2854 if (!mono_error_ok (&error))
2859 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2861 if (!mono_error_ok (&error))
2862 mono_error_set_pending_exception (&error);
2866 ICALL_EXPORT gboolean
2867 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2869 return mono_method_signature (method->method)->generic_param_count != 0;
2872 ICALL_EXPORT gboolean
2873 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2875 return method->method->is_generic;
2878 ICALL_EXPORT MonoArray*
2879 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2882 MonoReflectionType *rt;
2887 domain = mono_object_domain (method);
2889 if (method->method->is_inflated) {
2890 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2893 count = inst->type_argc;
2894 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2896 for (i = 0; i < count; i++) {
2897 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2898 mono_error_raise_exception (&error);
2900 mono_array_setref (res, i, rt);
2907 count = mono_method_signature (method->method)->generic_param_count;
2908 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2910 for (i = 0; i < count; i++) {
2911 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2912 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2913 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
2915 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2916 mono_error_raise_exception (&error);
2918 mono_array_setref (res, i, rt);
2924 ICALL_EXPORT MonoObject *
2925 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
2929 * Invoke from reflection is supposed to always be a virtual call (the API
2930 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2931 * greater flexibility.
2933 MonoMethod *m = method->method;
2934 MonoMethodSignature *sig = mono_method_signature (m);
2937 void *obj = this_arg;
2941 if (mono_security_core_clr_enabled ())
2942 mono_security_core_clr_ensure_reflection_access_method (m);
2944 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2945 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2946 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2951 if (!mono_object_isinst (this_arg, m->klass)) {
2952 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
2953 char *target_name = mono_type_get_full_name (m->klass);
2954 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2955 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2957 g_free (target_name);
2961 m = mono_object_get_virtual_method (this_arg, m);
2962 /* must pass the pointer to the value for valuetype methods */
2963 if (m->klass->valuetype)
2964 obj = mono_object_unbox (this_arg);
2965 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2966 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2971 if (sig->ret->byref) {
2972 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"));
2976 pcount = params? mono_array_length (params): 0;
2977 if (pcount != sig->param_count) {
2978 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2982 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
2983 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."));
2987 image = m->klass->image;
2988 if (image->assembly->ref_only) {
2989 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."));
2993 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
2994 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2998 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3002 intptr_t *lower_bounds;
3003 pcount = mono_array_length (params);
3004 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3005 /* Note: the synthetized array .ctors have int32 as argument type */
3006 for (i = 0; i < pcount; ++i)
3007 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3009 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3010 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3011 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3012 if (!mono_error_ok (&error)) {
3013 mono_error_set_pending_exception (&error);
3017 for (i = 0; i < mono_array_length (arr); ++i) {
3018 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3019 if (!mono_error_ok (&error)) {
3020 mono_error_set_pending_exception (&error);
3023 mono_array_setref_fast (arr, i, subarray);
3025 return (MonoObject*)arr;
3028 if (m->klass->rank == pcount) {
3029 /* Only lengths provided. */
3030 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3031 if (!mono_error_ok (&error)) {
3032 mono_error_set_pending_exception (&error);
3036 return (MonoObject*)arr;
3038 g_assert (pcount == (m->klass->rank * 2));
3039 /* The arguments are lower-bound-length pairs */
3040 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3042 for (i = 0; i < pcount / 2; ++i) {
3043 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3044 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3047 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3048 if (!mono_error_ok (&error)) {
3049 mono_error_set_pending_exception (&error);
3053 return (MonoObject*)arr;
3056 return mono_runtime_invoke_array (m, obj, params, NULL);
3059 #ifndef DISABLE_REMOTING
3060 ICALL_EXPORT MonoObject *
3061 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3063 MonoDomain *domain = mono_object_domain (method);
3064 MonoMethod *m = method->method;
3065 MonoMethodSignature *sig = mono_method_signature (m);
3066 MonoArray *out_args;
3068 int i, j, outarg_count = 0;
3070 if (m->klass == mono_defaults.object_class) {
3071 if (!strcmp (m->name, "FieldGetter")) {
3072 MonoClass *k = this_arg->vtable->klass;
3076 /* If this is a proxy, then it must be a CBO */
3077 if (k == mono_defaults.transparent_proxy_class) {
3078 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3079 this_arg = tp->rp->unwrapped_server;
3080 g_assert (this_arg);
3081 k = this_arg->vtable->klass;
3084 name = mono_array_get (params, MonoString *, 1);
3085 str = mono_string_to_utf8 (name);
3088 MonoClassField* field = mono_class_get_field_from_name (k, str);
3090 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3091 if (field_klass->valuetype)
3092 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
3094 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3096 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3097 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3098 mono_array_setref (out_args, 0, result);
3106 g_assert_not_reached ();
3108 } else if (!strcmp (m->name, "FieldSetter")) {
3109 MonoClass *k = this_arg->vtable->klass;
3115 /* If this is a proxy, then it must be a CBO */
3116 if (k == mono_defaults.transparent_proxy_class) {
3117 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3118 this_arg = tp->rp->unwrapped_server;
3119 g_assert (this_arg);
3120 k = this_arg->vtable->klass;
3123 name = mono_array_get (params, MonoString *, 1);
3124 str = mono_string_to_utf8 (name);
3127 MonoClassField* field = mono_class_get_field_from_name (k, str);
3129 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3130 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3132 if (field_klass->valuetype) {
3133 size = mono_type_size (field->type, &align);
3134 g_assert (size == mono_class_value_size (field_klass, NULL));
3135 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3137 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3140 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3141 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3151 g_assert_not_reached ();
3156 for (i = 0; i < mono_array_length (params); i++) {
3157 if (sig->params [i]->byref)
3161 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3163 /* handle constructors only for objects already allocated */
3164 if (!strcmp (method->method->name, ".ctor"))
3165 g_assert (this_arg);
3167 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3168 g_assert (!method->method->klass->valuetype);
3169 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3171 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3172 if (sig->params [i]->byref) {
3174 arg = mono_array_get (params, gpointer, i);
3175 mono_array_setref (out_args, j, arg);
3180 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3187 read_enum_value (const char *mem, int type)
3190 case MONO_TYPE_BOOLEAN:
3192 return *(guint8*)mem;
3194 return *(gint8*)mem;
3195 case MONO_TYPE_CHAR:
3197 return read16 (mem);
3199 return (gint16) read16 (mem);
3201 return read32 (mem);
3203 return (gint32) read32 (mem);
3206 return read64 (mem);
3208 g_assert_not_reached ();
3214 write_enum_value (char *mem, int type, guint64 value)
3218 case MONO_TYPE_I1: {
3219 guint8 *p = (guint8*)mem;
3224 case MONO_TYPE_I2: {
3225 guint16 *p = (guint16 *)mem;
3230 case MONO_TYPE_I4: {
3231 guint32 *p = (guint32 *)mem;
3236 case MONO_TYPE_I8: {
3237 guint64 *p = (guint64 *)mem;
3242 g_assert_not_reached ();
3247 ICALL_EXPORT MonoObject *
3248 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3256 domain = mono_object_domain (enumType);
3257 enumc = mono_class_from_mono_type (enumType->type);
3259 mono_class_init_or_throw (enumc);
3261 etype = mono_class_enum_basetype (enumc);
3263 res = mono_object_new_checked (domain, enumc, &error);
3264 mono_error_raise_exception (&error);
3265 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3270 ICALL_EXPORT MonoBoolean
3271 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3273 int size = mono_class_value_size (a->vtable->klass, NULL);
3274 guint64 a_val = 0, b_val = 0;
3276 memcpy (&a_val, mono_object_unbox (a), size);
3277 memcpy (&b_val, mono_object_unbox (b), size);
3279 return (a_val & b_val) == b_val;
3282 ICALL_EXPORT MonoObject *
3283 ves_icall_System_Enum_get_value (MonoObject *eobj)
3295 g_assert (eobj->vtable->klass->enumtype);
3297 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3298 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3299 mono_error_raise_exception (&error);
3300 dst = (char *)res + sizeof (MonoObject);
3301 src = (char *)eobj + sizeof (MonoObject);
3302 size = mono_class_value_size (enumc, NULL);
3304 memcpy (dst, src, size);
3309 ICALL_EXPORT MonoReflectionType *
3310 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3313 MonoReflectionType *ret;
3317 klass = mono_class_from_mono_type (type->type);
3318 mono_class_init_or_throw (klass);
3320 etype = mono_class_enum_basetype (klass);
3322 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3326 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3327 mono_error_raise_exception (&error);
3333 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3335 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3336 gpointer odata = (char *)other + sizeof (MonoObject);
3337 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3338 g_assert (basetype);
3343 if (eobj->vtable->klass != other->vtable->klass)
3346 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3347 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3348 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3351 return me > other ? 1 : -1; \
3354 switch (basetype->type) {
3356 COMPARE_ENUM_VALUES (guint8);
3358 COMPARE_ENUM_VALUES (gint8);
3359 case MONO_TYPE_CHAR:
3361 COMPARE_ENUM_VALUES (guint16);
3363 COMPARE_ENUM_VALUES (gint16);
3365 COMPARE_ENUM_VALUES (guint32);
3367 COMPARE_ENUM_VALUES (gint32);
3369 COMPARE_ENUM_VALUES (guint64);
3371 COMPARE_ENUM_VALUES (gint64);
3375 #undef COMPARE_ENUM_VALUES
3376 /* indicates that the enum was of an unsupported unerlying type */
3381 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3383 gpointer data = (char *)eobj + sizeof (MonoObject);
3384 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3385 g_assert (basetype);
3387 switch (basetype->type) {
3388 case MONO_TYPE_I1: {
3389 gint8 value = *((gint8*)data);
3390 return ((int)value ^ (int)value << 8);
3393 return *((guint8*)data);
3394 case MONO_TYPE_CHAR:
3396 return *((guint16*)data);
3398 case MONO_TYPE_I2: {
3399 gint16 value = *((gint16*)data);
3400 return ((int)(guint16)value | (((int)value) << 16));
3403 return *((guint32*)data);
3405 return *((gint32*)data);
3407 case MONO_TYPE_I8: {
3408 gint64 value = *((gint64*)data);
3409 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3412 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3417 ICALL_EXPORT MonoBoolean
3418 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3420 MonoDomain *domain = mono_object_domain (type);
3421 MonoClass *enumc = mono_class_from_mono_type (type->type);
3422 guint j = 0, nvalues;
3424 MonoClassField *field;
3426 guint64 field_value, previous_value = 0;
3427 gboolean sorted = TRUE;
3429 mono_class_init_or_throw (enumc);
3431 if (!enumc->enumtype) {
3432 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3436 base_type = mono_class_enum_basetype (enumc)->type;
3438 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3439 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3440 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3443 while ((field = mono_class_get_fields (enumc, &iter))) {
3445 MonoTypeEnum def_type;
3447 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3449 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3451 if (mono_field_is_deleted (field))
3453 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3455 p = mono_class_get_field_default_value (field, &def_type);
3456 /* len = */ mono_metadata_decode_blob_size (p, &p);
3458 field_value = read_enum_value (p, base_type);
3459 mono_array_set (*values, guint64, j, field_value);
3461 if (previous_value > field_value)
3464 previous_value = field_value;
3472 BFLAGS_IgnoreCase = 1,
3473 BFLAGS_DeclaredOnly = 2,
3474 BFLAGS_Instance = 4,
3476 BFLAGS_Public = 0x10,
3477 BFLAGS_NonPublic = 0x20,
3478 BFLAGS_FlattenHierarchy = 0x40,
3479 BFLAGS_InvokeMethod = 0x100,
3480 BFLAGS_CreateInstance = 0x200,
3481 BFLAGS_GetField = 0x400,
3482 BFLAGS_SetField = 0x800,
3483 BFLAGS_GetProperty = 0x1000,
3484 BFLAGS_SetProperty = 0x2000,
3485 BFLAGS_ExactBinding = 0x10000,
3486 BFLAGS_SuppressChangeType = 0x20000,
3487 BFLAGS_OptionalParamBinding = 0x40000
3490 ICALL_EXPORT MonoArray*
3491 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3495 MonoClass *startklass, *klass, *refklass;
3500 char *utf8_name = NULL;
3501 int (*compare_func) (const char *s1, const char *s2) = NULL;
3502 MonoClassField *field;
3503 MonoPtrArray tmp_array;
3505 domain = ((MonoObject *)type)->vtable->domain;
3506 if (type->type->byref)
3507 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3509 klass = startklass = mono_class_from_mono_type (type->type);
3510 refklass = mono_class_from_mono_type (reftype->type);
3512 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3515 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3516 mono_ptr_array_destroy (tmp_array);
3517 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3522 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3523 guint32 flags = mono_field_get_flags (field);
3525 if (mono_field_is_deleted_with_flags (field, flags))
3527 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3528 if (bflags & BFLAGS_Public)
3530 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3531 if (bflags & BFLAGS_NonPublic) {
3538 if (flags & FIELD_ATTRIBUTE_STATIC) {
3539 if (bflags & BFLAGS_Static)
3540 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3543 if (bflags & BFLAGS_Instance)
3551 if (utf8_name == NULL) {
3552 utf8_name = mono_string_to_utf8 (name);
3553 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3556 if (compare_func (mono_field_get_name (field), utf8_name))
3560 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3561 if (!mono_error_ok (&error))
3563 mono_ptr_array_append (tmp_array, member);
3565 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3568 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3570 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3571 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3573 mono_ptr_array_destroy (tmp_array);
3575 if (utf8_name != NULL)
3580 mono_ptr_array_destroy (tmp_array);
3581 mono_error_raise_exception (&error);
3582 g_assert_not_reached ();
3586 method_nonpublic (MonoMethod* method, gboolean start_klass)
3588 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3589 case METHOD_ATTRIBUTE_ASSEM:
3590 return (start_klass || mono_defaults.generic_ilist_class);
3591 case METHOD_ATTRIBUTE_PRIVATE:
3593 case METHOD_ATTRIBUTE_PUBLIC:
3601 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3604 MonoClass *startklass;
3608 /*FIXME, use MonoBitSet*/
3609 guint32 method_slots_default [8];
3610 guint32 *method_slots = NULL;
3611 int (*compare_func) (const char *s1, const char *s2) = NULL;
3613 array = g_ptr_array_new ();
3618 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3620 /* An optimization for calls made from Delegate:CreateDelegate () */
3621 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3622 method = mono_get_delegate_invoke (klass);
3623 if (mono_loader_get_last_error ())
3626 g_ptr_array_add (array, method);
3630 mono_class_setup_methods (klass);
3631 mono_class_setup_vtable (klass);
3632 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3635 if (is_generic_parameter (&klass->byval_arg))
3636 nslots = mono_class_get_vtable_size (klass->parent);
3638 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3639 if (nslots >= sizeof (method_slots_default) * 8) {
3640 method_slots = g_new0 (guint32, nslots / 32 + 1);
3642 method_slots = method_slots_default;
3643 memset (method_slots, 0, sizeof (method_slots_default));
3646 mono_class_setup_methods (klass);
3647 mono_class_setup_vtable (klass);
3648 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3652 while ((method = mono_class_get_methods (klass, &iter))) {
3654 if (method->slot != -1) {
3655 g_assert (method->slot < nslots);
3656 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3658 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3659 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3662 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3664 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3665 if (bflags & BFLAGS_Public)
3667 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3673 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3674 if (bflags & BFLAGS_Static)
3675 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3678 if (bflags & BFLAGS_Instance)
3686 if (compare_func (name, method->name))
3691 g_ptr_array_add (array, method);
3693 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3695 if (method_slots != method_slots_default)
3696 g_free (method_slots);
3701 if (method_slots != method_slots_default)
3702 g_free (method_slots);
3703 g_ptr_array_free (array, TRUE);
3705 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3706 *ex = mono_class_get_exception_for_failure (klass);
3708 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3709 mono_loader_clear_error ();
3714 ICALL_EXPORT MonoArray*
3715 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3717 static MonoClass *MethodInfo_array;
3721 MonoVTable *array_vtable;
3722 MonoException *ex = NULL;
3723 const char *mname = NULL;
3724 GPtrArray *method_array;
3725 MonoClass *klass, *refklass;
3728 mono_error_init (&error);
3730 if (!MethodInfo_array) {
3731 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3732 mono_memory_barrier ();
3733 MethodInfo_array = klass;
3736 klass = mono_class_from_mono_type (type->type);
3737 refklass = mono_class_from_mono_type (reftype->type);
3738 domain = ((MonoObject *)type)->vtable->domain;
3739 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3740 if (type->type->byref) {
3741 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3742 mono_error_set_pending_exception (&error);
3748 mname = mono_string_to_utf8 (name);
3750 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3751 g_free ((char*)mname);
3753 mono_set_pending_exception (ex);
3757 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3758 if (!mono_error_ok (&error)) {
3759 mono_error_set_pending_exception (&error);
3763 for (i = 0; i < method_array->len; ++i) {
3764 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3765 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3766 if (!mono_error_ok (&error))
3768 mono_array_setref (res, i, rm);
3772 g_ptr_array_free (method_array, TRUE);
3773 if (!mono_error_ok (&error))
3774 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3778 ICALL_EXPORT MonoArray*
3779 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3782 static MonoClass *System_Reflection_ConstructorInfo;
3783 MonoClass *startklass, *klass, *refklass;
3788 gpointer iter = NULL;
3789 MonoPtrArray tmp_array;
3792 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3794 domain = ((MonoObject *)type)->vtable->domain;
3795 if (type->type->byref)
3796 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3797 klass = startklass = mono_class_from_mono_type (type->type);
3798 refklass = mono_class_from_mono_type (reftype->type);
3800 if (!System_Reflection_ConstructorInfo)
3801 System_Reflection_ConstructorInfo = mono_class_from_name (
3802 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3804 mono_class_setup_methods (klass);
3805 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3806 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3811 while ((method = mono_class_get_methods (klass, &iter))) {
3813 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3815 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3816 if (bflags & BFLAGS_Public)
3819 if (bflags & BFLAGS_NonPublic)
3825 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3826 if (bflags & BFLAGS_Static)
3827 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3830 if (bflags & BFLAGS_Instance)
3836 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3837 if (!mono_error_ok (&error)) {
3838 mono_error_set_pending_exception (&error);
3842 mono_ptr_array_append (tmp_array, member);
3845 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3847 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3848 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3850 mono_ptr_array_destroy (tmp_array);
3856 property_hash (gconstpointer data)
3858 MonoProperty *prop = (MonoProperty*)data;
3860 return g_str_hash (prop->name);
3864 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3866 if (method1->is_inflated)
3867 method1 = ((MonoMethodInflated*) method1)->declaring;
3868 if (method2->is_inflated)
3869 method2 = ((MonoMethodInflated*) method2)->declaring;
3871 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3875 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3877 // Properties are hide-by-name-and-signature
3878 if (!g_str_equal (prop1->name, prop2->name))
3881 /* If we see a property in a generic method, we want to
3882 compare the generic signatures, not the inflated signatures
3883 because we might conflate two properties that were
3887 public T this[T t] { getter { return t; } } // method 1
3888 public U this[U u] { getter { return u; } } // method 2
3891 If we see int Foo<int,int>::Item[int] we need to know if
3892 the indexer came from method 1 or from method 2, and we
3893 shouldn't conflate them. (Bugzilla 36283)
3895 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
3898 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
3905 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3910 return method_nonpublic (accessor, start_klass);
3913 ICALL_EXPORT MonoArray*
3914 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3918 static MonoClass *System_Reflection_PropertyInfo;
3919 MonoClass *startklass, *klass;
3925 gchar *propname = NULL;
3926 int (*compare_func) (const char *s1, const char *s2) = NULL;
3928 GHashTable *properties = NULL;
3929 MonoPtrArray tmp_array;
3931 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
3933 if (!System_Reflection_PropertyInfo)
3934 System_Reflection_PropertyInfo = mono_class_from_name (
3935 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3937 domain = ((MonoObject *)type)->vtable->domain;
3938 if (type->type->byref)
3939 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3940 klass = startklass = mono_class_from_mono_type (type->type);
3943 propname = mono_string_to_utf8 (name);
3944 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3947 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3949 mono_class_setup_methods (klass);
3950 mono_class_setup_vtable (klass);
3951 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3955 while ((prop = mono_class_get_properties (klass, &iter))) {
3961 flags = method->flags;
3964 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3965 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3966 if (bflags & BFLAGS_Public)
3968 } else if (bflags & BFLAGS_NonPublic) {
3969 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3970 property_accessor_nonpublic(prop->set, startklass == klass)) {
3977 if (flags & METHOD_ATTRIBUTE_STATIC) {
3978 if (bflags & BFLAGS_Static)
3979 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3982 if (bflags & BFLAGS_Instance)
3991 if (compare_func (propname, prop->name))
3995 if (g_hash_table_lookup (properties, prop))
3998 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
4000 g_hash_table_insert (properties, prop, prop);
4002 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4005 g_hash_table_destroy (properties);
4008 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
4009 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4010 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4012 mono_ptr_array_destroy (tmp_array);
4018 g_hash_table_destroy (properties);
4021 mono_ptr_array_destroy (tmp_array);
4023 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4024 ex = mono_class_get_exception_for_failure (klass);
4026 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4027 mono_loader_clear_error ();
4029 mono_set_pending_exception (ex);
4034 event_hash (gconstpointer data)
4036 MonoEvent *event = (MonoEvent*)data;
4038 return g_str_hash (event->name);
4042 event_equal (MonoEvent *event1, MonoEvent *event2)
4044 // Events are hide-by-name
4045 return g_str_equal (event1->name, event2->name);
4048 ICALL_EXPORT MonoArray*
4049 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4053 static MonoClass *System_Reflection_EventInfo;
4054 MonoClass *startklass, *klass;
4060 char *utf8_name = NULL;
4061 int (*compare_func) (const char *s1, const char *s2) = NULL;
4062 GHashTable *events = NULL;
4063 MonoPtrArray tmp_array;
4065 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4067 if (!System_Reflection_EventInfo)
4068 System_Reflection_EventInfo = mono_class_from_name (
4069 mono_defaults.corlib, "System.Reflection", "EventInfo");
4071 domain = mono_object_domain (type);
4072 if (type->type->byref)
4073 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
4074 klass = startklass = mono_class_from_mono_type (type->type);
4076 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4078 mono_class_setup_methods (klass);
4079 mono_class_setup_vtable (klass);
4080 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
4084 while ((event = mono_class_get_events (klass, &iter))) {
4086 method = event->add;
4088 method = event->remove;
4090 method = event->raise;
4092 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4093 if (bflags & BFLAGS_Public)
4095 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4096 if (bflags & BFLAGS_NonPublic)
4101 if (bflags & BFLAGS_NonPublic)
4107 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4108 if (bflags & BFLAGS_Static)
4109 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4112 if (bflags & BFLAGS_Instance)
4117 if (bflags & BFLAGS_Instance)
4123 if (utf8_name == NULL) {
4124 utf8_name = mono_string_to_utf8 (name);
4125 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4128 if (compare_func (event->name, utf8_name))
4132 if (g_hash_table_lookup (events, event))
4135 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
4137 g_hash_table_insert (events, event, event);
4139 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4142 g_hash_table_destroy (events);
4144 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
4146 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4147 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4149 mono_ptr_array_destroy (tmp_array);
4151 if (utf8_name != NULL)
4157 mono_ptr_array_destroy (tmp_array);
4158 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4159 ex = mono_class_get_exception_for_failure (klass);
4161 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4162 mono_loader_clear_error ();
4164 mono_set_pending_exception (ex);
4168 ICALL_EXPORT MonoArray*
4169 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4172 MonoReflectionType *rt;
4180 MonoPtrArray tmp_array;
4182 domain = ((MonoObject *)type)->vtable->domain;
4183 if (type->type->byref)
4184 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4185 klass = mono_class_from_mono_type (type->type);
4188 * If a nested type is generic, return its generic type definition.
4189 * Note that this means that the return value is essentially the set
4190 * of nested types of the generic type definition of @klass.
4192 * A note in MSDN claims that a generic type definition can have
4193 * nested types that aren't generic. In any case, the container of that
4194 * nested type would be the generic type definition.
4196 if (klass->generic_class)
4197 klass = klass->generic_class->container_class;
4199 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4201 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4203 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4204 if (bflags & BFLAGS_Public)
4207 if (bflags & BFLAGS_NonPublic)
4215 str = mono_string_to_utf8 (name);
4216 mono_identifier_unescape_type_name_chars (str);
4219 if (strcmp (nested->name, str))
4223 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4224 mono_error_raise_exception (&error);
4226 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4229 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4231 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4232 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4234 mono_ptr_array_destroy (tmp_array);
4242 ICALL_EXPORT MonoReflectionType*
4243 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4246 MonoReflectionType *ret;
4248 MonoType *type = NULL;
4249 MonoTypeNameParse info;
4250 gboolean type_resolve;
4252 /* On MS.NET, this does not fire a TypeResolve event */
4253 type_resolve = TRUE;
4254 str = mono_string_to_utf8 (name);
4255 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4256 if (!mono_reflection_parse_type (str, &info)) {
4258 mono_reflection_free_type_info (&info);
4260 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4263 /*g_print ("failed parse\n");*/
4267 if (info.assembly.name) {
4269 mono_reflection_free_type_info (&info);
4271 /* 1.0 and 2.0 throw different exceptions */
4272 if (mono_defaults.generic_ilist_class)
4273 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4275 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4281 if (module != NULL) {
4283 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4288 if (assembly_is_dynamic (assembly->assembly)) {
4289 /* Enumerate all modules */
4290 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4294 if (abuilder->modules) {
4295 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4296 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4297 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4303 if (!type && abuilder->loaded_modules) {
4304 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4305 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4306 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4313 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4315 mono_reflection_free_type_info (&info);
4317 MonoException *e = NULL;
4320 e = mono_get_exception_type_load (name, NULL);
4322 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4323 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4325 mono_loader_clear_error ();
4328 mono_set_pending_exception (e);
4330 } else if (mono_loader_get_last_error ()) {
4332 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4335 mono_loader_clear_error ();
4338 if (type->type == MONO_TYPE_CLASS) {
4339 MonoClass *klass = mono_type_get_class (type);
4341 /* need to report exceptions ? */
4342 if (throwOnError && klass->exception_type) {
4343 /* report SecurityException (or others) that occured when loading the assembly */
4344 MonoException *exc = mono_class_get_exception_for_failure (klass);
4345 mono_loader_clear_error ();
4346 mono_set_pending_exception (exc);
4351 /* g_print ("got it\n"); */
4352 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4353 mono_error_raise_exception (&error);
4359 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4362 gchar *shadow_ini_file;
4365 /* Check for shadow-copied assembly */
4366 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4367 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4369 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4370 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4376 g_free (shadow_ini_file);
4377 if (content != NULL) {
4380 *filename = content;
4387 ICALL_EXPORT MonoString *
4388 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4390 MonoDomain *domain = mono_object_domain (assembly);
4391 MonoAssembly *mass = assembly->assembly;
4392 MonoString *res = NULL;
4397 if (g_path_is_absolute (mass->image->name)) {
4398 absolute = g_strdup (mass->image->name);
4399 dirname = g_path_get_dirname (absolute);
4401 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4402 dirname = g_strdup (mass->basedir);
4405 replace_shadow_path (domain, dirname, &absolute);
4410 for (i = strlen (absolute) - 1; i >= 0; i--)
4411 if (absolute [i] == '\\')
4416 uri = g_filename_to_uri (absolute, NULL, NULL);
4418 const char *prepend = "file://";
4420 if (*absolute == '/' && *(absolute + 1) == '/') {
4423 prepend = "file:///";
4426 uri = g_strconcat (prepend, absolute, NULL);
4430 res = mono_string_new (domain, uri);
4437 ICALL_EXPORT MonoBoolean
4438 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4440 MonoAssembly *mass = assembly->assembly;
4442 return mass->in_gac;
4445 ICALL_EXPORT MonoReflectionAssembly*
4446 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4450 MonoImageOpenStatus status;
4452 name = mono_string_to_utf8 (mname);
4453 res = mono_assembly_load_with_partial_name (name, &status);
4459 return mono_assembly_get_object (mono_domain_get (), res);
4462 ICALL_EXPORT MonoString *
4463 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4465 MonoDomain *domain = mono_object_domain (assembly);
4468 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4473 ICALL_EXPORT MonoBoolean
4474 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4476 return assembly->assembly->ref_only;
4479 ICALL_EXPORT MonoString *
4480 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4482 MonoDomain *domain = mono_object_domain (assembly);
4484 return mono_string_new (domain, assembly->assembly->image->version);
4487 ICALL_EXPORT MonoReflectionMethod*
4488 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4491 MonoReflectionMethod *res = NULL;
4494 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4498 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4499 if (!mono_error_ok (&error))
4502 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4505 if (!mono_error_ok (&error))
4506 mono_error_set_pending_exception (&error);
4510 ICALL_EXPORT MonoReflectionModule*
4511 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4513 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4516 ICALL_EXPORT MonoArray*
4517 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4519 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4520 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4524 for (i = 0; i < table->rows; ++i) {
4525 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4526 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4532 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4534 static MonoClass *System_Version = NULL;
4535 static MonoMethod *create_version = NULL;
4540 if (!System_Version) {
4541 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4542 g_assert (System_Version);
4545 if (!create_version) {
4546 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4547 create_version = mono_method_desc_search_in_class (desc, System_Version);
4548 g_assert (create_version);
4549 mono_method_desc_free (desc);
4555 args [3] = &revision;
4556 result = mono_object_new_checked (domain, System_Version, &error);
4557 mono_error_raise_exception (&error); /* FIXME don't raise here */
4558 mono_runtime_invoke (create_version, result, args, NULL);
4563 ICALL_EXPORT MonoArray*
4564 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4566 static MonoClass *System_Reflection_AssemblyName;
4569 MonoDomain *domain = mono_object_domain (assembly);
4571 static MonoMethod *create_culture = NULL;
4572 MonoImage *image = assembly->assembly->image;
4575 if (!System_Reflection_AssemblyName)
4576 System_Reflection_AssemblyName = mono_class_from_name (
4577 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4579 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4582 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4584 if (count > 0 && !create_culture) {
4585 MonoMethodDesc *desc = mono_method_desc_new (
4586 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4587 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4588 g_assert (create_culture);
4589 mono_method_desc_free (desc);
4592 for (i = 0; i < count; i++) {
4593 MonoReflectionAssemblyName *aname;
4594 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4596 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4598 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4599 domain, System_Reflection_AssemblyName, &error);
4600 mono_error_raise_exception (&error);
4602 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4604 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4605 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4606 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4607 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4608 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4609 aname->versioncompat = 1; /* SameMachine (default) */
4610 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4611 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4613 if (create_culture) {
4615 MonoBoolean assembly_ref = 1;
4616 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4617 args [1] = &assembly_ref;
4618 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4621 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4622 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4623 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4625 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4626 /* public key token isn't copied - the class library will
4627 automatically generate it from the public key if required */
4628 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4629 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4631 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4632 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4635 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4638 /* note: this function doesn't return the codebase on purpose (i.e. it can
4639 be used under partial trust as path information isn't present). */
4641 mono_array_setref (result, i, aname);
4646 /* move this in some file in mono/util/ */
4648 g_concat_dir_and_file (const char *dir, const char *file)
4650 g_return_val_if_fail (dir != NULL, NULL);
4651 g_return_val_if_fail (file != NULL, NULL);
4654 * If the directory name doesn't have a / on the end, we need
4655 * to add one so we get a proper path to the file
4657 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4658 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4660 return g_strconcat (dir, file, NULL);
4664 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4666 char *n = mono_string_to_utf8 (name);
4667 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4669 guint32 cols [MONO_MANIFEST_SIZE];
4670 guint32 impl, file_idx;
4674 for (i = 0; i < table->rows; ++i) {
4675 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4676 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4677 if (strcmp (val, n) == 0)
4681 if (i == table->rows)
4684 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4687 * this code should only be called after obtaining the
4688 * ResourceInfo and handling the other cases.
4690 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4691 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4693 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4698 module = assembly->assembly->image;
4700 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4702 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4705 ICALL_EXPORT gboolean
4706 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4708 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4710 guint32 cols [MONO_MANIFEST_SIZE];
4711 guint32 file_cols [MONO_FILE_SIZE];
4715 n = mono_string_to_utf8 (name);
4716 for (i = 0; i < table->rows; ++i) {
4717 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4718 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4719 if (strcmp (val, n) == 0)
4723 if (i == table->rows)
4726 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4727 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4730 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4731 case MONO_IMPLEMENTATION_FILE:
4732 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4733 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4734 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4735 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4736 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4737 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4740 info->location = RESOURCE_LOCATION_EMBEDDED;
4743 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4744 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4745 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4746 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4747 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4748 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4750 mono_set_pending_exception (ex);
4753 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4755 /* Obtain info recursively */
4756 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4757 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4760 case MONO_IMPLEMENTATION_EXP_TYPE:
4761 g_assert_not_reached ();
4769 ICALL_EXPORT MonoObject*
4770 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4772 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4773 MonoArray *result = NULL;
4778 /* check hash if needed */
4780 n = mono_string_to_utf8 (name);
4781 for (i = 0; i < table->rows; ++i) {
4782 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4783 if (strcmp (val, n) == 0) {
4786 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4787 fn = mono_string_new (mono_object_domain (assembly), n);
4789 return (MonoObject*)fn;
4797 for (i = 0; i < table->rows; ++i) {
4798 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4802 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4805 for (i = 0; i < table->rows; ++i) {
4806 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4807 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4808 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4809 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4814 return (MonoObject*)result;
4817 ICALL_EXPORT MonoArray*
4818 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4820 MonoDomain *domain = mono_domain_get();
4823 int i, j, file_count = 0;
4824 MonoImage **modules;
4825 guint32 module_count, real_module_count;
4826 MonoTableInfo *table;
4827 guint32 cols [MONO_FILE_SIZE];
4828 MonoImage *image = assembly->assembly->image;
4830 g_assert (image != NULL);
4831 g_assert (!assembly_is_dynamic (assembly->assembly));
4833 table = &image->tables [MONO_TABLE_FILE];
4834 file_count = table->rows;
4836 modules = image->modules;
4837 module_count = image->module_count;
4839 real_module_count = 0;
4840 for (i = 0; i < module_count; ++i)
4842 real_module_count ++;
4844 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4845 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4847 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4849 for (i = 0; i < module_count; ++i)
4851 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4855 for (i = 0; i < file_count; ++i, ++j) {
4856 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4857 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4858 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4860 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4862 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4863 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
4866 mono_array_setref (res, j, mono_module_get_object (domain, m));
4873 ICALL_EXPORT MonoReflectionMethod*
4874 ves_icall_GetCurrentMethod (void)
4876 MonoReflectionMethod *res = NULL;
4879 MonoMethod *m = mono_method_get_last_managed ();
4882 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
4886 while (m->is_inflated)
4887 m = ((MonoMethodInflated*)m)->declaring;
4889 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
4890 mono_error_raise_exception (&error);
4896 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4899 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4902 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4903 //method is inflated, we should inflate it on the other class
4904 MonoGenericContext ctx;
4905 ctx.method_inst = inflated->context.method_inst;
4906 ctx.class_inst = inflated->context.class_inst;
4907 if (klass->generic_class)
4908 ctx.class_inst = klass->generic_class->context.class_inst;
4909 else if (klass->generic_container)
4910 ctx.class_inst = klass->generic_container->context.class_inst;
4911 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
4912 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4916 mono_class_setup_methods (method->klass);
4917 if (method->klass->exception_type)
4919 for (i = 0; i < method->klass->method.count; ++i) {
4920 if (method->klass->methods [i] == method) {
4925 mono_class_setup_methods (klass);
4926 if (klass->exception_type)
4928 g_assert (offset >= 0 && offset < klass->method.count);
4929 return klass->methods [offset];
4932 ICALL_EXPORT MonoReflectionMethod*
4933 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4935 MonoReflectionMethod *res = NULL;
4939 klass = mono_class_from_mono_type (type);
4940 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4942 if (method->klass != klass) {
4943 method = mono_method_get_equivalent_method (method, klass);
4948 klass = method->klass;
4949 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
4950 mono_error_raise_exception (&error);
4954 ICALL_EXPORT MonoReflectionMethodBody*
4955 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4957 return mono_method_body_get_object (mono_domain_get (), method);
4960 ICALL_EXPORT MonoReflectionAssembly*
4961 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4963 MonoMethod *dest = NULL;
4965 mono_stack_walk_no_il (get_executing, &dest);
4967 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4971 ICALL_EXPORT MonoReflectionAssembly*
4972 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4974 MonoDomain* domain = mono_domain_get ();
4976 if (!domain->entry_assembly)
4979 return mono_assembly_get_object (domain, domain->entry_assembly);
4982 ICALL_EXPORT MonoReflectionAssembly*
4983 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4989 mono_stack_walk_no_il (get_executing, &dest);
4991 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
4995 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
4998 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5001 ICALL_EXPORT MonoString *
5002 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5003 gboolean assembly_qualified)
5005 MonoDomain *domain = mono_object_domain (object);
5006 MonoTypeNameFormat format;
5011 format = assembly_qualified ?
5012 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5013 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5015 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5017 name = mono_type_get_name_full (object->type, format);
5021 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5026 res = mono_string_new (domain, name);
5033 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5035 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5036 mono_class_init_or_throw (klass);
5037 return mono_security_core_clr_class_level (klass);
5041 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5043 MonoClassField *field = rfield->field;
5044 return mono_security_core_clr_field_level (field, TRUE);
5048 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5050 MonoMethod *method = rfield->method;
5051 return mono_security_core_clr_method_level (method, TRUE);
5055 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
5057 static MonoMethod *create_culture = NULL;
5060 const char *pkey_ptr;
5062 MonoBoolean assembly_ref = 0;
5064 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5065 aname->major = name->major;
5066 aname->minor = name->minor;
5067 aname->build = name->build;
5068 aname->flags = name->flags;
5069 aname->revision = name->revision;
5070 aname->hashalg = name->hash_alg;
5071 aname->versioncompat = 1; /* SameMachine (default) */
5072 aname->processor_architecture = name->arch;
5074 if (by_default_version)
5075 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
5078 if (absolute != NULL && *absolute != '\0') {
5079 const gchar *prepend = "file://";
5082 codebase = g_strdup (absolute);
5087 for (i = strlen (codebase) - 1; i >= 0; i--)
5088 if (codebase [i] == '\\')
5091 if (*codebase == '/' && *(codebase + 1) == '/') {
5094 prepend = "file:///";
5098 result = g_strconcat (prepend, codebase, NULL);
5104 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5108 if (!create_culture) {
5109 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5110 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5111 g_assert (create_culture);
5112 mono_method_desc_free (desc);
5115 if (name->culture) {
5116 args [0] = mono_string_new (domain, name->culture);
5117 args [1] = &assembly_ref;
5118 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5121 if (name->public_key) {
5122 pkey_ptr = (char*)name->public_key;
5123 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5125 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5126 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5127 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5128 } else if (default_publickey) {
5129 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5130 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5133 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5134 if (name->public_key_token [0]) {
5138 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5139 p = mono_array_addr (aname->keyToken, char, 0);
5141 for (i = 0, j = 0; i < 8; i++) {
5142 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5143 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5146 } else if (default_token) {
5147 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5151 ICALL_EXPORT MonoString *
5152 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5154 MonoDomain *domain = mono_object_domain (assembly);
5155 MonoAssembly *mass = assembly->assembly;
5159 name = mono_stringify_assembly_name (&mass->aname);
5160 res = mono_string_new (domain, name);
5167 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5170 MonoAssembly *mass = assembly->assembly;
5172 if (g_path_is_absolute (mass->image->name)) {
5173 fill_reflection_assembly_name (mono_object_domain (assembly),
5174 aname, &mass->aname, mass->image->name, TRUE,
5178 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5180 fill_reflection_assembly_name (mono_object_domain (assembly),
5181 aname, &mass->aname, absolute, TRUE, TRUE,
5188 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5191 MonoImageOpenStatus status = MONO_IMAGE_OK;
5194 MonoAssemblyName name;
5197 filename = mono_string_to_utf8 (fname);
5199 dirname = g_path_get_dirname (filename);
5200 replace_shadow_path (mono_domain_get (), dirname, &filename);
5203 image = mono_image_open (filename, &status);
5209 if (status == MONO_IMAGE_IMAGE_INVALID)
5210 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5212 exc = mono_get_exception_file_not_found2 (NULL, fname);
5213 mono_set_pending_exception (exc);
5217 res = mono_assembly_fill_assembly_name (image, &name);
5219 mono_image_close (image);
5221 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5225 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5229 mono_image_close (image);
5232 ICALL_EXPORT MonoBoolean
5233 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5234 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5236 MonoBoolean result = FALSE;
5237 MonoDeclSecurityEntry entry;
5239 /* SecurityAction.RequestMinimum */
5240 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5241 *minimum = entry.blob;
5242 *minLength = entry.size;
5245 /* SecurityAction.RequestOptional */
5246 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5247 *optional = entry.blob;
5248 *optLength = entry.size;
5251 /* SecurityAction.RequestRefuse */
5252 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5253 *refused = entry.blob;
5254 *refLength = entry.size;
5262 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5264 guint32 attrs, visibility;
5266 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5267 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5268 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5271 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5277 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5280 MonoReflectionType *rt;
5283 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5286 /* we start the count from 1 because we skip the special type <Module> */
5289 for (i = 1; i < tdef->rows; ++i) {
5290 if (mono_module_type_is_visible (tdef, image, i + 1))
5294 count = tdef->rows - 1;
5296 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5297 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5299 for (i = 1; i < tdef->rows; ++i) {
5300 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5301 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, &error);
5302 mono_loader_assert_no_error (); /* Plug any leaks */
5303 g_assert (mono_error_ok (&error));
5306 rt = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5307 mono_error_raise_exception (&error); /* FIXME don't raise here */
5309 mono_array_setref (res, count, rt);
5311 MonoException *ex = mono_error_convert_to_exception (&error);
5312 mono_array_setref (*exceptions, count, ex);
5321 ICALL_EXPORT MonoArray*
5322 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5324 MonoArray *res = NULL;
5325 MonoArray *exceptions = NULL;
5326 MonoImage *image = NULL;
5327 MonoTableInfo *table = NULL;
5330 int i, len, ex_count;
5332 domain = mono_object_domain (assembly);
5334 g_assert (!assembly_is_dynamic (assembly->assembly));
5335 image = assembly->assembly->image;
5336 table = &image->tables [MONO_TABLE_FILE];
5337 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5339 /* Append data from all modules in the assembly */
5340 for (i = 0; i < table->rows; ++i) {
5341 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5342 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5345 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5346 /* Append the new types to the end of the array */
5347 if (mono_array_length (res2) > 0) {
5349 MonoArray *res3, *ex3;
5351 len1 = mono_array_length (res);
5352 len2 = mono_array_length (res2);
5354 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5355 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5356 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5359 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5360 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5361 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5368 /* the ReflectionTypeLoadException must have all the types (Types property),
5369 * NULL replacing types which throws an exception. The LoaderException must
5370 * contain all exceptions for NULL items.
5373 len = mono_array_length (res);
5376 for (i = 0; i < len; i++) {
5377 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5381 klass = mono_type_get_class (t->type);
5382 if ((klass != NULL) && klass->exception_type) {
5383 /* keep the class in the list */
5384 list = g_list_append (list, klass);
5385 /* and replace Type with NULL */
5386 mono_array_setref (res, i, NULL);
5393 if (list || ex_count) {
5395 MonoException *exc = NULL;
5396 MonoArray *exl = NULL;
5397 int j, length = g_list_length (list) + ex_count;
5399 mono_loader_clear_error ();
5401 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5402 /* Types for which mono_class_get_checked () succeeded */
5403 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5404 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5405 mono_array_setref (exl, i, exc);
5407 /* Types for which it don't */
5408 for (j = 0; j < mono_array_length (exceptions); ++j) {
5409 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5411 g_assert (i < length);
5412 mono_array_setref (exl, i, exc);
5419 exc = mono_get_exception_reflection_type_load (res, exl);
5420 mono_loader_clear_error ();
5421 mono_set_pending_exception (exc);
5428 ICALL_EXPORT gboolean
5429 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5431 MonoAssemblyName aname;
5432 MonoDomain *domain = mono_object_domain (name);
5434 gboolean is_version_defined;
5435 gboolean is_token_defined;
5437 aname.public_key = NULL;
5438 val = mono_string_to_utf8 (assname);
5439 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5440 g_free ((guint8*) aname.public_key);
5445 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5446 FALSE, is_token_defined);
5448 mono_assembly_name_free (&aname);
5449 g_free ((guint8*) aname.public_key);
5455 ICALL_EXPORT MonoReflectionType*
5456 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5459 MonoReflectionType *ret;
5460 MonoDomain *domain = mono_object_domain (module);
5463 g_assert (module->image);
5465 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5466 /* These images do not have a global type */
5469 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5470 if (!mono_error_ok (&error)) {
5471 mono_error_set_pending_exception (&error);
5475 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5476 if (!mono_error_ok (&error)) {
5477 mono_error_set_pending_exception (&error);
5485 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5487 /*if (module->image)
5488 mono_image_close (module->image);*/
5491 ICALL_EXPORT MonoString*
5492 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5494 MonoDomain *domain = mono_object_domain (module);
5496 g_assert (module->image);
5497 return mono_string_new (domain, module->image->guid);
5500 ICALL_EXPORT gpointer
5501 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5504 if (module->image && module->image->is_module_handle)
5505 return module->image->raw_data;
5508 return (gpointer) (-1);
5512 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5514 if (image_is_dynamic (image)) {
5515 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5516 *pe_kind = dyn->pe_kind;
5517 *machine = dyn->machine;
5520 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5521 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5526 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5528 return (image->md_version_major << 16) | (image->md_version_minor);
5531 ICALL_EXPORT MonoArray*
5532 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5534 MonoArray *exceptions;
5538 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5540 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5541 for (i = 0; i < mono_array_length (exceptions); ++i) {
5542 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5544 mono_set_pending_exception (ex);
5553 mono_memberref_is_method (MonoImage *image, guint32 token)
5555 if (!image_is_dynamic (image)) {
5556 guint32 cols [MONO_MEMBERREF_SIZE];
5558 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5559 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5560 mono_metadata_decode_blob_size (sig, &sig);
5561 return (*sig != 0x6);
5563 MonoClass *handle_class;
5565 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5568 return mono_defaults.methodhandle_class == handle_class;
5573 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5576 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5577 mono_array_addr (type_args, MonoType*, 0));
5579 context->class_inst = NULL;
5581 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5582 mono_array_addr (method_args, MonoType*, 0));
5584 context->method_inst = NULL;
5587 ICALL_EXPORT MonoType*
5588 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5591 int table = mono_metadata_token_table (token);
5592 int index = mono_metadata_token_index (token);
5593 MonoGenericContext context;
5596 *resolve_error = ResolveTokenError_Other;
5598 /* Validate token */
5599 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5600 (table != MONO_TABLE_TYPESPEC)) {
5601 *resolve_error = ResolveTokenError_BadTable;
5605 if (image_is_dynamic (image)) {
5606 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5607 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5608 return klass ? &klass->byval_arg : NULL;
5611 init_generic_context_from_args (&context, type_args, method_args);
5612 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5613 return klass ? &klass->byval_arg : NULL;
5616 if ((index <= 0) || (index > image->tables [table].rows)) {
5617 *resolve_error = ResolveTokenError_OutOfRange;
5621 init_generic_context_from_args (&context, type_args, method_args);
5622 klass = mono_class_get_checked (image, token, &error);
5624 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5625 if (!mono_error_ok (&error)) {
5626 mono_error_set_pending_exception (&error);
5631 return &klass->byval_arg;
5636 ICALL_EXPORT MonoMethod*
5637 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5640 int table = mono_metadata_token_table (token);
5641 int index = mono_metadata_token_index (token);
5642 MonoGenericContext context;
5645 *resolve_error = ResolveTokenError_Other;
5647 /* Validate token */
5648 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5649 (table != MONO_TABLE_MEMBERREF)) {
5650 *resolve_error = ResolveTokenError_BadTable;
5654 if (image_is_dynamic (image)) {
5655 if (table == MONO_TABLE_METHOD)
5656 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5658 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5659 *resolve_error = ResolveTokenError_BadTable;
5663 init_generic_context_from_args (&context, type_args, method_args);
5664 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5667 if ((index <= 0) || (index > image->tables [table].rows)) {
5668 *resolve_error = ResolveTokenError_OutOfRange;
5671 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5672 *resolve_error = ResolveTokenError_BadTable;
5676 init_generic_context_from_args (&context, type_args, method_args);
5677 method = mono_get_method_checked (image, token, NULL, &context, &error);
5678 mono_error_set_pending_exception (&error);
5683 ICALL_EXPORT MonoString*
5684 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5686 int index = mono_metadata_token_index (token);
5688 *error = ResolveTokenError_Other;
5690 /* Validate token */
5691 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5692 *error = ResolveTokenError_BadTable;
5696 if (image_is_dynamic (image))
5697 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5699 if ((index <= 0) || (index >= image->heap_us.size)) {
5700 *error = ResolveTokenError_OutOfRange;
5704 /* FIXME: What to do if the index points into the middle of a string ? */
5706 return mono_ldstr (mono_domain_get (), image, index);
5709 ICALL_EXPORT MonoClassField*
5710 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5714 int table = mono_metadata_token_table (token);
5715 int index = mono_metadata_token_index (token);
5716 MonoGenericContext context;
5717 MonoClassField *field;
5719 *resolve_error = ResolveTokenError_Other;
5721 /* Validate token */
5722 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5723 *resolve_error = ResolveTokenError_BadTable;
5727 if (image_is_dynamic (image)) {
5728 if (table == MONO_TABLE_FIELD)
5729 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5731 if (mono_memberref_is_method (image, token)) {
5732 *resolve_error = ResolveTokenError_BadTable;
5736 init_generic_context_from_args (&context, type_args, method_args);
5737 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5740 if ((index <= 0) || (index > image->tables [table].rows)) {
5741 *resolve_error = ResolveTokenError_OutOfRange;
5744 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5745 *resolve_error = ResolveTokenError_BadTable;
5749 init_generic_context_from_args (&context, type_args, method_args);
5750 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5751 mono_error_set_pending_exception (&error);
5757 ICALL_EXPORT MonoObject*
5758 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5762 int table = mono_metadata_token_table (token);
5764 *error = ResolveTokenError_Other;
5767 case MONO_TABLE_TYPEDEF:
5768 case MONO_TABLE_TYPEREF:
5769 case MONO_TABLE_TYPESPEC: {
5770 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5772 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
5773 mono_error_raise_exception (&merror);
5780 case MONO_TABLE_METHOD:
5781 case MONO_TABLE_METHODSPEC: {
5782 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5784 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5785 mono_error_raise_exception (&merror);
5791 case MONO_TABLE_FIELD: {
5792 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5794 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5795 mono_error_raise_exception (&merror);
5801 case MONO_TABLE_MEMBERREF:
5802 if (mono_memberref_is_method (image, token)) {
5803 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5805 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5806 mono_error_raise_exception (&merror);
5813 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5815 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5816 mono_error_raise_exception (&merror);
5825 *error = ResolveTokenError_BadTable;
5831 ICALL_EXPORT MonoArray*
5832 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5834 int table = mono_metadata_token_table (token);
5835 int idx = mono_metadata_token_index (token);
5836 MonoTableInfo *tables = image->tables;
5841 *error = ResolveTokenError_OutOfRange;
5843 /* FIXME: Support other tables ? */
5844 if (table != MONO_TABLE_STANDALONESIG)
5847 if (image_is_dynamic (image))
5850 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5853 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5855 ptr = mono_metadata_blob_heap (image, sig);
5856 len = mono_metadata_decode_blob_size (ptr, &ptr);
5858 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5859 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5863 ICALL_EXPORT MonoReflectionType*
5864 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5867 MonoReflectionType *ret;
5869 int isbyref = 0, rank;
5870 char *str = mono_string_to_utf8 (smodifiers);
5873 klass = mono_class_from_mono_type (tb->type.type);
5875 /* logic taken from mono_reflection_parse_type(): keep in sync */
5879 if (isbyref) { /* only one level allowed by the spec */
5888 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
5889 mono_error_raise_exception (&error);
5893 klass = mono_ptr_class_get (&klass->byval_arg);
5894 mono_class_init (klass);
5905 else if (*p != '*') { /* '*' means unknown lower bound */
5916 klass = mono_array_class_get (klass, rank);
5917 mono_class_init (klass);
5926 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
5927 mono_error_raise_exception (&error);
5932 ICALL_EXPORT MonoBoolean
5933 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5939 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5945 check_for_invalid_type (MonoClass *klass)
5949 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5952 name = mono_type_get_full_name (klass);
5953 str = mono_string_new (mono_domain_get (), name);
5955 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5958 ICALL_EXPORT MonoReflectionType *
5959 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5962 MonoReflectionType *ret;
5963 MonoClass *klass, *aklass;
5965 klass = mono_class_from_mono_type (type->type);
5966 check_for_invalid_type (klass);
5968 if (rank == 0) //single dimentional array
5969 aklass = mono_array_class_get (klass, 1);
5971 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5973 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
5974 mono_error_raise_exception (&error);
5979 ICALL_EXPORT MonoReflectionType *
5980 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5983 MonoReflectionType *ret;
5986 klass = mono_class_from_mono_type (type->type);
5987 mono_class_init_or_throw (klass);
5988 check_for_invalid_type (klass);
5990 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
5991 mono_error_raise_exception (&error);
5996 ICALL_EXPORT MonoReflectionType *
5997 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6000 MonoReflectionType *ret;
6001 MonoClass *klass, *pklass;
6003 klass = mono_class_from_mono_type (type->type);
6004 mono_class_init_or_throw (klass);
6005 check_for_invalid_type (klass);
6007 pklass = mono_ptr_class_get (type->type);
6009 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6010 mono_error_raise_exception (&error);
6015 ICALL_EXPORT MonoObject *
6016 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6017 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6020 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6021 MonoObject *delegate;
6023 MonoMethod *method = info->method;
6025 mono_class_init_or_throw (delegate_class);
6027 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
6029 if (mono_security_core_clr_enabled ()) {
6030 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6034 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6035 mono_error_raise_exception (&error);
6037 if (method_is_dynamic (method)) {
6038 /* Creating a trampoline would leak memory */
6039 func = mono_compile_method (method);
6041 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6042 method = mono_object_get_virtual_method (target, method);
6043 func = mono_create_ftnptr (mono_domain_get (),
6044 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6047 mono_delegate_ctor_with_method (delegate, target, func, method);
6052 ICALL_EXPORT MonoMulticastDelegate *
6053 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6056 MonoMulticastDelegate *ret;
6058 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6060 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6061 mono_error_raise_exception (&error);
6062 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6067 ICALL_EXPORT MonoReflectionMethod*
6068 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6070 MonoReflectionMethod *ret = NULL;
6072 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6073 mono_error_raise_exception (&error);
6079 static inline gint32
6080 mono_array_get_byte_length (MonoArray *array)
6086 klass = array->obj.vtable->klass;
6088 if (array->bounds == NULL)
6089 length = array->max_length;
6092 for (i = 0; i < klass->rank; ++ i)
6093 length *= array->bounds [i].length;
6096 switch (klass->element_class->byval_arg.type) {
6099 case MONO_TYPE_BOOLEAN:
6103 case MONO_TYPE_CHAR:
6111 return length * sizeof (gpointer);
6122 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6124 return mono_array_get_byte_length (array);
6128 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6130 return mono_array_get (array, gint8, idx);
6134 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6136 mono_array_set (array, gint8, idx, value);
6139 ICALL_EXPORT MonoBoolean
6140 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6142 guint8 *src_buf, *dest_buf;
6145 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6149 g_assert (count >= 0);
6151 /* This is called directly from the class libraries without going through the managed wrapper */
6152 MONO_CHECK_ARG_NULL (src, FALSE);
6153 MONO_CHECK_ARG_NULL (dest, FALSE);
6155 /* watch out for integer overflow */
6156 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6159 src_buf = (guint8 *)src->vector + src_offset;
6160 dest_buf = (guint8 *)dest->vector + dest_offset;
6163 memcpy (dest_buf, src_buf, count);
6165 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6170 #ifndef DISABLE_REMOTING
6171 ICALL_EXPORT MonoObject *
6172 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6175 MonoDomain *domain = mono_object_domain (this_obj);
6177 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6178 MonoTransparentProxy *tp;
6182 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6183 mono_error_raise_exception (&error);
6184 tp = (MonoTransparentProxy*) res;
6186 MONO_OBJECT_SETREF (tp, rp, rp);
6187 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6188 klass = mono_class_from_mono_type (type);
6190 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6191 mono_class_setup_vtable (klass);
6192 if (klass->exception_type) {
6193 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6197 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
6198 tp->remote_class = mono_remote_class (domain, class_name, klass);
6200 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6204 ICALL_EXPORT MonoReflectionType *
6205 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6208 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6209 mono_error_raise_exception (&error);
6215 /* System.Environment */
6218 ves_icall_System_Environment_get_UserName (void)
6220 /* using glib is more portable */
6221 return mono_string_new (mono_domain_get (), g_get_user_name ());
6225 ICALL_EXPORT MonoString *
6226 ves_icall_System_Environment_get_MachineName (void)
6228 #if defined (HOST_WIN32)
6233 len = MAX_COMPUTERNAME_LENGTH + 1;
6234 buf = g_new (gunichar2, len);
6237 if (GetComputerName (buf, (PDWORD) &len)) {
6239 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6240 mono_error_raise_exception (&error);
6245 #elif !defined(DISABLE_SOCKETS)
6249 #if defined _SC_HOST_NAME_MAX
6250 n = sysconf (_SC_HOST_NAME_MAX);
6254 buf = g_malloc (n+1);
6256 if (gethostname (buf, n) == 0){
6258 result = mono_string_new (mono_domain_get (), buf);
6265 return mono_string_new (mono_domain_get (), "mono");
6270 ves_icall_System_Environment_get_Platform (void)
6272 #if defined (TARGET_WIN32)
6275 #elif defined(__MACH__)
6278 // Notice that the value is hidden from user code, and only exposed
6279 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6280 // define and making assumptions based on Unix/128/4 values before there
6281 // was a MacOS define. Lots of code would assume that not-Unix meant
6282 // Windows, but in this case, it would be OSX.
6291 ICALL_EXPORT MonoString *
6292 ves_icall_System_Environment_get_NewLine (void)
6294 #if defined (HOST_WIN32)
6295 return mono_string_new (mono_domain_get (), "\r\n");
6297 return mono_string_new (mono_domain_get (), "\n");
6301 ICALL_EXPORT MonoBoolean
6302 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6304 #if SIZEOF_VOID_P == 8
6308 gboolean isWow64Process = FALSE;
6309 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6310 return (MonoBoolean)isWow64Process;
6312 #elif defined(HAVE_SYS_UTSNAME_H)
6313 struct utsname name;
6315 if (uname (&name) >= 0) {
6316 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6323 ICALL_EXPORT MonoString *
6324 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6332 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6333 value = g_getenv (utf8_name);
6340 return mono_string_new (mono_domain_get (), value);
6344 * There is no standard way to get at environ.
6347 #ifndef __MINGW32_VERSION
6348 #if defined(__APPLE__)
6349 #if defined (TARGET_OSX)
6350 /* Apple defines this in crt_externs.h but doesn't provide that header for
6351 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6352 * in fact exist on all implementations (so far)
6354 gchar ***_NSGetEnviron(void);
6355 #define environ (*_NSGetEnviron())
6357 static char *mono_environ[1] = { NULL };
6358 #define environ mono_environ
6359 #endif /* defined (TARGET_OSX) */
6367 ICALL_EXPORT MonoArray *
6368 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6379 env_strings = GetEnvironmentStrings();
6382 env_string = env_strings;
6383 while (*env_string != '\0') {
6384 /* weird case that MS seems to skip */
6385 if (*env_string != '=')
6387 while (*env_string != '\0')
6393 domain = mono_domain_get ();
6394 names = mono_array_new (domain, mono_defaults.string_class, n);
6398 env_string = env_strings;
6399 while (*env_string != '\0') {
6400 /* weird case that MS seems to skip */
6401 if (*env_string != '=') {
6402 equal_str = wcschr(env_string, '=');
6403 g_assert(equal_str);
6405 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6406 mono_error_raise_exception (&error);
6407 mono_array_setref (names, n, str);
6410 while (*env_string != '\0')
6415 FreeEnvironmentStrings (env_strings);
6428 for (e = environ; *e != 0; ++ e)
6431 domain = mono_domain_get ();
6432 names = mono_array_new (domain, mono_defaults.string_class, n);
6435 for (e = environ; *e != 0; ++ e) {
6436 parts = g_strsplit (*e, "=", 2);
6438 str = mono_string_new (domain, *parts);
6439 mono_array_setref (names, n, str);
6452 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6454 #if !GLIB_CHECK_VERSION(2,4,0)
6455 #define g_setenv(a,b,c) setenv(a,b,c)
6456 #define g_unsetenv(a) unsetenv(a)
6460 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6463 gunichar2 *utf16_name, *utf16_value;
6465 gchar *utf8_name, *utf8_value;
6470 utf16_name = mono_string_to_utf16 (name);
6471 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6472 SetEnvironmentVariable (utf16_name, NULL);
6473 g_free (utf16_name);
6477 utf16_value = mono_string_to_utf16 (value);
6479 SetEnvironmentVariable (utf16_name, utf16_value);
6481 g_free (utf16_name);
6482 g_free (utf16_value);
6484 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6486 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6487 g_unsetenv (utf8_name);
6492 utf8_value = mono_string_to_utf8_checked (value, &error);
6493 if (!mono_error_ok (&error)) {
6495 mono_error_set_pending_exception (&error);
6498 g_setenv (utf8_name, utf8_value, TRUE);
6501 g_free (utf8_value);
6506 ves_icall_System_Environment_Exit (int result)
6508 mono_environment_exitcode_set (result);
6510 /* FIXME: There are some cleanup hangs that should be worked out, but
6511 * if the program is going to exit, everything will be cleaned up when
6512 * NaCl exits anyway.
6514 #ifndef __native_client__
6515 if (!mono_runtime_try_shutdown ())
6516 mono_thread_exit ();
6518 /* Suspend all managed threads since the runtime is going away */
6519 mono_thread_suspend_all_other_threads ();
6521 mono_runtime_quit ();
6524 /* we may need to do some cleanup here... */
6528 ICALL_EXPORT MonoString*
6529 ves_icall_System_Environment_GetGacPath (void)
6531 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6534 ICALL_EXPORT MonoString*
6535 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6537 #if defined (HOST_WIN32)
6538 #ifndef CSIDL_FLAG_CREATE
6539 #define CSIDL_FLAG_CREATE 0x8000
6542 WCHAR path [MAX_PATH];
6543 /* Create directory if no existing */
6544 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6549 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6550 mono_error_raise_exception (&error);
6554 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6556 return mono_string_new (mono_domain_get (), "");
6559 ICALL_EXPORT MonoArray *
6560 ves_icall_System_Environment_GetLogicalDrives (void)
6563 gunichar2 buf [256], *ptr, *dname;
6565 guint initial_size = 127, size = 128;
6568 MonoString *drivestr;
6569 MonoDomain *domain = mono_domain_get ();
6575 while (size > initial_size) {
6576 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6577 if (size > initial_size) {
6580 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6581 initial_size = size;
6595 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6600 while (*u16) { u16++; len ++; }
6601 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6602 mono_error_raise_exception (&error);
6603 mono_array_setref (result, ndrives++, drivestr);
6613 ICALL_EXPORT MonoString *
6614 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6616 gunichar2 volume_name [MAX_PATH + 1];
6618 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6620 return mono_string_from_utf16 (volume_name);
6623 ICALL_EXPORT MonoString *
6624 ves_icall_System_Environment_InternalGetHome (void)
6626 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6629 static const char *encodings [] = {
6631 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6632 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6633 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6635 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6636 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6637 "x_unicode_2_0_utf_7",
6639 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6640 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6642 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6645 "unicodefffe", "utf_16be",
6652 * Returns the internal codepage, if the value of "int_code_page" is
6653 * 1 at entry, and we can not compute a suitable code page number,
6654 * returns the code page as a string
6656 ICALL_EXPORT MonoString*
6657 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6662 char *codepage = NULL;
6664 int want_name = *int_code_page;
6667 *int_code_page = -1;
6669 g_get_charset (&cset);
6670 c = codepage = strdup (cset);
6671 for (c = codepage; *c; c++){
6672 if (isascii (*c) && isalpha (*c))
6677 /* g_print ("charset: %s\n", cset); */
6679 /* handle some common aliases */
6682 for (i = 0; p != 0; ){
6685 p = encodings [++i];
6688 if (strcmp (p, codepage) == 0){
6689 *int_code_page = code;
6692 p = encodings [++i];
6695 if (strstr (codepage, "utf_8") != NULL)
6696 *int_code_page |= 0x10000000;
6699 if (want_name && *int_code_page == -1)
6700 return mono_string_new (mono_domain_get (), cset);
6705 ICALL_EXPORT MonoBoolean
6706 ves_icall_System_Environment_get_HasShutdownStarted (void)
6708 if (mono_runtime_is_shutting_down ())
6711 if (mono_domain_is_unloading (mono_domain_get ()))
6718 ves_icall_System_Environment_BroadcastSettingChange (void)
6721 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6726 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6732 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6733 MonoReflectionMethod *method,
6734 MonoArray *out_args)
6736 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6739 #ifndef DISABLE_REMOTING
6740 ICALL_EXPORT MonoBoolean
6741 ves_icall_IsTransparentProxy (MonoObject *proxy)
6746 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6752 ICALL_EXPORT MonoReflectionMethod *
6753 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6754 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6756 MonoReflectionMethod *ret = NULL;
6761 MonoMethod **vtable;
6762 MonoMethod *res = NULL;
6764 MONO_CHECK_ARG_NULL (rtype, NULL);
6765 MONO_CHECK_ARG_NULL (rmethod, NULL);
6767 method = rmethod->method;
6768 klass = mono_class_from_mono_type (rtype->type);
6769 mono_class_init_or_throw (klass);
6771 if (MONO_CLASS_IS_INTERFACE (klass))
6774 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6777 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6778 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6784 mono_class_setup_vtable (klass);
6785 vtable = klass->vtable;
6787 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6788 gboolean variance_used = FALSE;
6789 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6790 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6792 res = vtable [offs + method->slot];
6794 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6797 if (method->slot != -1)
6798 res = vtable [method->slot];
6804 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
6805 mono_error_raise_exception (&error);
6810 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6815 klass = mono_class_from_mono_type (type->type);
6816 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6818 mono_vtable_set_is_remote (vtable, enable);
6821 #else /* DISABLE_REMOTING */
6824 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6826 g_assert_not_reached ();
6831 ICALL_EXPORT MonoObject *
6832 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6839 domain = mono_object_domain (type);
6840 klass = mono_class_from_mono_type (type->type);
6841 mono_class_init_or_throw (klass);
6843 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
6844 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6848 if (klass->rank >= 1) {
6849 g_assert (klass->rank == 1);
6850 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6852 /* Bypass remoting object creation check */
6853 ret = mono_object_new_alloc_specific_checked (mono_class_vtable_full (domain, klass, TRUE), &error);
6854 mono_error_set_pending_exception (&error);
6860 ICALL_EXPORT MonoString *
6861 ves_icall_System_IO_get_temp_path (void)
6863 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6866 #ifndef PLATFORM_NO_DRIVEINFO
6867 ICALL_EXPORT MonoBoolean
6868 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6869 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6873 ULARGE_INTEGER wapi_free_bytes_avail;
6874 ULARGE_INTEGER wapi_total_number_of_bytes;
6875 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6877 *error = ERROR_SUCCESS;
6878 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6879 &wapi_total_number_of_free_bytes);
6882 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6883 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6884 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6886 *free_bytes_avail = 0;
6887 *total_number_of_bytes = 0;
6888 *total_number_of_free_bytes = 0;
6889 *error = GetLastError ();
6895 ICALL_EXPORT guint32
6896 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6898 return GetDriveType (mono_string_chars (root_path_name));
6902 ICALL_EXPORT gpointer
6903 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6905 return mono_compile_method (method);
6908 ICALL_EXPORT MonoString *
6909 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6914 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6916 #if defined (HOST_WIN32)
6917 /* Avoid mixing '/' and '\\' */
6920 for (i = strlen (path) - 1; i >= 0; i--)
6921 if (path [i] == '/')
6925 mcpath = mono_string_new (mono_domain_get (), path);
6932 get_bundled_app_config (void)
6934 const gchar *app_config;
6937 gchar *config_file_name, *config_file_path;
6938 gsize len, config_file_path_length, config_ext_length;
6941 domain = mono_domain_get ();
6942 file = domain->setup->configuration_file;
6943 if (!file || file->length == 0)
6946 // Retrieve config file and remove the extension
6947 config_file_name = mono_string_to_utf8 (file);
6948 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6949 if (!config_file_path)
6950 config_file_path = config_file_name;
6952 config_file_path_length = strlen (config_file_path);
6953 config_ext_length = strlen (".config");
6954 if (config_file_path_length <= config_ext_length)
6957 len = config_file_path_length - config_ext_length;
6958 module = (gchar *)g_malloc0 (len + 1);
6959 memcpy (module, config_file_path, len);
6960 // Get the config file from the module name
6961 app_config = mono_config_string_for_assembly_file (module);
6964 if (config_file_name != config_file_path)
6965 g_free (config_file_name);
6966 g_free (config_file_path);
6971 return mono_string_new (mono_domain_get (), app_config);
6975 get_bundled_machine_config (void)
6977 const gchar *machine_config;
6979 machine_config = mono_get_machine_config ();
6981 if (!machine_config)
6984 return mono_string_new (mono_domain_get (), machine_config);
6987 ICALL_EXPORT MonoString *
6988 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6993 path = g_path_get_dirname (mono_get_config_dir ());
6995 #if defined (HOST_WIN32)
6996 /* Avoid mixing '/' and '\\' */
6999 for (i = strlen (path) - 1; i >= 0; i--)
7000 if (path [i] == '/')
7004 ipath = mono_string_new (mono_domain_get (), path);
7010 ICALL_EXPORT gboolean
7011 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7013 MonoPEResourceDataEntry *entry;
7016 if (!assembly || !result || !size)
7021 image = assembly->assembly->image;
7022 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7026 *result = mono_image_rva_map (image, entry->rde_data_offset);
7031 *size = entry->rde_size;
7036 ICALL_EXPORT MonoBoolean
7037 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7039 return mono_is_debugger_attached ();
7042 ICALL_EXPORT MonoBoolean
7043 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7045 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7046 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7052 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7054 if (mono_get_runtime_callbacks ()->debug_log)
7055 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7059 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7061 #if defined (HOST_WIN32)
7062 OutputDebugString (mono_string_chars (message));
7064 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7068 /* Only used for value types */
7069 ICALL_EXPORT MonoObject *
7070 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7077 domain = mono_object_domain (type);
7078 klass = mono_class_from_mono_type (type->type);
7079 mono_class_init_or_throw (klass);
7081 if (mono_class_is_nullable (klass))
7082 /* No arguments -> null */
7085 result = mono_object_new_checked (domain, klass, &error);
7086 mono_error_raise_exception (&error);
7090 ICALL_EXPORT MonoReflectionMethod *
7091 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7093 MonoReflectionMethod *ret = NULL;
7096 MonoClass *klass, *parent;
7097 MonoGenericContext *generic_inst = NULL;
7098 MonoMethod *method = m->method;
7099 MonoMethod *result = NULL;
7102 if (method->klass == NULL)
7105 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7106 MONO_CLASS_IS_INTERFACE (method->klass) ||
7107 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7110 slot = mono_method_get_vtable_slot (method);
7114 klass = method->klass;
7115 if (klass->generic_class) {
7116 generic_inst = mono_class_get_context (klass);
7117 klass = klass->generic_class->container_class;
7121 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7122 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7123 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7124 or klass is the generic container class and generic_inst is the instantiation.
7126 when we go to the parent, if the parent is an open constructed type, we need to
7127 replace the type parameters by the definitions from the generic_inst, and then take it
7128 apart again into the klass and the generic_inst.
7130 For cases like this:
7131 class C<T> : B<T, int> {
7132 public override void Foo () { ... }
7134 class B<U,V> : A<HashMap<U,V>> {
7135 public override void Foo () { ... }
7138 public virtual void Foo () { ... }
7141 if at each iteration the parent isn't open, we can skip inflating it. if at some
7142 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7145 MonoGenericContext *parent_inst = NULL;
7146 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7148 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7149 if (!mono_error_ok (&error)) {
7150 mono_error_set_pending_exception (&error);
7154 if (parent->generic_class) {
7155 parent_inst = mono_class_get_context (parent);
7156 parent = parent->generic_class->container_class;
7159 mono_class_setup_vtable (parent);
7160 if (parent->vtable_size <= slot)
7163 generic_inst = parent_inst;
7166 klass = klass->parent;
7169 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7170 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7171 if (!mono_error_ok (&error)) {
7172 mono_error_set_pending_exception (&error);
7176 generic_inst = NULL;
7178 if (klass->generic_class) {
7179 generic_inst = mono_class_get_context (klass);
7180 klass = klass->generic_class->container_class;
7186 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7187 if (!mono_error_ok (&error)) {
7188 mono_error_set_pending_exception (&error);
7193 if (klass == method->klass)
7196 /*This is possible if definition == FALSE.
7197 * Do it here to be really sure we don't read invalid memory.
7199 if (slot >= klass->vtable_size)
7202 mono_class_setup_vtable (klass);
7204 result = klass->vtable [slot];
7205 if (result == NULL) {
7206 /* It is an abstract method */
7207 gpointer iter = NULL;
7208 while ((result = mono_class_get_methods (klass, &iter)))
7209 if (result->slot == slot)
7216 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7217 mono_error_raise_exception (&error);
7221 ICALL_EXPORT MonoString*
7222 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7224 MonoMethod *method = m->method;
7226 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7231 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7233 iter->sig = *(MonoMethodSignature**)argsp;
7235 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7236 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7239 /* FIXME: it's not documented what start is exactly... */
7243 iter->args = argsp + sizeof (gpointer);
7245 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7247 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7250 ICALL_EXPORT MonoTypedRef
7251 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7253 guint32 i, arg_size;
7257 i = iter->sig->sentinelpos + iter->next_arg;
7259 g_assert (i < iter->sig->param_count);
7261 res.type = iter->sig->params [i];
7262 res.klass = mono_class_from_mono_type (res.type);
7263 arg_size = mono_type_stack_size (res.type, &align);
7264 #if defined(__arm__) || defined(__mips__)
7265 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7267 res.value = iter->args;
7268 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7269 /* Values are stored as 8 byte register sized objects, but 'value'
7270 * is dereferenced as a pointer in other routines.
7272 res.value = (char*)res.value + 4;
7274 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7275 if (arg_size <= sizeof (gpointer)) {
7277 int padding = arg_size - mono_type_size (res.type, &dummy);
7278 res.value = (guint8*)res.value + padding;
7281 iter->args = (char*)iter->args + arg_size;
7284 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7289 ICALL_EXPORT MonoTypedRef
7290 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7292 guint32 i, arg_size;
7296 i = iter->sig->sentinelpos + iter->next_arg;
7298 g_assert (i < iter->sig->param_count);
7300 while (i < iter->sig->param_count) {
7301 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7303 res.type = iter->sig->params [i];
7304 res.klass = mono_class_from_mono_type (res.type);
7305 /* FIXME: endianess issue... */
7306 arg_size = mono_type_stack_size (res.type, &align);
7307 #if defined(__arm__) || defined(__mips__)
7308 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7310 res.value = iter->args;
7311 iter->args = (char*)iter->args + arg_size;
7313 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7316 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7324 ICALL_EXPORT MonoType*
7325 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7329 i = iter->sig->sentinelpos + iter->next_arg;
7331 g_assert (i < iter->sig->param_count);
7333 return iter->sig->params [i];
7336 ICALL_EXPORT MonoObject*
7337 mono_TypedReference_ToObject (MonoTypedRef* tref)
7339 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7340 MonoObject** objp = (MonoObject **)tref->value;
7344 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
7347 ICALL_EXPORT MonoTypedRef
7348 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7351 MonoReflectionField *f;
7353 MonoType *ftype = NULL;
7357 memset (&res, 0, sizeof (res));
7360 g_assert (mono_array_length (fields) > 0);
7362 klass = target->vtable->klass;
7364 for (i = 0; i < mono_array_length (fields); ++i) {
7365 f = mono_array_get (fields, MonoReflectionField*, i);
7367 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7370 if (f->field->parent != klass) {
7371 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7375 p = (guint8*)target + f->field->offset;
7377 p += f->field->offset - sizeof (MonoObject);
7378 klass = mono_class_from_mono_type (f->field->type);
7379 ftype = f->field->type;
7383 res.klass = mono_class_from_mono_type (ftype);
7390 prelink_method (MonoMethod *method)
7392 const char *exc_class, *exc_arg;
7393 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7395 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7397 mono_raise_exception(
7398 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7400 /* create the wrapper, too? */
7404 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7406 prelink_method (method->method);
7410 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7412 MonoClass *klass = mono_class_from_mono_type (type->type);
7414 gpointer iter = NULL;
7416 mono_class_init_or_throw (klass);
7418 while ((m = mono_class_get_methods (klass, &iter)))
7422 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7424 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7425 gint32 const **exponents,
7426 gunichar2 const **digitLowerTable,
7427 gunichar2 const **digitUpperTable,
7428 gint64 const **tenPowersList,
7429 gint32 const **decHexDigits)
7431 *mantissas = Formatter_MantissaBitsTable;
7432 *exponents = Formatter_TensExponentTable;
7433 *digitLowerTable = Formatter_DigitLowerTable;
7434 *digitUpperTable = Formatter_DigitUpperTable;
7435 *tenPowersList = Formatter_TenPowersList;
7436 *decHexDigits = Formatter_DecHexDigits;
7440 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7441 * and avoid useless allocations.
7446 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7449 MonoReflectionType *rt;
7452 for (i = 0; i < type->num_mods; ++i) {
7453 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7458 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7460 for (i = 0; i < type->num_mods; ++i) {
7461 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7462 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
7463 mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */
7465 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, &error);
7466 mono_error_raise_exception (&error);
7468 mono_array_setref (res, count, rt);
7475 ICALL_EXPORT MonoArray*
7476 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7478 MonoType *type = param->ClassImpl->type;
7479 MonoClass *member_class = mono_object_class (param->MemberImpl);
7480 MonoMethod *method = NULL;
7483 MonoMethodSignature *sig;
7485 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7486 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7487 method = rmethod->method;
7488 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7489 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7490 if (!(method = prop->property->get))
7491 method = prop->property->set;
7494 char *type_name = mono_type_get_full_name (member_class);
7495 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7496 MonoException *ex = mono_get_exception_not_supported (msg);
7499 mono_set_pending_exception (ex);
7503 image = method->klass->image;
7504 pos = param->PositionImpl;
7505 sig = mono_method_signature (method);
7509 type = sig->params [pos];
7511 return type_array_from_modifiers (image, type, optional);
7515 get_property_type (MonoProperty *prop)
7517 MonoMethodSignature *sig;
7519 sig = mono_method_signature (prop->get);
7521 } else if (prop->set) {
7522 sig = mono_method_signature (prop->set);
7523 return sig->params [sig->param_count - 1];
7528 ICALL_EXPORT MonoArray*
7529 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7531 MonoType *type = get_property_type (property->property);
7532 MonoImage *image = property->klass->image;
7536 return type_array_from_modifiers (image, type, optional);
7540 *Construct a MonoType suited to be used to decode a constant blob object.
7542 * @type is the target type which will be constructed
7543 * @blob_type is the blob type, for example, that comes from the constant table
7544 * @real_type is the expected constructed type.
7547 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7549 type->type = blob_type;
7550 type->data.klass = NULL;
7551 if (blob_type == MONO_TYPE_CLASS)
7552 type->data.klass = mono_defaults.object_class;
7553 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7554 /* For enums, we need to use the base type */
7555 type->type = MONO_TYPE_VALUETYPE;
7556 type->data.klass = mono_class_from_mono_type (real_type);
7558 type->data.klass = mono_class_from_mono_type (real_type);
7561 ICALL_EXPORT MonoObject*
7562 property_info_get_default_value (MonoReflectionProperty *property)
7565 MonoProperty *prop = property->property;
7566 MonoType *type = get_property_type (prop);
7567 MonoDomain *domain = mono_object_domain (property);
7568 MonoTypeEnum def_type;
7569 const char *def_value;
7572 mono_class_init (prop->parent);
7574 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7575 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7579 def_value = mono_class_get_property_default_value (prop, &def_type);
7581 mono_type_from_blob_type (&blob_type, def_type, type);
7582 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7587 ICALL_EXPORT MonoBoolean
7588 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7590 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7591 MonoCustomAttrInfo *cinfo;
7594 mono_class_init_or_throw (attr_class);
7596 cinfo = mono_reflection_get_custom_attrs_info (obj);
7599 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7601 mono_custom_attrs_free (cinfo);
7605 ICALL_EXPORT MonoArray*
7606 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7608 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7613 mono_class_init_or_throw (attr_class);
7615 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7616 if (!mono_error_ok (&error)) {
7617 mono_error_set_pending_exception (&error);
7621 if (mono_loader_get_last_error ()) {
7622 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7629 ICALL_EXPORT MonoString*
7630 ves_icall_Mono_Runtime_GetDisplayName (void)
7633 MonoString *display_name;
7635 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7636 display_name = mono_string_new (mono_domain_get (), info);
7638 return display_name;
7641 ICALL_EXPORT MonoString*
7642 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7645 MonoString *message;
7649 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7650 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7653 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7655 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7656 mono_error_raise_exception (&error);
7663 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7666 char *path_str = mono_string_to_utf8 (path);
7668 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7676 #ifndef DISABLE_ICALL_TABLES
7678 #define ICALL_TYPE(id,name,first)
7679 #define ICALL(id,name,func) Icall_ ## id,
7682 #include "metadata/icall-def.h"
7688 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7689 #define ICALL(id,name,func)
7691 #include "metadata/icall-def.h"
7697 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7698 #define ICALL(id,name,func)
7700 guint16 first_icall;
7703 static const IcallTypeDesc
7704 icall_type_descs [] = {
7705 #include "metadata/icall-def.h"
7709 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7712 #define ICALL_TYPE(id,name,first)
7715 #ifdef HAVE_ARRAY_ELEM_INIT
7716 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7717 #define MSGSTRFIELD1(line) str##line
7719 static const struct msgstrtn_t {
7720 #define ICALL(id,name,func)
7722 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7723 #include "metadata/icall-def.h"
7725 } icall_type_names_str = {
7726 #define ICALL_TYPE(id,name,first) (name),
7727 #include "metadata/icall-def.h"
7730 static const guint16 icall_type_names_idx [] = {
7731 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7732 #include "metadata/icall-def.h"
7735 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7737 static const struct msgstr_t {
7739 #define ICALL_TYPE(id,name,first)
7740 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7741 #include "metadata/icall-def.h"
7743 } icall_names_str = {
7744 #define ICALL(id,name,func) (name),
7745 #include "metadata/icall-def.h"
7748 static const guint16 icall_names_idx [] = {
7749 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7750 #include "metadata/icall-def.h"
7753 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7759 #define ICALL_TYPE(id,name,first) name,
7760 #define ICALL(id,name,func)
7761 static const char* const
7762 icall_type_names [] = {
7763 #include "metadata/icall-def.h"
7767 #define icall_type_name_get(id) (icall_type_names [(id)])
7771 #define ICALL_TYPE(id,name,first)
7772 #define ICALL(id,name,func) name,
7773 static const char* const
7775 #include "metadata/icall-def.h"
7778 #define icall_name_get(id) icall_names [(id)]
7780 #endif /* !HAVE_ARRAY_ELEM_INIT */
7784 #define ICALL_TYPE(id,name,first)
7785 #define ICALL(id,name,func) func,
7786 static const gconstpointer
7787 icall_functions [] = {
7788 #include "metadata/icall-def.h"
7792 #ifdef ENABLE_ICALL_SYMBOL_MAP
7795 #define ICALL_TYPE(id,name,first)
7796 #define ICALL(id,name,func) #func,
7797 static const gconstpointer
7798 icall_symbols [] = {
7799 #include "metadata/icall-def.h"
7804 #endif /* DISABLE_ICALL_TABLES */
7806 static mono_mutex_t icall_mutex;
7807 static GHashTable *icall_hash = NULL;
7808 static GHashTable *jit_icall_hash_name = NULL;
7809 static GHashTable *jit_icall_hash_addr = NULL;
7812 mono_icall_init (void)
7814 #ifndef DISABLE_ICALL_TABLES
7817 /* check that tables are sorted: disable in release */
7820 const char *prev_class = NULL;
7821 const char *prev_method;
7823 for (i = 0; i < Icall_type_num; ++i) {
7824 const IcallTypeDesc *desc;
7827 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7828 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7829 prev_class = icall_type_name_get (i);
7830 desc = &icall_type_descs [i];
7831 num_icalls = icall_desc_num_icalls (desc);
7832 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7833 for (j = 0; j < num_icalls; ++j) {
7834 const char *methodn = icall_name_get (desc->first_icall + j);
7835 if (prev_method && strcmp (prev_method, methodn) >= 0)
7836 g_print ("method %s should come before method %s\n", methodn, prev_method);
7837 prev_method = methodn;
7843 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7844 mono_os_mutex_init (&icall_mutex);
7848 mono_icall_lock (void)
7850 mono_locks_os_acquire (&icall_mutex, IcallLock);
7854 mono_icall_unlock (void)
7856 mono_locks_os_release (&icall_mutex, IcallLock);
7860 mono_icall_cleanup (void)
7862 g_hash_table_destroy (icall_hash);
7863 g_hash_table_destroy (jit_icall_hash_name);
7864 g_hash_table_destroy (jit_icall_hash_addr);
7865 mono_os_mutex_destroy (&icall_mutex);
7869 mono_add_internal_call (const char *name, gconstpointer method)
7873 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7875 mono_icall_unlock ();
7878 #ifndef DISABLE_ICALL_TABLES
7880 #ifdef HAVE_ARRAY_ELEM_INIT
7882 compare_method_imap (const void *key, const void *elem)
7884 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7885 return strcmp (key, method_name);
7889 find_method_icall (const IcallTypeDesc *imap, const char *name)
7891 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);
7894 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7898 compare_class_imap (const void *key, const void *elem)
7900 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7901 return strcmp (key, class_name);
7904 static const IcallTypeDesc*
7905 find_class_icalls (const char *name)
7907 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);
7910 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7913 #else /* HAVE_ARRAY_ELEM_INIT */
7916 compare_method_imap (const void *key, const void *elem)
7918 const char** method_name = (const char**)elem;
7919 return strcmp (key, *method_name);
7923 find_method_icall (const IcallTypeDesc *imap, const char *name)
7925 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7928 return (gpointer)icall_functions [(nameslot - icall_names)];
7932 compare_class_imap (const void *key, const void *elem)
7934 const char** class_name = (const char**)elem;
7935 return strcmp (key, *class_name);
7938 static const IcallTypeDesc*
7939 find_class_icalls (const char *name)
7941 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7944 return &icall_type_descs [nameslot - icall_type_names];
7947 #endif /* HAVE_ARRAY_ELEM_INIT */
7949 #endif /* DISABLE_ICALL_TABLES */
7952 * we should probably export this as an helper (handle nested types).
7953 * Returns the number of chars written in buf.
7956 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7958 int nspacelen, cnamelen;
7959 nspacelen = strlen (klass->name_space);
7960 cnamelen = strlen (klass->name);
7961 if (nspacelen + cnamelen + 2 > bufsize)
7964 memcpy (buf, klass->name_space, nspacelen);
7965 buf [nspacelen ++] = '.';
7967 memcpy (buf + nspacelen, klass->name, cnamelen);
7968 buf [nspacelen + cnamelen] = 0;
7969 return nspacelen + cnamelen;
7972 #ifdef DISABLE_ICALL_TABLES
7974 no_icall_table (void)
7976 g_assert_not_reached ();
7981 mono_lookup_internal_call (MonoMethod *method)
7986 int typelen = 0, mlen, siglen;
7988 #ifndef DISABLE_ICALL_TABLES
7989 const IcallTypeDesc *imap = NULL;
7992 g_assert (method != NULL);
7994 if (method->is_inflated)
7995 method = ((MonoMethodInflated *) method)->declaring;
7997 if (method->klass->nested_in) {
7998 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8002 mname [pos++] = '/';
8005 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8011 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8016 #ifndef DISABLE_ICALL_TABLES
8017 imap = find_class_icalls (mname);
8020 mname [typelen] = ':';
8021 mname [typelen + 1] = ':';
8023 mlen = strlen (method->name);
8024 memcpy (mname + typelen + 2, method->name, mlen);
8025 sigstart = mname + typelen + 2 + mlen;
8028 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8029 siglen = strlen (tmpsig);
8030 if (typelen + mlen + siglen + 6 > sizeof (mname))
8033 memcpy (sigstart + 1, tmpsig, siglen);
8034 sigstart [siglen + 1] = ')';
8035 sigstart [siglen + 2] = 0;
8040 res = g_hash_table_lookup (icall_hash, mname);
8042 mono_icall_unlock ();;
8045 /* try without signature */
8047 res = g_hash_table_lookup (icall_hash, mname);
8049 mono_icall_unlock ();
8053 #ifdef DISABLE_ICALL_TABLES
8054 mono_icall_unlock ();
8055 /* Fail only when the result is actually used */
8056 /* mono_marshal_get_native_wrapper () depends on this */
8057 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8058 return ves_icall_System_String_ctor_RedirectToCreateString;
8060 return no_icall_table;
8062 /* it wasn't found in the static call tables */
8064 mono_icall_unlock ();
8067 res = find_method_icall (imap, sigstart - mlen);
8069 mono_icall_unlock ();
8072 /* try _with_ signature */
8074 res = find_method_icall (imap, sigstart - mlen);
8076 mono_icall_unlock ();
8080 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8081 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8082 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8083 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8084 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");
8085 g_print ("If you see other errors or faults after this message they are probably related\n");
8086 g_print ("and you need to fix your mono install first.\n");
8088 mono_icall_unlock ();
8094 #ifdef ENABLE_ICALL_SYMBOL_MAP
8096 func_cmp (gconstpointer key, gconstpointer p)
8098 return (gsize)key - (gsize)*(gsize*)p;
8103 * mono_lookup_icall_symbol:
8105 * Given the icall METHOD, returns its C symbol.
8108 mono_lookup_icall_symbol (MonoMethod *m)
8110 #ifdef DISABLE_ICALL_TABLES
8111 g_assert_not_reached ();
8114 #ifdef ENABLE_ICALL_SYMBOL_MAP
8118 static gconstpointer *functions_sorted;
8119 static const char**symbols_sorted;
8120 static gboolean inited;
8125 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8126 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8127 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8128 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8129 /* Bubble sort the two arrays */
8133 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8134 if (functions_sorted [i] > functions_sorted [i + 1]) {
8137 tmp = functions_sorted [i];
8138 functions_sorted [i] = functions_sorted [i + 1];
8139 functions_sorted [i + 1] = tmp;
8140 tmp = symbols_sorted [i];
8141 symbols_sorted [i] = symbols_sorted [i + 1];
8142 symbols_sorted [i + 1] = tmp;
8149 func = mono_lookup_internal_call (m);
8152 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8156 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8158 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8159 g_assert_not_reached ();
8166 type_from_typename (char *type_name)
8168 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8170 if (!strcmp (type_name, "int"))
8171 klass = mono_defaults.int_class;
8172 else if (!strcmp (type_name, "ptr"))
8173 klass = mono_defaults.int_class;
8174 else if (!strcmp (type_name, "void"))
8175 klass = mono_defaults.void_class;
8176 else if (!strcmp (type_name, "int32"))
8177 klass = mono_defaults.int32_class;
8178 else if (!strcmp (type_name, "uint32"))
8179 klass = mono_defaults.uint32_class;
8180 else if (!strcmp (type_name, "int8"))
8181 klass = mono_defaults.sbyte_class;
8182 else if (!strcmp (type_name, "uint8"))
8183 klass = mono_defaults.byte_class;
8184 else if (!strcmp (type_name, "int16"))
8185 klass = mono_defaults.int16_class;
8186 else if (!strcmp (type_name, "uint16"))
8187 klass = mono_defaults.uint16_class;
8188 else if (!strcmp (type_name, "long"))
8189 klass = mono_defaults.int64_class;
8190 else if (!strcmp (type_name, "ulong"))
8191 klass = mono_defaults.uint64_class;
8192 else if (!strcmp (type_name, "float"))
8193 klass = mono_defaults.single_class;
8194 else if (!strcmp (type_name, "double"))
8195 klass = mono_defaults.double_class;
8196 else if (!strcmp (type_name, "object"))
8197 klass = mono_defaults.object_class;
8198 else if (!strcmp (type_name, "obj"))
8199 klass = mono_defaults.object_class;
8200 else if (!strcmp (type_name, "string"))
8201 klass = mono_defaults.string_class;
8202 else if (!strcmp (type_name, "bool"))
8203 klass = mono_defaults.boolean_class;
8204 else if (!strcmp (type_name, "boolean"))
8205 klass = mono_defaults.boolean_class;
8207 g_error ("%s", type_name);
8208 g_assert_not_reached ();
8210 return &klass->byval_arg;
8214 * LOCKING: Take the corlib image lock.
8216 MonoMethodSignature*
8217 mono_create_icall_signature (const char *sigstr)
8222 MonoMethodSignature *res, *res2;
8223 MonoImage *corlib = mono_defaults.corlib;
8225 mono_image_lock (corlib);
8226 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8227 mono_image_unlock (corlib);
8232 parts = g_strsplit (sigstr, " ", 256);
8241 res = mono_metadata_signature_alloc (corlib, len - 1);
8246 * Under windows, the default pinvoke calling convention is STDCALL but
8249 res->call_convention = MONO_CALL_C;
8252 res->ret = type_from_typename (parts [0]);
8253 for (i = 1; i < len; ++i) {
8254 res->params [i - 1] = type_from_typename (parts [i]);
8259 mono_image_lock (corlib);
8260 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8262 res = res2; /*Value is allocated in the image pool*/
8264 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8265 mono_image_unlock (corlib);
8271 mono_find_jit_icall_by_name (const char *name)
8273 MonoJitICallInfo *info;
8274 g_assert (jit_icall_hash_name);
8277 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8278 mono_icall_unlock ();
8283 mono_find_jit_icall_by_addr (gconstpointer addr)
8285 MonoJitICallInfo *info;
8286 g_assert (jit_icall_hash_addr);
8289 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8290 mono_icall_unlock ();
8296 * mono_get_jit_icall_info:
8298 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8299 * caller should access it while holding the icall lock.
8302 mono_get_jit_icall_info (void)
8304 return jit_icall_hash_name;
8308 * mono_lookup_jit_icall_symbol:
8310 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8313 mono_lookup_jit_icall_symbol (const char *name)
8315 MonoJitICallInfo *info;
8316 const char *res = NULL;
8319 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8321 res = info->c_symbol;
8322 mono_icall_unlock ();
8327 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8330 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8331 mono_icall_unlock ();
8335 * 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
8336 * icalls without wrappers in some cases.
8339 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8341 MonoJitICallInfo *info;
8348 if (!jit_icall_hash_name) {
8349 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8350 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8353 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8354 g_warning ("jit icall already defined \"%s\"\n", name);
8355 g_assert_not_reached ();
8358 info = g_new0 (MonoJitICallInfo, 1);
8363 info->c_symbol = c_symbol;
8364 info->no_raise = no_raise;
8367 info->wrapper = func;
8369 info->wrapper = NULL;
8372 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8373 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8375 mono_icall_unlock ();
8380 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8382 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);