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);
1158 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1159 mono_error_raise_exception (&error);
1164 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1165 MonoReflectionMethod *method,
1166 MonoArray *opt_param_types)
1168 MONO_CHECK_ARG_NULL (method, 0);
1171 gint32 result = mono_image_create_method_token (
1172 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1173 mono_error_raise_exception (&error);
1178 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1181 mono_image_create_pefile (mb, file, &error);
1182 mono_error_raise_exception (&error);
1186 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1189 if (!mono_image_build_metadata (mb, &error))
1190 mono_error_raise_exception (&error);
1194 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1196 mono_image_register_token (mb->dynamic_image, token, obj);
1199 ICALL_EXPORT MonoObject*
1200 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1204 mono_loader_lock ();
1205 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1206 mono_loader_unlock ();
1212 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1214 MonoMethod **dest = (MonoMethod **)data;
1216 /* skip unmanaged frames */
1232 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1234 MonoMethod **dest = (MonoMethod **)data;
1236 /* skip unmanaged frames */
1241 if (!strcmp (m->klass->name_space, "System.Reflection"))
1250 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1252 MonoMethod **dest = (MonoMethod **)data;
1254 /* skip unmanaged frames */
1258 if (m->wrapper_type != MONO_WRAPPER_NONE)
1261 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1275 static MonoReflectionType *
1276 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase)
1279 MonoReflectionType *ret;
1280 MonoMethod *m, *dest;
1282 MonoType *type = NULL;
1283 MonoAssembly *assembly = NULL;
1284 gboolean type_resolve = FALSE;
1287 * We must compute the calling assembly as type loading must happen under a metadata context.
1288 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1289 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1291 m = mono_method_get_last_managed ();
1294 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1299 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1300 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1301 * to crash. This only seems to happen in some strange remoting
1302 * scenarios and I was unable to figure out what's happening there.
1303 * Dec 10, 2005 - Martin.
1307 assembly = dest->klass->image->assembly;
1308 type_resolve = TRUE;
1310 g_warning (G_STRLOC);
1313 if (info->assembly.name)
1314 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1318 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1319 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1322 if (!info->assembly.name && !type) /* try mscorlib */
1323 type = mono_reflection_get_type (NULL, info, ignoreCase, &type_resolve);
1325 if (assembly && !type && type_resolve) {
1326 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1327 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1333 ret = mono_type_get_object_checked (mono_domain_get (), type, &error);
1334 mono_error_raise_exception (&error); /* FIXME don't raise here */
1340 MonoReflectionType *
1341 mono_type_get (const char *str)
1343 char *copy = g_strdup (str);
1344 MonoTypeNameParse info;
1345 MonoReflectionType *type;
1348 parsedOk = mono_reflection_parse_type(copy, &info);
1350 mono_reflection_free_type_info (&info);
1355 type = type_from_parsed_name (&info, FALSE);
1357 mono_reflection_free_type_info (&info);
1364 ICALL_EXPORT MonoReflectionType*
1365 ves_icall_type_from_name (MonoString *name,
1366 MonoBoolean throwOnError,
1367 MonoBoolean ignoreCase)
1369 char *str = mono_string_to_utf8 (name);
1370 MonoTypeNameParse info;
1371 MonoReflectionType *type;
1374 parsedOk = mono_reflection_parse_type (str, &info);
1376 /* mono_reflection_parse_type() mangles the string */
1378 mono_reflection_free_type_info (&info);
1381 mono_set_pending_exception (mono_get_exception_argument("typeName", "failed parse"));
1386 type = type_from_parsed_name (&info, ignoreCase);
1388 mono_reflection_free_type_info (&info);
1392 MonoException *e = NULL;
1395 e = mono_get_exception_type_load (name, NULL);
1397 mono_loader_clear_error ();
1399 mono_set_pending_exception (e);
1408 ICALL_EXPORT MonoReflectionType*
1409 ves_icall_type_from_handle (MonoType *handle)
1412 MonoReflectionType *ret;
1413 MonoDomain *domain = mono_domain_get ();
1415 ret = mono_type_get_object_checked (domain, handle, &error);
1416 mono_error_raise_exception (&error);
1421 /* System.TypeCode */
1440 TYPECODE_STRING = 18
1443 ICALL_EXPORT guint32
1444 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1446 int t = type->type->type;
1448 if (type->type->byref)
1449 return TYPECODE_OBJECT;
1453 case MONO_TYPE_VOID:
1454 return TYPECODE_OBJECT;
1455 case MONO_TYPE_BOOLEAN:
1456 return TYPECODE_BOOLEAN;
1458 return TYPECODE_BYTE;
1460 return TYPECODE_SBYTE;
1462 return TYPECODE_UINT16;
1464 return TYPECODE_INT16;
1465 case MONO_TYPE_CHAR:
1466 return TYPECODE_CHAR;
1470 return TYPECODE_OBJECT;
1472 return TYPECODE_UINT32;
1474 return TYPECODE_INT32;
1476 return TYPECODE_UINT64;
1478 return TYPECODE_INT64;
1480 return TYPECODE_SINGLE;
1482 return TYPECODE_DOUBLE;
1483 case MONO_TYPE_VALUETYPE: {
1484 MonoClass *klass = type->type->data.klass;
1486 if (klass->enumtype) {
1487 t = mono_class_enum_basetype (klass)->type;
1489 } else if (mono_is_corlib_image (klass->image)) {
1490 if (strcmp (klass->name_space, "System") == 0) {
1491 if (strcmp (klass->name, "Decimal") == 0)
1492 return TYPECODE_DECIMAL;
1493 else if (strcmp (klass->name, "DateTime") == 0)
1494 return TYPECODE_DATETIME;
1497 return TYPECODE_OBJECT;
1499 case MONO_TYPE_STRING:
1500 return TYPECODE_STRING;
1501 case MONO_TYPE_SZARRAY:
1502 case MONO_TYPE_ARRAY:
1503 case MONO_TYPE_OBJECT:
1505 case MONO_TYPE_MVAR:
1506 case MONO_TYPE_TYPEDBYREF:
1507 return TYPECODE_OBJECT;
1508 case MONO_TYPE_CLASS:
1510 MonoClass *klass = type->type->data.klass;
1511 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1512 if (strcmp (klass->name, "DBNull") == 0)
1513 return TYPECODE_DBNULL;
1516 return TYPECODE_OBJECT;
1517 case MONO_TYPE_GENERICINST:
1518 return TYPECODE_OBJECT;
1520 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1526 mono_type_is_primitive (MonoType *type)
1528 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1529 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1533 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1535 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1536 return mono_class_enum_basetype (type->data.klass);
1537 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1538 return mono_class_enum_basetype (type->data.generic_class->container_class);
1542 ICALL_EXPORT guint32
1543 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1548 g_assert (type != NULL);
1550 klass = mono_class_from_mono_type (type->type);
1551 klassc = mono_class_from_mono_type (c->type);
1553 if (type->type->byref ^ c->type->byref)
1556 if (type->type->byref) {
1557 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1558 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1560 klass = mono_class_from_mono_type (t);
1561 klassc = mono_class_from_mono_type (ot);
1563 if (mono_type_is_primitive (t)) {
1564 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1565 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1566 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1567 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1568 return t->type == ot->type;
1570 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1573 if (klass->valuetype)
1574 return klass == klassc;
1575 return klass->valuetype == klassc->valuetype;
1578 return mono_class_is_assignable_from (klass, klassc);
1581 ICALL_EXPORT guint32
1582 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1584 MonoClass *klass = mono_class_from_mono_type (type->type);
1585 mono_class_init_or_throw (klass);
1586 return mono_object_isinst (obj, klass) != NULL;
1589 ICALL_EXPORT guint32
1590 ves_icall_get_attributes (MonoReflectionType *type)
1592 MonoClass *klass = mono_class_from_mono_type (type->type);
1593 return klass->flags;
1596 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1597 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1599 MonoClass *klass = field->field->parent;
1600 MonoMarshalType *info;
1604 if (klass->generic_container ||
1605 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1608 ftype = mono_field_get_type (field->field);
1609 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1612 info = mono_marshal_load_type_info (klass);
1614 for (i = 0; i < info->num_fields; ++i) {
1615 if (info->fields [i].field == field->field) {
1616 if (!info->fields [i].mspec)
1619 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1626 ICALL_EXPORT MonoReflectionField*
1627 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1630 gboolean found = FALSE;
1637 klass = handle->parent;
1639 klass = mono_class_from_mono_type (type);
1641 /* Check that the field belongs to the class */
1642 for (k = klass; k; k = k->parent) {
1643 if (k == handle->parent) {
1650 /* The managed code will throw the exception */
1654 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1655 mono_error_raise_exception (&error);
1659 ICALL_EXPORT MonoArray*
1660 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1663 MonoType *type = mono_field_get_type_checked (field->field, &error);
1664 if (!mono_error_ok (&error)) {
1665 mono_error_set_pending_exception (&error);
1669 return type_array_from_modifiers (field->field->parent->image, type, optional);
1673 vell_icall_get_method_attributes (MonoMethod *method)
1675 return method->flags;
1679 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1682 MonoReflectionType *rt;
1683 MonoDomain *domain = mono_domain_get ();
1684 MonoMethodSignature* sig;
1686 sig = mono_method_signature_checked (method, &error);
1687 if (!mono_error_ok (&error)) {
1688 mono_error_set_pending_exception (&error);
1692 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1693 if (!mono_error_ok (&error)) {
1694 mono_error_set_pending_exception (&error);
1698 MONO_STRUCT_SETREF (info, parent, rt);
1700 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1701 if (!mono_error_ok (&error)) {
1702 mono_error_set_pending_exception (&error);
1706 MONO_STRUCT_SETREF (info, ret, rt);
1708 info->attrs = method->flags;
1709 info->implattrs = method->iflags;
1710 if (sig->call_convention == MONO_CALL_DEFAULT)
1711 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1713 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1718 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1721 ICALL_EXPORT MonoArray*
1722 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1724 MonoDomain *domain = mono_domain_get ();
1726 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1729 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1730 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1732 MonoDomain *domain = mono_domain_get ();
1733 MonoReflectionMarshalAsAttribute* res = NULL;
1734 MonoMarshalSpec **mspecs;
1737 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1738 mono_method_get_marshal_info (method, mspecs);
1741 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1743 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1745 mono_metadata_free_marshal_spec (mspecs [i]);
1752 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1754 MonoClass *parent = field->field->parent;
1755 if (!parent->size_inited)
1756 mono_class_init (parent);
1757 mono_class_setup_fields_locking (parent);
1759 return field->field->offset - sizeof (MonoObject);
1762 ICALL_EXPORT MonoReflectionType*
1763 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1766 MonoReflectionType *ret;
1769 parent = declaring? field->field->parent: field->klass;
1771 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1772 mono_error_raise_exception (&error);
1778 ICALL_EXPORT MonoObject *
1779 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1781 MonoClass *fklass = field->klass;
1782 MonoClassField *cf = field->field;
1783 MonoDomain *domain = mono_object_domain (field);
1785 if (fklass->image->assembly->ref_only) {
1786 mono_set_pending_exception (mono_get_exception_invalid_operation (
1787 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1791 if (mono_security_core_clr_enabled ())
1792 mono_security_core_clr_ensure_reflection_access_field (cf);
1794 return mono_field_get_value_object (domain, cf, obj);
1798 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1801 MonoClassField *cf = field->field;
1805 if (field->klass->image->assembly->ref_only) {
1806 mono_set_pending_exception (mono_get_exception_invalid_operation (
1807 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1811 if (mono_security_core_clr_enabled ())
1812 mono_security_core_clr_ensure_reflection_access_field (cf);
1814 type = mono_field_get_type_checked (cf, &error);
1815 if (!mono_error_ok (&error)) {
1816 mono_error_set_pending_exception (&error);
1820 v = (gchar *) value;
1822 switch (type->type) {
1825 case MONO_TYPE_BOOLEAN:
1828 case MONO_TYPE_CHAR:
1837 case MONO_TYPE_VALUETYPE:
1840 v += sizeof (MonoObject);
1842 case MONO_TYPE_STRING:
1843 case MONO_TYPE_OBJECT:
1844 case MONO_TYPE_CLASS:
1845 case MONO_TYPE_ARRAY:
1846 case MONO_TYPE_SZARRAY:
1849 case MONO_TYPE_GENERICINST: {
1850 MonoGenericClass *gclass = type->data.generic_class;
1851 g_assert (!gclass->context.class_inst->is_open);
1853 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1854 MonoClass *nklass = mono_class_from_mono_type (type);
1855 MonoObject *nullable;
1858 * Convert the boxed vtype into a Nullable structure.
1859 * This is complicated by the fact that Nullables have
1860 * a variable structure.
1862 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1863 if (!mono_error_ok (&error)) {
1864 mono_error_set_pending_exception (&error);
1868 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1870 v = (gchar *)mono_object_unbox (nullable);
1873 if (gclass->container_class->valuetype && (v != NULL))
1874 v += sizeof (MonoObject);
1878 g_error ("type 0x%x not handled in "
1879 "ves_icall_FieldInfo_SetValueInternal", type->type);
1884 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1885 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1886 if (!vtable->initialized)
1887 mono_runtime_class_init (vtable);
1888 mono_field_static_set_value (vtable, cf, v);
1890 mono_field_set_value (obj, cf, v);
1895 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1904 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1905 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1909 if (MONO_TYPE_IS_REFERENCE (f->type))
1910 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1912 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1915 ICALL_EXPORT MonoObject *
1916 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1918 MonoObject *o = NULL;
1919 MonoClassField *field = rfield->field;
1921 MonoDomain *domain = mono_object_domain (rfield);
1923 MonoTypeEnum def_type;
1924 const char *def_value;
1928 mono_class_init (field->parent);
1930 t = mono_field_get_type_checked (field, &error);
1931 if (!mono_error_ok (&error)) {
1932 mono_error_set_pending_exception (&error);
1936 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
1937 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1941 if (image_is_dynamic (field->parent->image)) {
1942 MonoClass *klass = field->parent;
1943 int fidx = field - klass->fields;
1945 g_assert (fidx >= 0 && fidx < klass->field.count);
1946 g_assert (klass->ext);
1947 g_assert (klass->ext->field_def_values);
1948 def_type = klass->ext->field_def_values [fidx].def_type;
1949 def_value = klass->ext->field_def_values [fidx].data;
1950 if (def_type == MONO_TYPE_END) {
1951 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1955 def_value = mono_class_get_field_default_value (field, &def_type);
1956 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
1958 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1963 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1967 case MONO_TYPE_BOOLEAN:
1970 case MONO_TYPE_CHAR:
1978 case MONO_TYPE_R8: {
1981 /* boxed value type */
1982 t = g_new0 (MonoType, 1);
1984 klass = mono_class_from_mono_type (t);
1986 o = mono_object_new_checked (domain, klass, &error);
1987 if (!mono_error_ok (&error)) {
1988 mono_error_set_pending_exception (&error);
1991 v = ((gchar *) o) + sizeof (MonoObject);
1992 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1995 case MONO_TYPE_STRING:
1996 case MONO_TYPE_CLASS:
1997 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2000 g_assert_not_reached ();
2006 ICALL_EXPORT MonoReflectionType*
2007 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2010 MonoReflectionType *ret;
2013 type = mono_field_get_type_checked (ref_field->field, &error);
2014 if (!mono_error_ok (&error)) {
2015 mono_error_set_pending_exception (&error);
2019 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2020 if (!mono_error_ok (&error)) {
2021 mono_error_set_pending_exception (&error);
2028 /* From MonoProperty.cs */
2030 PInfo_Attributes = 1,
2031 PInfo_GetMethod = 1 << 1,
2032 PInfo_SetMethod = 1 << 2,
2033 PInfo_ReflectedType = 1 << 3,
2034 PInfo_DeclaringType = 1 << 4,
2039 ves_icall_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2042 MonoReflectionType *rt;
2043 MonoReflectionMethod *rm;
2044 MonoDomain *domain = mono_object_domain (property);
2045 const MonoProperty *pproperty = property->property;
2047 if ((req_info & PInfo_ReflectedType) != 0) {
2048 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2049 mono_error_raise_exception (&error);
2051 MONO_STRUCT_SETREF (info, parent, rt);
2053 if ((req_info & PInfo_DeclaringType) != 0) {
2054 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2055 mono_error_raise_exception (&error);
2057 MONO_STRUCT_SETREF (info, declaring_type, rt);
2060 if ((req_info & PInfo_Name) != 0)
2061 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2063 if ((req_info & PInfo_Attributes) != 0)
2064 info->attrs = pproperty->attrs;
2066 if ((req_info & PInfo_GetMethod) != 0) {
2067 if (pproperty->get &&
2068 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2069 pproperty->get->klass == property->klass)) {
2070 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2071 mono_error_raise_exception (&error);
2076 MONO_STRUCT_SETREF (info, get, rm);
2078 if ((req_info & PInfo_SetMethod) != 0) {
2079 if (pproperty->set &&
2080 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2081 pproperty->set->klass == property->klass)) {
2082 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2083 mono_error_raise_exception (&error);
2088 MONO_STRUCT_SETREF (info, set, rm);
2091 * There may be other methods defined for properties, though, it seems they are not exposed
2092 * in the reflection API
2097 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2100 MonoReflectionType *rt;
2101 MonoReflectionMethod *rm;
2102 MonoDomain *domain = mono_object_domain (event);
2104 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2105 mono_error_raise_exception (&error);
2107 MONO_STRUCT_SETREF (info, reflected_type, rt);
2109 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2110 mono_error_raise_exception (&error);
2112 MONO_STRUCT_SETREF (info, declaring_type, rt);
2114 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2115 info->attrs = event->event->attrs;
2117 if (event->event->add) {
2118 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2119 mono_error_raise_exception (&error);
2124 MONO_STRUCT_SETREF (info, add_method, rm);
2126 if (event->event->remove) {
2127 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2128 mono_error_raise_exception (&error);
2133 MONO_STRUCT_SETREF (info, remove_method, rm);
2135 if (event->event->raise) {
2136 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2137 mono_error_raise_exception (&error);
2142 MONO_STRUCT_SETREF (info, raise_method, rm);
2144 #ifndef MONO_SMALL_CONFIG
2145 if (event->event->other) {
2147 while (event->event->other [n])
2149 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2151 for (i = 0; i < n; i++) {
2152 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2153 mono_error_raise_exception (&error);
2154 mono_array_setref (info->other_methods, i, rm);
2161 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2166 mono_class_setup_interfaces (klass, error);
2167 if (!mono_error_ok (error))
2170 for (i = 0; i < klass->interface_count; i++) {
2171 ic = klass->interfaces [i];
2172 g_hash_table_insert (ifaces, ic, ic);
2174 collect_interfaces (ic, ifaces, error);
2175 if (!mono_error_ok (error))
2181 MonoArray *iface_array;
2182 MonoGenericContext *context;
2186 } FillIfaceArrayData;
2189 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2191 MonoReflectionType *rt;
2192 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2193 MonoClass *ic = (MonoClass *)key;
2194 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2196 if (!mono_error_ok (data->error))
2199 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2200 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2201 if (!mono_error_ok (data->error))
2205 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2206 if (!mono_error_ok (data->error))
2209 mono_array_setref (data->iface_array, data->next_idx++, rt);
2212 mono_metadata_free_type (inflated);
2216 get_interfaces_hash (gconstpointer v1)
2218 MonoClass *k = (MonoClass*)v1;
2220 return k->type_token;
2223 ICALL_EXPORT MonoArray*
2224 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2227 MonoClass *klass = mono_class_from_mono_type (type->type);
2229 FillIfaceArrayData data = { 0 };
2232 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2234 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2235 data.context = mono_class_get_context (klass);
2236 klass = klass->generic_class->container_class;
2239 for (parent = klass; parent; parent = parent->parent) {
2240 mono_class_setup_interfaces (parent, &error);
2241 if (!mono_error_ok (&error))
2243 collect_interfaces (parent, iface_hash, &error);
2244 if (!mono_error_ok (&error))
2248 data.error = &error;
2249 data.domain = mono_object_domain (type);
2251 len = g_hash_table_size (iface_hash);
2253 g_hash_table_destroy (iface_hash);
2254 if (!data.domain->empty_types)
2255 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2256 return data.domain->empty_types;
2259 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2260 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2261 if (!mono_error_ok (&error))
2264 g_hash_table_destroy (iface_hash);
2265 return data.iface_array;
2268 g_hash_table_destroy (iface_hash);
2269 mono_error_set_pending_exception (&error);
2274 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2276 gboolean variance_used;
2277 MonoClass *klass = mono_class_from_mono_type (type->type);
2278 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2279 MonoReflectionMethod *member;
2282 int i = 0, len, ioffset;
2286 mono_class_init_or_throw (klass);
2287 mono_class_init_or_throw (iclass);
2289 mono_class_setup_vtable (klass);
2291 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2295 len = mono_class_num_methods (iclass);
2296 domain = mono_object_domain (type);
2297 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2298 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2300 while ((method = mono_class_get_methods (iclass, &iter))) {
2301 member = mono_method_get_object_checked (domain, method, iclass, &error);
2302 mono_error_raise_exception (&error);
2303 mono_array_setref (*methods, i, member);
2304 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2305 mono_error_raise_exception (&error);
2306 mono_array_setref (*targets, i, member);
2313 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2315 MonoClass *klass = mono_class_from_mono_type (type->type);
2316 mono_class_init_or_throw (klass);
2318 if (image_is_dynamic (klass->image)) {
2319 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2320 *packing = tb->packing_size;
2321 *size = tb->class_size;
2323 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2327 ICALL_EXPORT MonoReflectionType*
2328 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2331 MonoReflectionType *ret;
2334 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2335 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2336 mono_error_raise_exception (&error);
2341 klass = mono_class_from_mono_type (type->type);
2342 mono_class_init_or_throw (klass);
2344 // GetElementType should only return a type for:
2345 // Array Pointer PassedByRef
2346 if (type->type->byref)
2347 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2348 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2349 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2350 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2351 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2355 mono_error_raise_exception (&error);
2360 ICALL_EXPORT MonoReflectionType*
2361 ves_icall_get_type_parent (MonoReflectionType *type)
2364 MonoReflectionType *ret;
2366 if (type->type->byref)
2369 MonoClass *klass = mono_class_from_mono_type (type->type);
2373 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2374 mono_error_raise_exception (&error);
2379 ICALL_EXPORT MonoBoolean
2380 ves_icall_type_ispointer (MonoReflectionType *type)
2382 return type->type->type == MONO_TYPE_PTR;
2385 ICALL_EXPORT MonoBoolean
2386 ves_icall_type_isprimitive (MonoReflectionType *type)
2388 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)));
2391 ICALL_EXPORT MonoBoolean
2392 ves_icall_type_isbyref (MonoReflectionType *type)
2394 return type->type->byref;
2397 ICALL_EXPORT MonoBoolean
2398 ves_icall_type_iscomobject (MonoReflectionType *type)
2400 MonoClass *klass = mono_class_from_mono_type (type->type);
2401 mono_class_init_or_throw (klass);
2403 return mono_class_is_com_object (klass);
2406 ICALL_EXPORT MonoReflectionModule*
2407 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2409 MonoClass *klass = mono_class_from_mono_type (type->type);
2410 return mono_module_get_object (mono_object_domain (type), klass->image);
2413 ICALL_EXPORT MonoReflectionAssembly*
2414 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2416 MonoDomain *domain = mono_domain_get ();
2417 MonoClass *klass = mono_class_from_mono_type (type->type);
2418 return mono_assembly_get_object (domain, klass->image->assembly);
2421 ICALL_EXPORT MonoReflectionType*
2422 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2425 MonoReflectionType *ret;
2426 MonoDomain *domain = mono_domain_get ();
2429 if (type->type->byref)
2431 if (type->type->type == MONO_TYPE_VAR) {
2432 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2433 klass = param ? param->owner.klass : NULL;
2434 } else if (type->type->type == MONO_TYPE_MVAR) {
2435 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2436 klass = param ? param->owner.method->klass : NULL;
2438 klass = mono_class_from_mono_type (type->type)->nested_in;
2444 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2445 mono_error_raise_exception (&error);
2450 ICALL_EXPORT MonoString*
2451 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2453 MonoDomain *domain = mono_domain_get ();
2454 MonoClass *klass = mono_class_from_mono_type (type->type);
2456 if (type->type->byref) {
2457 char *n = g_strdup_printf ("%s&", klass->name);
2458 MonoString *res = mono_string_new (domain, n);
2464 return mono_string_new (domain, klass->name);
2468 ICALL_EXPORT MonoString*
2469 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2471 MonoDomain *domain = mono_domain_get ();
2472 MonoClass *klass = mono_class_from_mono_type (type->type);
2474 while (klass->nested_in)
2475 klass = klass->nested_in;
2477 if (klass->name_space [0] == '\0')
2480 return mono_string_new (domain, klass->name_space);
2484 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2488 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2489 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2493 klass = mono_class_from_mono_type (type->type);
2499 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2502 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2506 ICALL_EXPORT MonoArray*
2507 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2510 MonoReflectionType *rt;
2512 MonoClass *klass, *pklass;
2513 MonoDomain *domain = mono_object_domain (type);
2516 klass = mono_class_from_mono_type (type->type);
2518 if (klass->generic_container) {
2519 MonoGenericContainer *container = klass->generic_container;
2520 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2521 for (i = 0; i < container->type_argc; ++i) {
2522 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2524 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2525 mono_error_raise_exception (&error);
2527 mono_array_setref (res, i, rt);
2529 } else if (klass->generic_class) {
2530 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2531 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2532 for (i = 0; i < inst->type_argc; ++i) {
2533 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2534 mono_error_raise_exception (&error);
2536 mono_array_setref (res, i, rt);
2544 ICALL_EXPORT gboolean
2545 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2549 if (!IS_MONOTYPE (type))
2552 if (type->type->byref)
2555 klass = mono_class_from_mono_type (type->type);
2556 return klass->generic_container != NULL;
2559 ICALL_EXPORT MonoReflectionType*
2560 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2563 MonoReflectionType *ret;
2566 if (type->type->byref)
2569 klass = mono_class_from_mono_type (type->type);
2571 if (klass->generic_container) {
2572 return type; /* check this one */
2574 if (klass->generic_class) {
2575 MonoClass *generic_class = klass->generic_class->container_class;
2578 tb = mono_class_get_ref_info (generic_class);
2580 if (generic_class->wastypebuilder && tb)
2581 return (MonoReflectionType *)tb;
2583 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2584 mono_error_raise_exception (&error);
2592 ICALL_EXPORT MonoReflectionType*
2593 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2596 MonoReflectionType *ret;
2598 MonoType *geninst, **types;
2601 g_assert (IS_MONOTYPE (type));
2602 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2604 count = mono_array_length (type_array);
2605 types = g_new0 (MonoType *, count);
2607 for (i = 0; i < count; i++) {
2608 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2609 types [i] = t->type;
2612 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2617 klass = mono_class_from_mono_type (geninst);
2619 /*we might inflate to the GTD*/
2620 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2621 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2625 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2626 mono_error_raise_exception (&error);
2631 ICALL_EXPORT gboolean
2632 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2636 if (!IS_MONOTYPE (type))
2639 if (type->type->byref)
2642 klass = mono_class_from_mono_type (type->type);
2643 return klass->generic_class != NULL || klass->generic_container != NULL;
2647 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2649 if (!IS_MONOTYPE (type))
2652 if (is_generic_parameter (type->type))
2653 return mono_type_get_generic_param_num (type->type);
2657 ICALL_EXPORT GenericParameterAttributes
2658 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2660 g_assert (IS_MONOTYPE (type));
2661 g_assert (is_generic_parameter (type->type));
2662 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2665 ICALL_EXPORT MonoArray *
2666 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2669 MonoReflectionType *rt;
2670 MonoGenericParamInfo *param_info;
2676 g_assert (IS_MONOTYPE (type));
2678 domain = mono_object_domain (type);
2679 param_info = mono_generic_param_info (type->type->data.generic_param);
2680 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2683 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2684 for (i = 0; i < count; i++) {
2685 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2686 mono_error_raise_exception (&error);
2688 mono_array_setref (res, i, rt);
2695 ICALL_EXPORT MonoBoolean
2696 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2698 return is_generic_parameter (type->type);
2701 ICALL_EXPORT MonoBoolean
2702 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2704 return is_generic_parameter (tb->type.type);
2708 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2709 MonoReflectionType *t)
2711 enumtype->type = t->type;
2714 ICALL_EXPORT MonoReflectionMethod*
2715 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2716 MonoReflectionMethod* generic)
2723 MonoReflectionMethod *ret = NULL;
2725 domain = ((MonoObject *)type)->vtable->domain;
2727 klass = mono_class_from_mono_type (type->type);
2728 mono_class_init_or_throw (klass);
2731 while ((method = mono_class_get_methods (klass, &iter))) {
2732 if (method->token == generic->method->token) {
2733 ret = mono_method_get_object_checked (domain, method, klass, &error);
2734 mono_error_raise_exception (&error);
2741 ICALL_EXPORT MonoReflectionMethod *
2742 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2745 MonoType *type = ref_type->type;
2747 MonoReflectionMethod *ret = NULL;
2749 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2750 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2753 if (type->type == MONO_TYPE_VAR)
2756 method = mono_type_get_generic_param_owner (type)->owner.method;
2759 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2760 if (!mono_error_ok (&error))
2761 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2765 ICALL_EXPORT MonoBoolean
2766 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2768 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2772 ICALL_EXPORT MonoBoolean
2773 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2775 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2780 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2782 MonoDomain *domain = mono_domain_get ();
2783 MonoImage *image = method->method->klass->image;
2784 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2785 MonoTableInfo *tables = image->tables;
2786 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2787 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2788 guint32 im_cols [MONO_IMPLMAP_SIZE];
2789 guint32 scope_token;
2790 const char *import = NULL;
2791 const char *scope = NULL;
2793 if (image_is_dynamic (image)) {
2794 MonoReflectionMethodAux *method_aux =
2795 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2797 import = method_aux->dllentry;
2798 scope = method_aux->dll;
2801 if (!import || !scope) {
2802 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2807 if (piinfo->implmap_idx) {
2808 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2810 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2811 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2812 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2813 scope = mono_metadata_string_heap (image, scope_token);
2817 *flags = piinfo->piflags;
2818 *entry_point = mono_string_new (domain, import);
2819 *dll_name = mono_string_new (domain, scope);
2822 ICALL_EXPORT MonoReflectionMethod *
2823 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2825 MonoMethodInflated *imethod;
2827 MonoReflectionMethod *ret = NULL;
2830 if (method->method->is_generic)
2833 if (!method->method->is_inflated)
2836 imethod = (MonoMethodInflated *) method->method;
2838 result = imethod->declaring;
2839 /* Not a generic method. */
2840 if (!result->is_generic)
2843 if (image_is_dynamic (method->method->klass->image)) {
2844 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2845 MonoReflectionMethod *res;
2848 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2849 * the dynamic case as well ?
2851 mono_image_lock ((MonoImage*)image);
2852 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2853 mono_image_unlock ((MonoImage*)image);
2859 if (imethod->context.class_inst) {
2860 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2861 /*Generic methods gets the context of the GTD.*/
2862 if (mono_class_get_context (klass)) {
2863 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2864 if (!mono_error_ok (&error))
2869 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2871 if (!mono_error_ok (&error))
2872 mono_error_set_pending_exception (&error);
2876 ICALL_EXPORT gboolean
2877 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2879 return mono_method_signature (method->method)->generic_param_count != 0;
2882 ICALL_EXPORT gboolean
2883 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2885 return method->method->is_generic;
2888 ICALL_EXPORT MonoArray*
2889 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2892 MonoReflectionType *rt;
2897 domain = mono_object_domain (method);
2899 if (method->method->is_inflated) {
2900 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2903 count = inst->type_argc;
2904 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2906 for (i = 0; i < count; i++) {
2907 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2908 mono_error_raise_exception (&error);
2910 mono_array_setref (res, i, rt);
2917 count = mono_method_signature (method->method)->generic_param_count;
2918 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2920 for (i = 0; i < count; i++) {
2921 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2922 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2923 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
2925 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2926 mono_error_raise_exception (&error);
2928 mono_array_setref (res, i, rt);
2934 ICALL_EXPORT MonoObject *
2935 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
2939 * Invoke from reflection is supposed to always be a virtual call (the API
2940 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2941 * greater flexibility.
2943 MonoMethod *m = method->method;
2944 MonoMethodSignature *sig = mono_method_signature (m);
2947 void *obj = this_arg;
2951 if (mono_security_core_clr_enabled ())
2952 mono_security_core_clr_ensure_reflection_access_method (m);
2954 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2955 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2956 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2961 if (!mono_object_isinst (this_arg, m->klass)) {
2962 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
2963 char *target_name = mono_type_get_full_name (m->klass);
2964 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2965 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2967 g_free (target_name);
2971 m = mono_object_get_virtual_method (this_arg, m);
2972 /* must pass the pointer to the value for valuetype methods */
2973 if (m->klass->valuetype)
2974 obj = mono_object_unbox (this_arg);
2975 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2976 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2981 if (sig->ret->byref) {
2982 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"));
2986 pcount = params? mono_array_length (params): 0;
2987 if (pcount != sig->param_count) {
2988 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2992 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
2993 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."));
2997 image = m->klass->image;
2998 if (image->assembly->ref_only) {
2999 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."));
3003 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3004 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3008 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3012 intptr_t *lower_bounds;
3013 pcount = mono_array_length (params);
3014 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3015 /* Note: the synthetized array .ctors have int32 as argument type */
3016 for (i = 0; i < pcount; ++i)
3017 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3019 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3020 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3021 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3022 if (!mono_error_ok (&error)) {
3023 mono_error_set_pending_exception (&error);
3027 for (i = 0; i < mono_array_length (arr); ++i) {
3028 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3029 if (!mono_error_ok (&error)) {
3030 mono_error_set_pending_exception (&error);
3033 mono_array_setref_fast (arr, i, subarray);
3035 return (MonoObject*)arr;
3038 if (m->klass->rank == pcount) {
3039 /* Only lengths provided. */
3040 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3041 if (!mono_error_ok (&error)) {
3042 mono_error_set_pending_exception (&error);
3046 return (MonoObject*)arr;
3048 g_assert (pcount == (m->klass->rank * 2));
3049 /* The arguments are lower-bound-length pairs */
3050 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3052 for (i = 0; i < pcount / 2; ++i) {
3053 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3054 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3057 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3058 if (!mono_error_ok (&error)) {
3059 mono_error_set_pending_exception (&error);
3063 return (MonoObject*)arr;
3066 return mono_runtime_invoke_array (m, obj, params, NULL);
3069 #ifndef DISABLE_REMOTING
3070 ICALL_EXPORT MonoObject *
3071 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3073 MonoDomain *domain = mono_object_domain (method);
3074 MonoMethod *m = method->method;
3075 MonoMethodSignature *sig = mono_method_signature (m);
3076 MonoArray *out_args;
3078 int i, j, outarg_count = 0;
3080 if (m->klass == mono_defaults.object_class) {
3081 if (!strcmp (m->name, "FieldGetter")) {
3082 MonoClass *k = this_arg->vtable->klass;
3086 /* If this is a proxy, then it must be a CBO */
3087 if (k == mono_defaults.transparent_proxy_class) {
3088 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3089 this_arg = tp->rp->unwrapped_server;
3090 g_assert (this_arg);
3091 k = this_arg->vtable->klass;
3094 name = mono_array_get (params, MonoString *, 1);
3095 str = mono_string_to_utf8 (name);
3098 MonoClassField* field = mono_class_get_field_from_name (k, str);
3100 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3101 if (field_klass->valuetype)
3102 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
3104 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3106 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3107 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3108 mono_array_setref (out_args, 0, result);
3116 g_assert_not_reached ();
3118 } else if (!strcmp (m->name, "FieldSetter")) {
3119 MonoClass *k = this_arg->vtable->klass;
3125 /* If this is a proxy, then it must be a CBO */
3126 if (k == mono_defaults.transparent_proxy_class) {
3127 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3128 this_arg = tp->rp->unwrapped_server;
3129 g_assert (this_arg);
3130 k = this_arg->vtable->klass;
3133 name = mono_array_get (params, MonoString *, 1);
3134 str = mono_string_to_utf8 (name);
3137 MonoClassField* field = mono_class_get_field_from_name (k, str);
3139 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3140 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3142 if (field_klass->valuetype) {
3143 size = mono_type_size (field->type, &align);
3144 g_assert (size == mono_class_value_size (field_klass, NULL));
3145 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3147 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3150 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3151 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3161 g_assert_not_reached ();
3166 for (i = 0; i < mono_array_length (params); i++) {
3167 if (sig->params [i]->byref)
3171 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3173 /* handle constructors only for objects already allocated */
3174 if (!strcmp (method->method->name, ".ctor"))
3175 g_assert (this_arg);
3177 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3178 g_assert (!method->method->klass->valuetype);
3179 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3181 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3182 if (sig->params [i]->byref) {
3184 arg = mono_array_get (params, gpointer, i);
3185 mono_array_setref (out_args, j, arg);
3190 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3197 read_enum_value (const char *mem, int type)
3200 case MONO_TYPE_BOOLEAN:
3202 return *(guint8*)mem;
3204 return *(gint8*)mem;
3205 case MONO_TYPE_CHAR:
3207 return read16 (mem);
3209 return (gint16) read16 (mem);
3211 return read32 (mem);
3213 return (gint32) read32 (mem);
3216 return read64 (mem);
3218 g_assert_not_reached ();
3224 write_enum_value (char *mem, int type, guint64 value)
3228 case MONO_TYPE_I1: {
3229 guint8 *p = (guint8*)mem;
3234 case MONO_TYPE_I2: {
3235 guint16 *p = (guint16 *)mem;
3240 case MONO_TYPE_I4: {
3241 guint32 *p = (guint32 *)mem;
3246 case MONO_TYPE_I8: {
3247 guint64 *p = (guint64 *)mem;
3252 g_assert_not_reached ();
3257 ICALL_EXPORT MonoObject *
3258 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3266 domain = mono_object_domain (enumType);
3267 enumc = mono_class_from_mono_type (enumType->type);
3269 mono_class_init_or_throw (enumc);
3271 etype = mono_class_enum_basetype (enumc);
3273 res = mono_object_new_checked (domain, enumc, &error);
3274 mono_error_raise_exception (&error);
3275 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3280 ICALL_EXPORT MonoBoolean
3281 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3283 int size = mono_class_value_size (a->vtable->klass, NULL);
3284 guint64 a_val = 0, b_val = 0;
3286 memcpy (&a_val, mono_object_unbox (a), size);
3287 memcpy (&b_val, mono_object_unbox (b), size);
3289 return (a_val & b_val) == b_val;
3292 ICALL_EXPORT MonoObject *
3293 ves_icall_System_Enum_get_value (MonoObject *eobj)
3305 g_assert (eobj->vtable->klass->enumtype);
3307 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3308 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3309 mono_error_raise_exception (&error);
3310 dst = (char *)res + sizeof (MonoObject);
3311 src = (char *)eobj + sizeof (MonoObject);
3312 size = mono_class_value_size (enumc, NULL);
3314 memcpy (dst, src, size);
3319 ICALL_EXPORT MonoReflectionType *
3320 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3323 MonoReflectionType *ret;
3327 klass = mono_class_from_mono_type (type->type);
3328 mono_class_init_or_throw (klass);
3330 etype = mono_class_enum_basetype (klass);
3332 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3336 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3337 mono_error_raise_exception (&error);
3343 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3345 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3346 gpointer odata = (char *)other + sizeof (MonoObject);
3347 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3348 g_assert (basetype);
3353 if (eobj->vtable->klass != other->vtable->klass)
3356 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3357 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3358 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3361 return me > other ? 1 : -1; \
3364 switch (basetype->type) {
3366 COMPARE_ENUM_VALUES (guint8);
3368 COMPARE_ENUM_VALUES (gint8);
3369 case MONO_TYPE_CHAR:
3371 COMPARE_ENUM_VALUES (guint16);
3373 COMPARE_ENUM_VALUES (gint16);
3375 COMPARE_ENUM_VALUES (guint32);
3377 COMPARE_ENUM_VALUES (gint32);
3379 COMPARE_ENUM_VALUES (guint64);
3381 COMPARE_ENUM_VALUES (gint64);
3385 #undef COMPARE_ENUM_VALUES
3386 /* indicates that the enum was of an unsupported unerlying type */
3391 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3393 gpointer data = (char *)eobj + sizeof (MonoObject);
3394 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3395 g_assert (basetype);
3397 switch (basetype->type) {
3398 case MONO_TYPE_I1: {
3399 gint8 value = *((gint8*)data);
3400 return ((int)value ^ (int)value << 8);
3403 return *((guint8*)data);
3404 case MONO_TYPE_CHAR:
3406 return *((guint16*)data);
3408 case MONO_TYPE_I2: {
3409 gint16 value = *((gint16*)data);
3410 return ((int)(guint16)value | (((int)value) << 16));
3413 return *((guint32*)data);
3415 return *((gint32*)data);
3417 case MONO_TYPE_I8: {
3418 gint64 value = *((gint64*)data);
3419 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3422 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3427 ICALL_EXPORT MonoBoolean
3428 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3430 MonoDomain *domain = mono_object_domain (type);
3431 MonoClass *enumc = mono_class_from_mono_type (type->type);
3432 guint j = 0, nvalues;
3434 MonoClassField *field;
3436 guint64 field_value, previous_value = 0;
3437 gboolean sorted = TRUE;
3439 mono_class_init_or_throw (enumc);
3441 if (!enumc->enumtype) {
3442 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3446 base_type = mono_class_enum_basetype (enumc)->type;
3448 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3449 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3450 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3453 while ((field = mono_class_get_fields (enumc, &iter))) {
3455 MonoTypeEnum def_type;
3457 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3459 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3461 if (mono_field_is_deleted (field))
3463 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3465 p = mono_class_get_field_default_value (field, &def_type);
3466 /* len = */ mono_metadata_decode_blob_size (p, &p);
3468 field_value = read_enum_value (p, base_type);
3469 mono_array_set (*values, guint64, j, field_value);
3471 if (previous_value > field_value)
3474 previous_value = field_value;
3482 BFLAGS_IgnoreCase = 1,
3483 BFLAGS_DeclaredOnly = 2,
3484 BFLAGS_Instance = 4,
3486 BFLAGS_Public = 0x10,
3487 BFLAGS_NonPublic = 0x20,
3488 BFLAGS_FlattenHierarchy = 0x40,
3489 BFLAGS_InvokeMethod = 0x100,
3490 BFLAGS_CreateInstance = 0x200,
3491 BFLAGS_GetField = 0x400,
3492 BFLAGS_SetField = 0x800,
3493 BFLAGS_GetProperty = 0x1000,
3494 BFLAGS_SetProperty = 0x2000,
3495 BFLAGS_ExactBinding = 0x10000,
3496 BFLAGS_SuppressChangeType = 0x20000,
3497 BFLAGS_OptionalParamBinding = 0x40000
3500 ICALL_EXPORT MonoArray*
3501 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3505 MonoClass *startklass, *klass, *refklass;
3510 char *utf8_name = NULL;
3511 int (*compare_func) (const char *s1, const char *s2) = NULL;
3512 MonoClassField *field;
3513 MonoPtrArray tmp_array;
3515 domain = ((MonoObject *)type)->vtable->domain;
3516 if (type->type->byref)
3517 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3519 klass = startklass = mono_class_from_mono_type (type->type);
3520 refklass = mono_class_from_mono_type (reftype->type);
3522 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3525 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3526 mono_ptr_array_destroy (tmp_array);
3527 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3532 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3533 guint32 flags = mono_field_get_flags (field);
3535 if (mono_field_is_deleted_with_flags (field, flags))
3537 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3538 if (bflags & BFLAGS_Public)
3540 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3541 if (bflags & BFLAGS_NonPublic) {
3548 if (flags & FIELD_ATTRIBUTE_STATIC) {
3549 if (bflags & BFLAGS_Static)
3550 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3553 if (bflags & BFLAGS_Instance)
3561 if (utf8_name == NULL) {
3562 utf8_name = mono_string_to_utf8 (name);
3563 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3566 if (compare_func (mono_field_get_name (field), utf8_name))
3570 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3571 if (!mono_error_ok (&error))
3573 mono_ptr_array_append (tmp_array, member);
3575 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3578 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3580 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3581 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3583 mono_ptr_array_destroy (tmp_array);
3585 if (utf8_name != NULL)
3590 mono_ptr_array_destroy (tmp_array);
3591 mono_error_raise_exception (&error);
3592 g_assert_not_reached ();
3596 method_nonpublic (MonoMethod* method, gboolean start_klass)
3598 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3599 case METHOD_ATTRIBUTE_ASSEM:
3600 return (start_klass || mono_defaults.generic_ilist_class);
3601 case METHOD_ATTRIBUTE_PRIVATE:
3603 case METHOD_ATTRIBUTE_PUBLIC:
3611 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3614 MonoClass *startklass;
3618 /*FIXME, use MonoBitSet*/
3619 guint32 method_slots_default [8];
3620 guint32 *method_slots = NULL;
3621 int (*compare_func) (const char *s1, const char *s2) = NULL;
3623 array = g_ptr_array_new ();
3628 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3630 /* An optimization for calls made from Delegate:CreateDelegate () */
3631 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3632 method = mono_get_delegate_invoke (klass);
3633 if (mono_loader_get_last_error ())
3636 g_ptr_array_add (array, method);
3640 mono_class_setup_methods (klass);
3641 mono_class_setup_vtable (klass);
3642 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3645 if (is_generic_parameter (&klass->byval_arg))
3646 nslots = mono_class_get_vtable_size (klass->parent);
3648 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3649 if (nslots >= sizeof (method_slots_default) * 8) {
3650 method_slots = g_new0 (guint32, nslots / 32 + 1);
3652 method_slots = method_slots_default;
3653 memset (method_slots, 0, sizeof (method_slots_default));
3656 mono_class_setup_methods (klass);
3657 mono_class_setup_vtable (klass);
3658 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3662 while ((method = mono_class_get_methods (klass, &iter))) {
3664 if (method->slot != -1) {
3665 g_assert (method->slot < nslots);
3666 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3668 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3669 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3672 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3674 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3675 if (bflags & BFLAGS_Public)
3677 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3683 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3684 if (bflags & BFLAGS_Static)
3685 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3688 if (bflags & BFLAGS_Instance)
3696 if (compare_func (name, method->name))
3701 g_ptr_array_add (array, method);
3703 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3705 if (method_slots != method_slots_default)
3706 g_free (method_slots);
3711 if (method_slots != method_slots_default)
3712 g_free (method_slots);
3713 g_ptr_array_free (array, TRUE);
3715 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3716 *ex = mono_class_get_exception_for_failure (klass);
3718 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3719 mono_loader_clear_error ();
3724 ICALL_EXPORT MonoArray*
3725 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3727 static MonoClass *MethodInfo_array;
3731 MonoVTable *array_vtable;
3732 MonoException *ex = NULL;
3733 const char *mname = NULL;
3734 GPtrArray *method_array;
3735 MonoClass *klass, *refklass;
3738 mono_error_init (&error);
3740 if (!MethodInfo_array) {
3741 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3742 mono_memory_barrier ();
3743 MethodInfo_array = klass;
3746 klass = mono_class_from_mono_type (type->type);
3747 refklass = mono_class_from_mono_type (reftype->type);
3748 domain = ((MonoObject *)type)->vtable->domain;
3749 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3750 if (type->type->byref) {
3751 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3752 mono_error_set_pending_exception (&error);
3758 mname = mono_string_to_utf8 (name);
3760 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3761 g_free ((char*)mname);
3763 mono_set_pending_exception (ex);
3767 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3768 if (!mono_error_ok (&error)) {
3769 mono_error_set_pending_exception (&error);
3773 for (i = 0; i < method_array->len; ++i) {
3774 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3775 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3776 if (!mono_error_ok (&error))
3778 mono_array_setref (res, i, rm);
3782 g_ptr_array_free (method_array, TRUE);
3783 if (!mono_error_ok (&error))
3784 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3788 ICALL_EXPORT MonoArray*
3789 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3792 static MonoClass *System_Reflection_ConstructorInfo;
3793 MonoClass *startklass, *klass, *refklass;
3798 gpointer iter = NULL;
3799 MonoPtrArray tmp_array;
3802 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3804 domain = ((MonoObject *)type)->vtable->domain;
3805 if (type->type->byref)
3806 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3807 klass = startklass = mono_class_from_mono_type (type->type);
3808 refklass = mono_class_from_mono_type (reftype->type);
3810 if (!System_Reflection_ConstructorInfo)
3811 System_Reflection_ConstructorInfo = mono_class_from_name (
3812 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3814 mono_class_setup_methods (klass);
3815 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3816 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3821 while ((method = mono_class_get_methods (klass, &iter))) {
3823 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3825 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3826 if (bflags & BFLAGS_Public)
3829 if (bflags & BFLAGS_NonPublic)
3835 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3836 if (bflags & BFLAGS_Static)
3837 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3840 if (bflags & BFLAGS_Instance)
3846 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3847 if (!mono_error_ok (&error)) {
3848 mono_error_set_pending_exception (&error);
3852 mono_ptr_array_append (tmp_array, member);
3855 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3857 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3858 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3860 mono_ptr_array_destroy (tmp_array);
3866 property_hash (gconstpointer data)
3868 MonoProperty *prop = (MonoProperty*)data;
3870 return g_str_hash (prop->name);
3874 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3876 if (method1->is_inflated)
3877 method1 = ((MonoMethodInflated*) method1)->declaring;
3878 if (method2->is_inflated)
3879 method2 = ((MonoMethodInflated*) method2)->declaring;
3881 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3885 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3887 // Properties are hide-by-name-and-signature
3888 if (!g_str_equal (prop1->name, prop2->name))
3891 /* If we see a property in a generic method, we want to
3892 compare the generic signatures, not the inflated signatures
3893 because we might conflate two properties that were
3897 public T this[T t] { getter { return t; } } // method 1
3898 public U this[U u] { getter { return u; } } // method 2
3901 If we see int Foo<int,int>::Item[int] we need to know if
3902 the indexer came from method 1 or from method 2, and we
3903 shouldn't conflate them. (Bugzilla 36283)
3905 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
3908 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
3915 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3920 return method_nonpublic (accessor, start_klass);
3923 ICALL_EXPORT MonoArray*
3924 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3928 static MonoClass *System_Reflection_PropertyInfo;
3929 MonoClass *startklass, *klass;
3935 gchar *propname = NULL;
3936 int (*compare_func) (const char *s1, const char *s2) = NULL;
3938 GHashTable *properties = NULL;
3939 MonoPtrArray tmp_array;
3941 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
3943 if (!System_Reflection_PropertyInfo)
3944 System_Reflection_PropertyInfo = mono_class_from_name (
3945 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3947 domain = ((MonoObject *)type)->vtable->domain;
3948 if (type->type->byref)
3949 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3950 klass = startklass = mono_class_from_mono_type (type->type);
3953 propname = mono_string_to_utf8 (name);
3954 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3957 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3959 mono_class_setup_methods (klass);
3960 mono_class_setup_vtable (klass);
3961 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3965 while ((prop = mono_class_get_properties (klass, &iter))) {
3971 flags = method->flags;
3974 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3975 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3976 if (bflags & BFLAGS_Public)
3978 } else if (bflags & BFLAGS_NonPublic) {
3979 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3980 property_accessor_nonpublic(prop->set, startklass == klass)) {
3987 if (flags & METHOD_ATTRIBUTE_STATIC) {
3988 if (bflags & BFLAGS_Static)
3989 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3992 if (bflags & BFLAGS_Instance)
4001 if (compare_func (propname, prop->name))
4005 if (g_hash_table_lookup (properties, prop))
4008 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
4010 g_hash_table_insert (properties, prop, prop);
4012 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4015 g_hash_table_destroy (properties);
4018 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
4019 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4020 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4022 mono_ptr_array_destroy (tmp_array);
4028 g_hash_table_destroy (properties);
4031 mono_ptr_array_destroy (tmp_array);
4033 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4034 ex = mono_class_get_exception_for_failure (klass);
4036 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4037 mono_loader_clear_error ();
4039 mono_set_pending_exception (ex);
4044 event_hash (gconstpointer data)
4046 MonoEvent *event = (MonoEvent*)data;
4048 return g_str_hash (event->name);
4052 event_equal (MonoEvent *event1, MonoEvent *event2)
4054 // Events are hide-by-name
4055 return g_str_equal (event1->name, event2->name);
4058 ICALL_EXPORT MonoArray*
4059 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4063 static MonoClass *System_Reflection_EventInfo;
4064 MonoClass *startklass, *klass;
4070 char *utf8_name = NULL;
4071 int (*compare_func) (const char *s1, const char *s2) = NULL;
4072 GHashTable *events = NULL;
4073 MonoPtrArray tmp_array;
4075 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4077 if (!System_Reflection_EventInfo)
4078 System_Reflection_EventInfo = mono_class_from_name (
4079 mono_defaults.corlib, "System.Reflection", "EventInfo");
4081 domain = mono_object_domain (type);
4082 if (type->type->byref)
4083 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
4084 klass = startklass = mono_class_from_mono_type (type->type);
4086 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4088 mono_class_setup_methods (klass);
4089 mono_class_setup_vtable (klass);
4090 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
4094 while ((event = mono_class_get_events (klass, &iter))) {
4096 method = event->add;
4098 method = event->remove;
4100 method = event->raise;
4102 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4103 if (bflags & BFLAGS_Public)
4105 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4106 if (bflags & BFLAGS_NonPublic)
4111 if (bflags & BFLAGS_NonPublic)
4117 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4118 if (bflags & BFLAGS_Static)
4119 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4122 if (bflags & BFLAGS_Instance)
4127 if (bflags & BFLAGS_Instance)
4133 if (utf8_name == NULL) {
4134 utf8_name = mono_string_to_utf8 (name);
4135 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4138 if (compare_func (event->name, utf8_name))
4142 if (g_hash_table_lookup (events, event))
4145 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
4147 g_hash_table_insert (events, event, event);
4149 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4152 g_hash_table_destroy (events);
4154 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
4156 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4157 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4159 mono_ptr_array_destroy (tmp_array);
4161 if (utf8_name != NULL)
4167 mono_ptr_array_destroy (tmp_array);
4168 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4169 ex = mono_class_get_exception_for_failure (klass);
4171 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4172 mono_loader_clear_error ();
4174 mono_set_pending_exception (ex);
4178 ICALL_EXPORT MonoArray*
4179 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4182 MonoReflectionType *rt;
4190 MonoPtrArray tmp_array;
4192 domain = ((MonoObject *)type)->vtable->domain;
4193 if (type->type->byref)
4194 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4195 klass = mono_class_from_mono_type (type->type);
4198 * If a nested type is generic, return its generic type definition.
4199 * Note that this means that the return value is essentially the set
4200 * of nested types of the generic type definition of @klass.
4202 * A note in MSDN claims that a generic type definition can have
4203 * nested types that aren't generic. In any case, the container of that
4204 * nested type would be the generic type definition.
4206 if (klass->generic_class)
4207 klass = klass->generic_class->container_class;
4209 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4211 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4213 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4214 if (bflags & BFLAGS_Public)
4217 if (bflags & BFLAGS_NonPublic)
4225 str = mono_string_to_utf8 (name);
4226 mono_identifier_unescape_type_name_chars (str);
4229 if (strcmp (nested->name, str))
4233 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4234 mono_error_raise_exception (&error);
4236 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4239 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4241 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4242 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4244 mono_ptr_array_destroy (tmp_array);
4252 ICALL_EXPORT MonoReflectionType*
4253 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4256 MonoReflectionType *ret;
4258 MonoType *type = NULL;
4259 MonoTypeNameParse info;
4260 gboolean type_resolve;
4262 /* On MS.NET, this does not fire a TypeResolve event */
4263 type_resolve = TRUE;
4264 str = mono_string_to_utf8 (name);
4265 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4266 if (!mono_reflection_parse_type (str, &info)) {
4268 mono_reflection_free_type_info (&info);
4270 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4273 /*g_print ("failed parse\n");*/
4277 if (info.assembly.name) {
4279 mono_reflection_free_type_info (&info);
4281 /* 1.0 and 2.0 throw different exceptions */
4282 if (mono_defaults.generic_ilist_class)
4283 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4285 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4291 if (module != NULL) {
4293 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4298 if (assembly_is_dynamic (assembly->assembly)) {
4299 /* Enumerate all modules */
4300 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4304 if (abuilder->modules) {
4305 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4306 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4307 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4313 if (!type && abuilder->loaded_modules) {
4314 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4315 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4316 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4323 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4325 mono_reflection_free_type_info (&info);
4327 MonoException *e = NULL;
4330 e = mono_get_exception_type_load (name, NULL);
4332 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4333 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4335 mono_loader_clear_error ();
4338 mono_set_pending_exception (e);
4340 } else if (mono_loader_get_last_error ()) {
4342 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4345 mono_loader_clear_error ();
4348 if (type->type == MONO_TYPE_CLASS) {
4349 MonoClass *klass = mono_type_get_class (type);
4351 /* need to report exceptions ? */
4352 if (throwOnError && klass->exception_type) {
4353 /* report SecurityException (or others) that occured when loading the assembly */
4354 MonoException *exc = mono_class_get_exception_for_failure (klass);
4355 mono_loader_clear_error ();
4356 mono_set_pending_exception (exc);
4361 /* g_print ("got it\n"); */
4362 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4363 mono_error_raise_exception (&error);
4369 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4372 gchar *shadow_ini_file;
4375 /* Check for shadow-copied assembly */
4376 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4377 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4379 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4380 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4386 g_free (shadow_ini_file);
4387 if (content != NULL) {
4390 *filename = content;
4397 ICALL_EXPORT MonoString *
4398 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4400 MonoDomain *domain = mono_object_domain (assembly);
4401 MonoAssembly *mass = assembly->assembly;
4402 MonoString *res = NULL;
4407 if (g_path_is_absolute (mass->image->name)) {
4408 absolute = g_strdup (mass->image->name);
4409 dirname = g_path_get_dirname (absolute);
4411 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4412 dirname = g_strdup (mass->basedir);
4415 replace_shadow_path (domain, dirname, &absolute);
4420 for (i = strlen (absolute) - 1; i >= 0; i--)
4421 if (absolute [i] == '\\')
4426 uri = g_filename_to_uri (absolute, NULL, NULL);
4428 const char *prepend = "file://";
4430 if (*absolute == '/' && *(absolute + 1) == '/') {
4433 prepend = "file:///";
4436 uri = g_strconcat (prepend, absolute, NULL);
4440 res = mono_string_new (domain, uri);
4447 ICALL_EXPORT MonoBoolean
4448 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4450 MonoAssembly *mass = assembly->assembly;
4452 return mass->in_gac;
4455 ICALL_EXPORT MonoReflectionAssembly*
4456 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4460 MonoImageOpenStatus status;
4462 name = mono_string_to_utf8 (mname);
4463 res = mono_assembly_load_with_partial_name (name, &status);
4469 return mono_assembly_get_object (mono_domain_get (), res);
4472 ICALL_EXPORT MonoString *
4473 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4475 MonoDomain *domain = mono_object_domain (assembly);
4478 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4483 ICALL_EXPORT MonoBoolean
4484 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4486 return assembly->assembly->ref_only;
4489 ICALL_EXPORT MonoString *
4490 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4492 MonoDomain *domain = mono_object_domain (assembly);
4494 return mono_string_new (domain, assembly->assembly->image->version);
4497 ICALL_EXPORT MonoReflectionMethod*
4498 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4501 MonoReflectionMethod *res = NULL;
4504 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4508 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4509 if (!mono_error_ok (&error))
4512 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4515 if (!mono_error_ok (&error))
4516 mono_error_set_pending_exception (&error);
4520 ICALL_EXPORT MonoReflectionModule*
4521 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4523 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4526 ICALL_EXPORT MonoArray*
4527 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4529 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4530 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4534 for (i = 0; i < table->rows; ++i) {
4535 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4536 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4542 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4544 static MonoClass *System_Version = NULL;
4545 static MonoMethod *create_version = NULL;
4550 if (!System_Version) {
4551 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4552 g_assert (System_Version);
4555 if (!create_version) {
4556 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4557 create_version = mono_method_desc_search_in_class (desc, System_Version);
4558 g_assert (create_version);
4559 mono_method_desc_free (desc);
4565 args [3] = &revision;
4566 result = mono_object_new_checked (domain, System_Version, &error);
4567 mono_error_raise_exception (&error); /* FIXME don't raise here */
4568 mono_runtime_invoke (create_version, result, args, NULL);
4573 ICALL_EXPORT MonoArray*
4574 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4576 static MonoClass *System_Reflection_AssemblyName;
4579 MonoDomain *domain = mono_object_domain (assembly);
4581 static MonoMethod *create_culture = NULL;
4582 MonoImage *image = assembly->assembly->image;
4585 if (!System_Reflection_AssemblyName)
4586 System_Reflection_AssemblyName = mono_class_from_name (
4587 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4589 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4592 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4594 if (count > 0 && !create_culture) {
4595 MonoMethodDesc *desc = mono_method_desc_new (
4596 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4597 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4598 g_assert (create_culture);
4599 mono_method_desc_free (desc);
4602 for (i = 0; i < count; i++) {
4603 MonoReflectionAssemblyName *aname;
4604 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4606 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4608 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4609 domain, System_Reflection_AssemblyName, &error);
4610 mono_error_raise_exception (&error);
4612 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4614 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4615 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4616 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4617 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4618 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4619 aname->versioncompat = 1; /* SameMachine (default) */
4620 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4621 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4623 if (create_culture) {
4625 MonoBoolean assembly_ref = 1;
4626 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4627 args [1] = &assembly_ref;
4628 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4631 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4632 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4633 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4635 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4636 /* public key token isn't copied - the class library will
4637 automatically generate it from the public key if required */
4638 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4639 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4641 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4642 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4645 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4648 /* note: this function doesn't return the codebase on purpose (i.e. it can
4649 be used under partial trust as path information isn't present). */
4651 mono_array_setref (result, i, aname);
4656 /* move this in some file in mono/util/ */
4658 g_concat_dir_and_file (const char *dir, const char *file)
4660 g_return_val_if_fail (dir != NULL, NULL);
4661 g_return_val_if_fail (file != NULL, NULL);
4664 * If the directory name doesn't have a / on the end, we need
4665 * to add one so we get a proper path to the file
4667 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4668 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4670 return g_strconcat (dir, file, NULL);
4674 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4676 char *n = mono_string_to_utf8 (name);
4677 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4679 guint32 cols [MONO_MANIFEST_SIZE];
4680 guint32 impl, file_idx;
4684 for (i = 0; i < table->rows; ++i) {
4685 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4686 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4687 if (strcmp (val, n) == 0)
4691 if (i == table->rows)
4694 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4697 * this code should only be called after obtaining the
4698 * ResourceInfo and handling the other cases.
4700 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4701 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4703 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4708 module = assembly->assembly->image;
4710 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4712 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4715 ICALL_EXPORT gboolean
4716 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4718 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4720 guint32 cols [MONO_MANIFEST_SIZE];
4721 guint32 file_cols [MONO_FILE_SIZE];
4725 n = mono_string_to_utf8 (name);
4726 for (i = 0; i < table->rows; ++i) {
4727 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4728 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4729 if (strcmp (val, n) == 0)
4733 if (i == table->rows)
4736 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4737 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4740 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4741 case MONO_IMPLEMENTATION_FILE:
4742 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4743 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4744 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4745 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4746 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4747 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4750 info->location = RESOURCE_LOCATION_EMBEDDED;
4753 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4754 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4755 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4756 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4757 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4758 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4760 mono_set_pending_exception (ex);
4763 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4765 /* Obtain info recursively */
4766 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4767 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4770 case MONO_IMPLEMENTATION_EXP_TYPE:
4771 g_assert_not_reached ();
4779 ICALL_EXPORT MonoObject*
4780 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4782 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4783 MonoArray *result = NULL;
4788 /* check hash if needed */
4790 n = mono_string_to_utf8 (name);
4791 for (i = 0; i < table->rows; ++i) {
4792 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4793 if (strcmp (val, n) == 0) {
4796 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4797 fn = mono_string_new (mono_object_domain (assembly), n);
4799 return (MonoObject*)fn;
4807 for (i = 0; i < table->rows; ++i) {
4808 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4812 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4815 for (i = 0; i < table->rows; ++i) {
4816 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4817 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4818 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4819 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4824 return (MonoObject*)result;
4827 ICALL_EXPORT MonoArray*
4828 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4830 MonoDomain *domain = mono_domain_get();
4833 int i, j, file_count = 0;
4834 MonoImage **modules;
4835 guint32 module_count, real_module_count;
4836 MonoTableInfo *table;
4837 guint32 cols [MONO_FILE_SIZE];
4838 MonoImage *image = assembly->assembly->image;
4840 g_assert (image != NULL);
4841 g_assert (!assembly_is_dynamic (assembly->assembly));
4843 table = &image->tables [MONO_TABLE_FILE];
4844 file_count = table->rows;
4846 modules = image->modules;
4847 module_count = image->module_count;
4849 real_module_count = 0;
4850 for (i = 0; i < module_count; ++i)
4852 real_module_count ++;
4854 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4855 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4857 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4859 for (i = 0; i < module_count; ++i)
4861 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4865 for (i = 0; i < file_count; ++i, ++j) {
4866 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4867 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4868 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4870 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4872 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4873 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
4876 mono_array_setref (res, j, mono_module_get_object (domain, m));
4883 ICALL_EXPORT MonoReflectionMethod*
4884 ves_icall_GetCurrentMethod (void)
4886 MonoReflectionMethod *res = NULL;
4889 MonoMethod *m = mono_method_get_last_managed ();
4892 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
4896 while (m->is_inflated)
4897 m = ((MonoMethodInflated*)m)->declaring;
4899 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
4900 mono_error_raise_exception (&error);
4906 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4909 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4912 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4913 //method is inflated, we should inflate it on the other class
4914 MonoGenericContext ctx;
4915 ctx.method_inst = inflated->context.method_inst;
4916 ctx.class_inst = inflated->context.class_inst;
4917 if (klass->generic_class)
4918 ctx.class_inst = klass->generic_class->context.class_inst;
4919 else if (klass->generic_container)
4920 ctx.class_inst = klass->generic_container->context.class_inst;
4921 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
4922 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4926 mono_class_setup_methods (method->klass);
4927 if (method->klass->exception_type)
4929 for (i = 0; i < method->klass->method.count; ++i) {
4930 if (method->klass->methods [i] == method) {
4935 mono_class_setup_methods (klass);
4936 if (klass->exception_type)
4938 g_assert (offset >= 0 && offset < klass->method.count);
4939 return klass->methods [offset];
4942 ICALL_EXPORT MonoReflectionMethod*
4943 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4945 MonoReflectionMethod *res = NULL;
4949 klass = mono_class_from_mono_type (type);
4950 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4952 if (method->klass != klass) {
4953 method = mono_method_get_equivalent_method (method, klass);
4958 klass = method->klass;
4959 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
4960 mono_error_raise_exception (&error);
4964 ICALL_EXPORT MonoReflectionMethodBody*
4965 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4967 return mono_method_body_get_object (mono_domain_get (), method);
4970 ICALL_EXPORT MonoReflectionAssembly*
4971 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4973 MonoMethod *dest = NULL;
4975 mono_stack_walk_no_il (get_executing, &dest);
4977 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4981 ICALL_EXPORT MonoReflectionAssembly*
4982 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4984 MonoDomain* domain = mono_domain_get ();
4986 if (!domain->entry_assembly)
4989 return mono_assembly_get_object (domain, domain->entry_assembly);
4992 ICALL_EXPORT MonoReflectionAssembly*
4993 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4999 mono_stack_walk_no_il (get_executing, &dest);
5001 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5005 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5008 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5011 ICALL_EXPORT MonoString *
5012 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5013 gboolean assembly_qualified)
5015 MonoDomain *domain = mono_object_domain (object);
5016 MonoTypeNameFormat format;
5021 format = assembly_qualified ?
5022 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5023 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5025 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5027 name = mono_type_get_name_full (object->type, format);
5031 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5036 res = mono_string_new (domain, name);
5043 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5045 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5046 mono_class_init_or_throw (klass);
5047 return mono_security_core_clr_class_level (klass);
5051 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5053 MonoClassField *field = rfield->field;
5054 return mono_security_core_clr_field_level (field, TRUE);
5058 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5060 MonoMethod *method = rfield->method;
5061 return mono_security_core_clr_method_level (method, TRUE);
5065 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
5067 static MonoMethod *create_culture = NULL;
5070 const char *pkey_ptr;
5072 MonoBoolean assembly_ref = 0;
5074 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5075 aname->major = name->major;
5076 aname->minor = name->minor;
5077 aname->build = name->build;
5078 aname->flags = name->flags;
5079 aname->revision = name->revision;
5080 aname->hashalg = name->hash_alg;
5081 aname->versioncompat = 1; /* SameMachine (default) */
5082 aname->processor_architecture = name->arch;
5084 if (by_default_version)
5085 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
5088 if (absolute != NULL && *absolute != '\0') {
5089 const gchar *prepend = "file://";
5092 codebase = g_strdup (absolute);
5097 for (i = strlen (codebase) - 1; i >= 0; i--)
5098 if (codebase [i] == '\\')
5101 if (*codebase == '/' && *(codebase + 1) == '/') {
5104 prepend = "file:///";
5108 result = g_strconcat (prepend, codebase, NULL);
5114 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5118 if (!create_culture) {
5119 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5120 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5121 g_assert (create_culture);
5122 mono_method_desc_free (desc);
5125 if (name->culture) {
5126 args [0] = mono_string_new (domain, name->culture);
5127 args [1] = &assembly_ref;
5128 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5131 if (name->public_key) {
5132 pkey_ptr = (char*)name->public_key;
5133 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5135 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5136 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5137 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5138 } else if (default_publickey) {
5139 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5140 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5143 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5144 if (name->public_key_token [0]) {
5148 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5149 p = mono_array_addr (aname->keyToken, char, 0);
5151 for (i = 0, j = 0; i < 8; i++) {
5152 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5153 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5156 } else if (default_token) {
5157 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5161 ICALL_EXPORT MonoString *
5162 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5164 MonoDomain *domain = mono_object_domain (assembly);
5165 MonoAssembly *mass = assembly->assembly;
5169 name = mono_stringify_assembly_name (&mass->aname);
5170 res = mono_string_new (domain, name);
5177 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5180 MonoAssembly *mass = assembly->assembly;
5182 if (g_path_is_absolute (mass->image->name)) {
5183 fill_reflection_assembly_name (mono_object_domain (assembly),
5184 aname, &mass->aname, mass->image->name, TRUE,
5188 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5190 fill_reflection_assembly_name (mono_object_domain (assembly),
5191 aname, &mass->aname, absolute, TRUE, TRUE,
5198 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5201 MonoImageOpenStatus status = MONO_IMAGE_OK;
5204 MonoAssemblyName name;
5207 filename = mono_string_to_utf8 (fname);
5209 dirname = g_path_get_dirname (filename);
5210 replace_shadow_path (mono_domain_get (), dirname, &filename);
5213 image = mono_image_open (filename, &status);
5219 if (status == MONO_IMAGE_IMAGE_INVALID)
5220 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5222 exc = mono_get_exception_file_not_found2 (NULL, fname);
5223 mono_set_pending_exception (exc);
5227 res = mono_assembly_fill_assembly_name (image, &name);
5229 mono_image_close (image);
5231 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5235 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5239 mono_image_close (image);
5242 ICALL_EXPORT MonoBoolean
5243 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5244 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5246 MonoBoolean result = FALSE;
5247 MonoDeclSecurityEntry entry;
5249 /* SecurityAction.RequestMinimum */
5250 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5251 *minimum = entry.blob;
5252 *minLength = entry.size;
5255 /* SecurityAction.RequestOptional */
5256 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5257 *optional = entry.blob;
5258 *optLength = entry.size;
5261 /* SecurityAction.RequestRefuse */
5262 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5263 *refused = entry.blob;
5264 *refLength = entry.size;
5272 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5274 guint32 attrs, visibility;
5276 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5277 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5278 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5281 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5287 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5290 MonoReflectionType *rt;
5293 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5296 /* we start the count from 1 because we skip the special type <Module> */
5299 for (i = 1; i < tdef->rows; ++i) {
5300 if (mono_module_type_is_visible (tdef, image, i + 1))
5304 count = tdef->rows - 1;
5306 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5307 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5309 for (i = 1; i < tdef->rows; ++i) {
5310 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5311 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, &error);
5312 mono_loader_assert_no_error (); /* Plug any leaks */
5313 g_assert (mono_error_ok (&error));
5316 rt = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5317 mono_error_raise_exception (&error); /* FIXME don't raise here */
5319 mono_array_setref (res, count, rt);
5321 MonoException *ex = mono_error_convert_to_exception (&error);
5322 mono_array_setref (*exceptions, count, ex);
5331 ICALL_EXPORT MonoArray*
5332 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5334 MonoArray *res = NULL;
5335 MonoArray *exceptions = NULL;
5336 MonoImage *image = NULL;
5337 MonoTableInfo *table = NULL;
5340 int i, len, ex_count;
5342 domain = mono_object_domain (assembly);
5344 g_assert (!assembly_is_dynamic (assembly->assembly));
5345 image = assembly->assembly->image;
5346 table = &image->tables [MONO_TABLE_FILE];
5347 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5349 /* Append data from all modules in the assembly */
5350 for (i = 0; i < table->rows; ++i) {
5351 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5352 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5355 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5356 /* Append the new types to the end of the array */
5357 if (mono_array_length (res2) > 0) {
5359 MonoArray *res3, *ex3;
5361 len1 = mono_array_length (res);
5362 len2 = mono_array_length (res2);
5364 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5365 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5366 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5369 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5370 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5371 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5378 /* the ReflectionTypeLoadException must have all the types (Types property),
5379 * NULL replacing types which throws an exception. The LoaderException must
5380 * contain all exceptions for NULL items.
5383 len = mono_array_length (res);
5386 for (i = 0; i < len; i++) {
5387 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5391 klass = mono_type_get_class (t->type);
5392 if ((klass != NULL) && klass->exception_type) {
5393 /* keep the class in the list */
5394 list = g_list_append (list, klass);
5395 /* and replace Type with NULL */
5396 mono_array_setref (res, i, NULL);
5403 if (list || ex_count) {
5405 MonoException *exc = NULL;
5406 MonoArray *exl = NULL;
5407 int j, length = g_list_length (list) + ex_count;
5409 mono_loader_clear_error ();
5411 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5412 /* Types for which mono_class_get_checked () succeeded */
5413 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5414 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5415 mono_array_setref (exl, i, exc);
5417 /* Types for which it don't */
5418 for (j = 0; j < mono_array_length (exceptions); ++j) {
5419 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5421 g_assert (i < length);
5422 mono_array_setref (exl, i, exc);
5429 exc = mono_get_exception_reflection_type_load (res, exl);
5430 mono_loader_clear_error ();
5431 mono_set_pending_exception (exc);
5438 ICALL_EXPORT gboolean
5439 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5441 MonoAssemblyName aname;
5442 MonoDomain *domain = mono_object_domain (name);
5444 gboolean is_version_defined;
5445 gboolean is_token_defined;
5447 aname.public_key = NULL;
5448 val = mono_string_to_utf8 (assname);
5449 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5450 g_free ((guint8*) aname.public_key);
5455 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5456 FALSE, is_token_defined);
5458 mono_assembly_name_free (&aname);
5459 g_free ((guint8*) aname.public_key);
5465 ICALL_EXPORT MonoReflectionType*
5466 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5469 MonoReflectionType *ret;
5470 MonoDomain *domain = mono_object_domain (module);
5473 g_assert (module->image);
5475 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5476 /* These images do not have a global type */
5479 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5480 if (!mono_error_ok (&error)) {
5481 mono_error_set_pending_exception (&error);
5485 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5486 if (!mono_error_ok (&error)) {
5487 mono_error_set_pending_exception (&error);
5495 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5497 /*if (module->image)
5498 mono_image_close (module->image);*/
5501 ICALL_EXPORT MonoString*
5502 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5504 MonoDomain *domain = mono_object_domain (module);
5506 g_assert (module->image);
5507 return mono_string_new (domain, module->image->guid);
5510 ICALL_EXPORT gpointer
5511 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5514 if (module->image && module->image->is_module_handle)
5515 return module->image->raw_data;
5518 return (gpointer) (-1);
5522 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5524 if (image_is_dynamic (image)) {
5525 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5526 *pe_kind = dyn->pe_kind;
5527 *machine = dyn->machine;
5530 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5531 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5536 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5538 return (image->md_version_major << 16) | (image->md_version_minor);
5541 ICALL_EXPORT MonoArray*
5542 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5544 MonoArray *exceptions;
5548 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5550 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5551 for (i = 0; i < mono_array_length (exceptions); ++i) {
5552 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5554 mono_set_pending_exception (ex);
5563 mono_memberref_is_method (MonoImage *image, guint32 token)
5565 if (!image_is_dynamic (image)) {
5566 guint32 cols [MONO_MEMBERREF_SIZE];
5568 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5569 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5570 mono_metadata_decode_blob_size (sig, &sig);
5571 return (*sig != 0x6);
5573 MonoClass *handle_class;
5575 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5578 return mono_defaults.methodhandle_class == handle_class;
5583 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5586 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5587 mono_array_addr (type_args, MonoType*, 0));
5589 context->class_inst = NULL;
5591 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5592 mono_array_addr (method_args, MonoType*, 0));
5594 context->method_inst = NULL;
5597 ICALL_EXPORT MonoType*
5598 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5601 int table = mono_metadata_token_table (token);
5602 int index = mono_metadata_token_index (token);
5603 MonoGenericContext context;
5606 *resolve_error = ResolveTokenError_Other;
5608 /* Validate token */
5609 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5610 (table != MONO_TABLE_TYPESPEC)) {
5611 *resolve_error = ResolveTokenError_BadTable;
5615 if (image_is_dynamic (image)) {
5616 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5617 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5618 return klass ? &klass->byval_arg : NULL;
5621 init_generic_context_from_args (&context, type_args, method_args);
5622 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5623 return klass ? &klass->byval_arg : NULL;
5626 if ((index <= 0) || (index > image->tables [table].rows)) {
5627 *resolve_error = ResolveTokenError_OutOfRange;
5631 init_generic_context_from_args (&context, type_args, method_args);
5632 klass = mono_class_get_checked (image, token, &error);
5634 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5635 if (!mono_error_ok (&error)) {
5636 mono_error_set_pending_exception (&error);
5641 return &klass->byval_arg;
5646 ICALL_EXPORT MonoMethod*
5647 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5650 int table = mono_metadata_token_table (token);
5651 int index = mono_metadata_token_index (token);
5652 MonoGenericContext context;
5655 *resolve_error = ResolveTokenError_Other;
5657 /* Validate token */
5658 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5659 (table != MONO_TABLE_MEMBERREF)) {
5660 *resolve_error = ResolveTokenError_BadTable;
5664 if (image_is_dynamic (image)) {
5665 if (table == MONO_TABLE_METHOD)
5666 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5668 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5669 *resolve_error = ResolveTokenError_BadTable;
5673 init_generic_context_from_args (&context, type_args, method_args);
5674 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5677 if ((index <= 0) || (index > image->tables [table].rows)) {
5678 *resolve_error = ResolveTokenError_OutOfRange;
5681 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5682 *resolve_error = ResolveTokenError_BadTable;
5686 init_generic_context_from_args (&context, type_args, method_args);
5687 method = mono_get_method_checked (image, token, NULL, &context, &error);
5688 mono_error_set_pending_exception (&error);
5693 ICALL_EXPORT MonoString*
5694 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5696 int index = mono_metadata_token_index (token);
5698 *error = ResolveTokenError_Other;
5700 /* Validate token */
5701 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5702 *error = ResolveTokenError_BadTable;
5706 if (image_is_dynamic (image))
5707 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5709 if ((index <= 0) || (index >= image->heap_us.size)) {
5710 *error = ResolveTokenError_OutOfRange;
5714 /* FIXME: What to do if the index points into the middle of a string ? */
5716 return mono_ldstr (mono_domain_get (), image, index);
5719 ICALL_EXPORT MonoClassField*
5720 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5724 int table = mono_metadata_token_table (token);
5725 int index = mono_metadata_token_index (token);
5726 MonoGenericContext context;
5727 MonoClassField *field;
5729 *resolve_error = ResolveTokenError_Other;
5731 /* Validate token */
5732 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5733 *resolve_error = ResolveTokenError_BadTable;
5737 if (image_is_dynamic (image)) {
5738 if (table == MONO_TABLE_FIELD)
5739 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5741 if (mono_memberref_is_method (image, token)) {
5742 *resolve_error = ResolveTokenError_BadTable;
5746 init_generic_context_from_args (&context, type_args, method_args);
5747 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5750 if ((index <= 0) || (index > image->tables [table].rows)) {
5751 *resolve_error = ResolveTokenError_OutOfRange;
5754 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5755 *resolve_error = ResolveTokenError_BadTable;
5759 init_generic_context_from_args (&context, type_args, method_args);
5760 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5761 mono_error_set_pending_exception (&error);
5767 ICALL_EXPORT MonoObject*
5768 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5772 int table = mono_metadata_token_table (token);
5774 *error = ResolveTokenError_Other;
5777 case MONO_TABLE_TYPEDEF:
5778 case MONO_TABLE_TYPEREF:
5779 case MONO_TABLE_TYPESPEC: {
5780 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5782 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
5783 mono_error_raise_exception (&merror);
5790 case MONO_TABLE_METHOD:
5791 case MONO_TABLE_METHODSPEC: {
5792 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5794 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5795 mono_error_raise_exception (&merror);
5801 case MONO_TABLE_FIELD: {
5802 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5804 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5805 mono_error_raise_exception (&merror);
5811 case MONO_TABLE_MEMBERREF:
5812 if (mono_memberref_is_method (image, token)) {
5813 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5815 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5816 mono_error_raise_exception (&merror);
5823 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5825 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5826 mono_error_raise_exception (&merror);
5835 *error = ResolveTokenError_BadTable;
5841 ICALL_EXPORT MonoArray*
5842 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5844 int table = mono_metadata_token_table (token);
5845 int idx = mono_metadata_token_index (token);
5846 MonoTableInfo *tables = image->tables;
5851 *error = ResolveTokenError_OutOfRange;
5853 /* FIXME: Support other tables ? */
5854 if (table != MONO_TABLE_STANDALONESIG)
5857 if (image_is_dynamic (image))
5860 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5863 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5865 ptr = mono_metadata_blob_heap (image, sig);
5866 len = mono_metadata_decode_blob_size (ptr, &ptr);
5868 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5869 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5873 ICALL_EXPORT MonoReflectionType*
5874 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5877 MonoReflectionType *ret;
5879 int isbyref = 0, rank;
5880 char *str = mono_string_to_utf8 (smodifiers);
5883 klass = mono_class_from_mono_type (tb->type.type);
5885 /* logic taken from mono_reflection_parse_type(): keep in sync */
5889 if (isbyref) { /* only one level allowed by the spec */
5898 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
5899 mono_error_raise_exception (&error);
5903 klass = mono_ptr_class_get (&klass->byval_arg);
5904 mono_class_init (klass);
5915 else if (*p != '*') { /* '*' means unknown lower bound */
5926 klass = mono_array_class_get (klass, rank);
5927 mono_class_init (klass);
5936 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
5937 mono_error_raise_exception (&error);
5942 ICALL_EXPORT MonoBoolean
5943 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5949 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5955 check_for_invalid_type (MonoClass *klass)
5959 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5962 name = mono_type_get_full_name (klass);
5963 str = mono_string_new (mono_domain_get (), name);
5965 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5968 ICALL_EXPORT MonoReflectionType *
5969 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5972 MonoReflectionType *ret;
5973 MonoClass *klass, *aklass;
5975 klass = mono_class_from_mono_type (type->type);
5976 check_for_invalid_type (klass);
5978 if (rank == 0) //single dimentional array
5979 aklass = mono_array_class_get (klass, 1);
5981 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5983 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
5984 mono_error_raise_exception (&error);
5989 ICALL_EXPORT MonoReflectionType *
5990 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5993 MonoReflectionType *ret;
5996 klass = mono_class_from_mono_type (type->type);
5997 mono_class_init_or_throw (klass);
5998 check_for_invalid_type (klass);
6000 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6001 mono_error_raise_exception (&error);
6006 ICALL_EXPORT MonoReflectionType *
6007 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6010 MonoReflectionType *ret;
6011 MonoClass *klass, *pklass;
6013 klass = mono_class_from_mono_type (type->type);
6014 mono_class_init_or_throw (klass);
6015 check_for_invalid_type (klass);
6017 pklass = mono_ptr_class_get (type->type);
6019 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6020 mono_error_raise_exception (&error);
6025 ICALL_EXPORT MonoObject *
6026 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6027 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6030 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6031 MonoObject *delegate;
6033 MonoMethod *method = info->method;
6035 mono_class_init_or_throw (delegate_class);
6037 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
6039 if (mono_security_core_clr_enabled ()) {
6040 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6044 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6045 mono_error_raise_exception (&error);
6047 if (method_is_dynamic (method)) {
6048 /* Creating a trampoline would leak memory */
6049 func = mono_compile_method (method);
6051 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6052 method = mono_object_get_virtual_method (target, method);
6053 func = mono_create_ftnptr (mono_domain_get (),
6054 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6057 mono_delegate_ctor_with_method (delegate, target, func, method);
6062 ICALL_EXPORT MonoMulticastDelegate *
6063 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6066 MonoMulticastDelegate *ret;
6068 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6070 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6071 mono_error_raise_exception (&error);
6072 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6077 ICALL_EXPORT MonoReflectionMethod*
6078 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6080 MonoReflectionMethod *ret = NULL;
6082 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6083 mono_error_raise_exception (&error);
6089 static inline gint32
6090 mono_array_get_byte_length (MonoArray *array)
6096 klass = array->obj.vtable->klass;
6098 if (array->bounds == NULL)
6099 length = array->max_length;
6102 for (i = 0; i < klass->rank; ++ i)
6103 length *= array->bounds [i].length;
6106 switch (klass->element_class->byval_arg.type) {
6109 case MONO_TYPE_BOOLEAN:
6113 case MONO_TYPE_CHAR:
6121 return length * sizeof (gpointer);
6132 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6134 return mono_array_get_byte_length (array);
6138 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6140 return mono_array_get (array, gint8, idx);
6144 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6146 mono_array_set (array, gint8, idx, value);
6149 ICALL_EXPORT MonoBoolean
6150 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6152 guint8 *src_buf, *dest_buf;
6155 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6159 g_assert (count >= 0);
6161 /* This is called directly from the class libraries without going through the managed wrapper */
6162 MONO_CHECK_ARG_NULL (src, FALSE);
6163 MONO_CHECK_ARG_NULL (dest, FALSE);
6165 /* watch out for integer overflow */
6166 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6169 src_buf = (guint8 *)src->vector + src_offset;
6170 dest_buf = (guint8 *)dest->vector + dest_offset;
6173 memcpy (dest_buf, src_buf, count);
6175 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6180 #ifndef DISABLE_REMOTING
6181 ICALL_EXPORT MonoObject *
6182 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6185 MonoDomain *domain = mono_object_domain (this_obj);
6187 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6188 MonoTransparentProxy *tp;
6192 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6193 mono_error_raise_exception (&error);
6194 tp = (MonoTransparentProxy*) res;
6196 MONO_OBJECT_SETREF (tp, rp, rp);
6197 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6198 klass = mono_class_from_mono_type (type);
6200 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6201 mono_class_setup_vtable (klass);
6202 if (klass->exception_type) {
6203 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6207 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
6208 tp->remote_class = mono_remote_class (domain, class_name, klass);
6210 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6214 ICALL_EXPORT MonoReflectionType *
6215 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6218 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6219 mono_error_raise_exception (&error);
6225 /* System.Environment */
6228 ves_icall_System_Environment_get_UserName (void)
6230 /* using glib is more portable */
6231 return mono_string_new (mono_domain_get (), g_get_user_name ());
6235 ICALL_EXPORT MonoString *
6236 ves_icall_System_Environment_get_MachineName (void)
6238 #if defined (HOST_WIN32)
6243 len = MAX_COMPUTERNAME_LENGTH + 1;
6244 buf = g_new (gunichar2, len);
6247 if (GetComputerName (buf, (PDWORD) &len)) {
6249 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6250 mono_error_raise_exception (&error);
6255 #elif !defined(DISABLE_SOCKETS)
6259 #if defined _SC_HOST_NAME_MAX
6260 n = sysconf (_SC_HOST_NAME_MAX);
6264 buf = g_malloc (n+1);
6266 if (gethostname (buf, n) == 0){
6268 result = mono_string_new (mono_domain_get (), buf);
6275 return mono_string_new (mono_domain_get (), "mono");
6280 ves_icall_System_Environment_get_Platform (void)
6282 #if defined (TARGET_WIN32)
6285 #elif defined(__MACH__)
6288 // Notice that the value is hidden from user code, and only exposed
6289 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6290 // define and making assumptions based on Unix/128/4 values before there
6291 // was a MacOS define. Lots of code would assume that not-Unix meant
6292 // Windows, but in this case, it would be OSX.
6301 ICALL_EXPORT MonoString *
6302 ves_icall_System_Environment_get_NewLine (void)
6304 #if defined (HOST_WIN32)
6305 return mono_string_new (mono_domain_get (), "\r\n");
6307 return mono_string_new (mono_domain_get (), "\n");
6311 ICALL_EXPORT MonoBoolean
6312 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6314 #if SIZEOF_VOID_P == 8
6318 gboolean isWow64Process = FALSE;
6319 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6320 return (MonoBoolean)isWow64Process;
6322 #elif defined(HAVE_SYS_UTSNAME_H)
6323 struct utsname name;
6325 if (uname (&name) >= 0) {
6326 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6333 ICALL_EXPORT MonoString *
6334 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6342 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6343 value = g_getenv (utf8_name);
6350 return mono_string_new (mono_domain_get (), value);
6354 * There is no standard way to get at environ.
6357 #ifndef __MINGW32_VERSION
6358 #if defined(__APPLE__)
6359 #if defined (TARGET_OSX)
6360 /* Apple defines this in crt_externs.h but doesn't provide that header for
6361 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6362 * in fact exist on all implementations (so far)
6364 gchar ***_NSGetEnviron(void);
6365 #define environ (*_NSGetEnviron())
6367 static char *mono_environ[1] = { NULL };
6368 #define environ mono_environ
6369 #endif /* defined (TARGET_OSX) */
6377 ICALL_EXPORT MonoArray *
6378 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6389 env_strings = GetEnvironmentStrings();
6392 env_string = env_strings;
6393 while (*env_string != '\0') {
6394 /* weird case that MS seems to skip */
6395 if (*env_string != '=')
6397 while (*env_string != '\0')
6403 domain = mono_domain_get ();
6404 names = mono_array_new (domain, mono_defaults.string_class, n);
6408 env_string = env_strings;
6409 while (*env_string != '\0') {
6410 /* weird case that MS seems to skip */
6411 if (*env_string != '=') {
6412 equal_str = wcschr(env_string, '=');
6413 g_assert(equal_str);
6415 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6416 mono_error_raise_exception (&error);
6417 mono_array_setref (names, n, str);
6420 while (*env_string != '\0')
6425 FreeEnvironmentStrings (env_strings);
6438 for (e = environ; *e != 0; ++ e)
6441 domain = mono_domain_get ();
6442 names = mono_array_new (domain, mono_defaults.string_class, n);
6445 for (e = environ; *e != 0; ++ e) {
6446 parts = g_strsplit (*e, "=", 2);
6448 str = mono_string_new (domain, *parts);
6449 mono_array_setref (names, n, str);
6462 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6464 #if !GLIB_CHECK_VERSION(2,4,0)
6465 #define g_setenv(a,b,c) setenv(a,b,c)
6466 #define g_unsetenv(a) unsetenv(a)
6470 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6473 gunichar2 *utf16_name, *utf16_value;
6475 gchar *utf8_name, *utf8_value;
6480 utf16_name = mono_string_to_utf16 (name);
6481 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6482 SetEnvironmentVariable (utf16_name, NULL);
6483 g_free (utf16_name);
6487 utf16_value = mono_string_to_utf16 (value);
6489 SetEnvironmentVariable (utf16_name, utf16_value);
6491 g_free (utf16_name);
6492 g_free (utf16_value);
6494 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6496 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6497 g_unsetenv (utf8_name);
6502 utf8_value = mono_string_to_utf8_checked (value, &error);
6503 if (!mono_error_ok (&error)) {
6505 mono_error_set_pending_exception (&error);
6508 g_setenv (utf8_name, utf8_value, TRUE);
6511 g_free (utf8_value);
6516 ves_icall_System_Environment_Exit (int result)
6518 mono_environment_exitcode_set (result);
6520 /* FIXME: There are some cleanup hangs that should be worked out, but
6521 * if the program is going to exit, everything will be cleaned up when
6522 * NaCl exits anyway.
6524 #ifndef __native_client__
6525 if (!mono_runtime_try_shutdown ())
6526 mono_thread_exit ();
6528 /* Suspend all managed threads since the runtime is going away */
6529 mono_thread_suspend_all_other_threads ();
6531 mono_runtime_quit ();
6534 /* we may need to do some cleanup here... */
6538 ICALL_EXPORT MonoString*
6539 ves_icall_System_Environment_GetGacPath (void)
6541 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6544 ICALL_EXPORT MonoString*
6545 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6547 #if defined (HOST_WIN32)
6548 #ifndef CSIDL_FLAG_CREATE
6549 #define CSIDL_FLAG_CREATE 0x8000
6552 WCHAR path [MAX_PATH];
6553 /* Create directory if no existing */
6554 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6559 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6560 mono_error_raise_exception (&error);
6564 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6566 return mono_string_new (mono_domain_get (), "");
6569 ICALL_EXPORT MonoArray *
6570 ves_icall_System_Environment_GetLogicalDrives (void)
6573 gunichar2 buf [256], *ptr, *dname;
6575 guint initial_size = 127, size = 128;
6578 MonoString *drivestr;
6579 MonoDomain *domain = mono_domain_get ();
6585 while (size > initial_size) {
6586 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6587 if (size > initial_size) {
6590 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6591 initial_size = size;
6605 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6610 while (*u16) { u16++; len ++; }
6611 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6612 mono_error_raise_exception (&error);
6613 mono_array_setref (result, ndrives++, drivestr);
6623 ICALL_EXPORT MonoString *
6624 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6626 gunichar2 volume_name [MAX_PATH + 1];
6628 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6630 return mono_string_from_utf16 (volume_name);
6633 ICALL_EXPORT MonoString *
6634 ves_icall_System_Environment_InternalGetHome (void)
6636 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6639 static const char *encodings [] = {
6641 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6642 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6643 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6645 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6646 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6647 "x_unicode_2_0_utf_7",
6649 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6650 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6652 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6655 "unicodefffe", "utf_16be",
6662 * Returns the internal codepage, if the value of "int_code_page" is
6663 * 1 at entry, and we can not compute a suitable code page number,
6664 * returns the code page as a string
6666 ICALL_EXPORT MonoString*
6667 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6672 char *codepage = NULL;
6674 int want_name = *int_code_page;
6677 *int_code_page = -1;
6679 g_get_charset (&cset);
6680 c = codepage = strdup (cset);
6681 for (c = codepage; *c; c++){
6682 if (isascii (*c) && isalpha (*c))
6687 /* g_print ("charset: %s\n", cset); */
6689 /* handle some common aliases */
6692 for (i = 0; p != 0; ){
6695 p = encodings [++i];
6698 if (strcmp (p, codepage) == 0){
6699 *int_code_page = code;
6702 p = encodings [++i];
6705 if (strstr (codepage, "utf_8") != NULL)
6706 *int_code_page |= 0x10000000;
6709 if (want_name && *int_code_page == -1)
6710 return mono_string_new (mono_domain_get (), cset);
6715 ICALL_EXPORT MonoBoolean
6716 ves_icall_System_Environment_get_HasShutdownStarted (void)
6718 if (mono_runtime_is_shutting_down ())
6721 if (mono_domain_is_unloading (mono_domain_get ()))
6728 ves_icall_System_Environment_BroadcastSettingChange (void)
6731 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6736 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6742 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6743 MonoReflectionMethod *method,
6744 MonoArray *out_args)
6746 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6749 #ifndef DISABLE_REMOTING
6750 ICALL_EXPORT MonoBoolean
6751 ves_icall_IsTransparentProxy (MonoObject *proxy)
6756 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6762 ICALL_EXPORT MonoReflectionMethod *
6763 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6764 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6766 MonoReflectionMethod *ret = NULL;
6771 MonoMethod **vtable;
6772 MonoMethod *res = NULL;
6774 MONO_CHECK_ARG_NULL (rtype, NULL);
6775 MONO_CHECK_ARG_NULL (rmethod, NULL);
6777 method = rmethod->method;
6778 klass = mono_class_from_mono_type (rtype->type);
6779 mono_class_init_or_throw (klass);
6781 if (MONO_CLASS_IS_INTERFACE (klass))
6784 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6787 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6788 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6794 mono_class_setup_vtable (klass);
6795 vtable = klass->vtable;
6797 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6798 gboolean variance_used = FALSE;
6799 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6800 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6802 res = vtable [offs + method->slot];
6804 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6807 if (method->slot != -1)
6808 res = vtable [method->slot];
6814 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
6815 mono_error_raise_exception (&error);
6820 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6825 klass = mono_class_from_mono_type (type->type);
6826 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6828 mono_vtable_set_is_remote (vtable, enable);
6831 #else /* DISABLE_REMOTING */
6834 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6836 g_assert_not_reached ();
6841 ICALL_EXPORT MonoObject *
6842 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6849 domain = mono_object_domain (type);
6850 klass = mono_class_from_mono_type (type->type);
6851 mono_class_init_or_throw (klass);
6853 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
6854 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6858 if (klass->rank >= 1) {
6859 g_assert (klass->rank == 1);
6860 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6862 /* Bypass remoting object creation check */
6863 ret = mono_object_new_alloc_specific_checked (mono_class_vtable_full (domain, klass, TRUE), &error);
6864 mono_error_set_pending_exception (&error);
6870 ICALL_EXPORT MonoString *
6871 ves_icall_System_IO_get_temp_path (void)
6873 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6876 #ifndef PLATFORM_NO_DRIVEINFO
6877 ICALL_EXPORT MonoBoolean
6878 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6879 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6883 ULARGE_INTEGER wapi_free_bytes_avail;
6884 ULARGE_INTEGER wapi_total_number_of_bytes;
6885 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6887 *error = ERROR_SUCCESS;
6888 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6889 &wapi_total_number_of_free_bytes);
6892 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6893 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6894 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6896 *free_bytes_avail = 0;
6897 *total_number_of_bytes = 0;
6898 *total_number_of_free_bytes = 0;
6899 *error = GetLastError ();
6905 ICALL_EXPORT guint32
6906 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6908 return GetDriveType (mono_string_chars (root_path_name));
6912 ICALL_EXPORT gpointer
6913 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6915 return mono_compile_method (method);
6918 ICALL_EXPORT MonoString *
6919 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6924 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6926 #if defined (HOST_WIN32)
6927 /* Avoid mixing '/' and '\\' */
6930 for (i = strlen (path) - 1; i >= 0; i--)
6931 if (path [i] == '/')
6935 mcpath = mono_string_new (mono_domain_get (), path);
6942 get_bundled_app_config (void)
6944 const gchar *app_config;
6947 gchar *config_file_name, *config_file_path;
6948 gsize len, config_file_path_length, config_ext_length;
6951 domain = mono_domain_get ();
6952 file = domain->setup->configuration_file;
6953 if (!file || file->length == 0)
6956 // Retrieve config file and remove the extension
6957 config_file_name = mono_string_to_utf8 (file);
6958 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6959 if (!config_file_path)
6960 config_file_path = config_file_name;
6962 config_file_path_length = strlen (config_file_path);
6963 config_ext_length = strlen (".config");
6964 if (config_file_path_length <= config_ext_length)
6967 len = config_file_path_length - config_ext_length;
6968 module = (gchar *)g_malloc0 (len + 1);
6969 memcpy (module, config_file_path, len);
6970 // Get the config file from the module name
6971 app_config = mono_config_string_for_assembly_file (module);
6974 if (config_file_name != config_file_path)
6975 g_free (config_file_name);
6976 g_free (config_file_path);
6981 return mono_string_new (mono_domain_get (), app_config);
6985 get_bundled_machine_config (void)
6987 const gchar *machine_config;
6989 machine_config = mono_get_machine_config ();
6991 if (!machine_config)
6994 return mono_string_new (mono_domain_get (), machine_config);
6997 ICALL_EXPORT MonoString *
6998 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7003 path = g_path_get_dirname (mono_get_config_dir ());
7005 #if defined (HOST_WIN32)
7006 /* Avoid mixing '/' and '\\' */
7009 for (i = strlen (path) - 1; i >= 0; i--)
7010 if (path [i] == '/')
7014 ipath = mono_string_new (mono_domain_get (), path);
7020 ICALL_EXPORT gboolean
7021 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7023 MonoPEResourceDataEntry *entry;
7026 if (!assembly || !result || !size)
7031 image = assembly->assembly->image;
7032 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7036 *result = mono_image_rva_map (image, entry->rde_data_offset);
7041 *size = entry->rde_size;
7046 ICALL_EXPORT MonoBoolean
7047 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7049 return mono_is_debugger_attached ();
7052 ICALL_EXPORT MonoBoolean
7053 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7055 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7056 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7062 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7064 if (mono_get_runtime_callbacks ()->debug_log)
7065 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7069 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7071 #if defined (HOST_WIN32)
7072 OutputDebugString (mono_string_chars (message));
7074 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7078 /* Only used for value types */
7079 ICALL_EXPORT MonoObject *
7080 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7087 domain = mono_object_domain (type);
7088 klass = mono_class_from_mono_type (type->type);
7089 mono_class_init_or_throw (klass);
7091 if (mono_class_is_nullable (klass))
7092 /* No arguments -> null */
7095 result = mono_object_new_checked (domain, klass, &error);
7096 mono_error_raise_exception (&error);
7100 ICALL_EXPORT MonoReflectionMethod *
7101 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7103 MonoReflectionMethod *ret = NULL;
7106 MonoClass *klass, *parent;
7107 MonoGenericContext *generic_inst = NULL;
7108 MonoMethod *method = m->method;
7109 MonoMethod *result = NULL;
7112 if (method->klass == NULL)
7115 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7116 MONO_CLASS_IS_INTERFACE (method->klass) ||
7117 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7120 slot = mono_method_get_vtable_slot (method);
7124 klass = method->klass;
7125 if (klass->generic_class) {
7126 generic_inst = mono_class_get_context (klass);
7127 klass = klass->generic_class->container_class;
7131 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7132 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7133 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7134 or klass is the generic container class and generic_inst is the instantiation.
7136 when we go to the parent, if the parent is an open constructed type, we need to
7137 replace the type parameters by the definitions from the generic_inst, and then take it
7138 apart again into the klass and the generic_inst.
7140 For cases like this:
7141 class C<T> : B<T, int> {
7142 public override void Foo () { ... }
7144 class B<U,V> : A<HashMap<U,V>> {
7145 public override void Foo () { ... }
7148 public virtual void Foo () { ... }
7151 if at each iteration the parent isn't open, we can skip inflating it. if at some
7152 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7155 MonoGenericContext *parent_inst = NULL;
7156 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7158 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7159 if (!mono_error_ok (&error)) {
7160 mono_error_set_pending_exception (&error);
7164 if (parent->generic_class) {
7165 parent_inst = mono_class_get_context (parent);
7166 parent = parent->generic_class->container_class;
7169 mono_class_setup_vtable (parent);
7170 if (parent->vtable_size <= slot)
7173 generic_inst = parent_inst;
7176 klass = klass->parent;
7179 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7180 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7181 if (!mono_error_ok (&error)) {
7182 mono_error_set_pending_exception (&error);
7186 generic_inst = NULL;
7188 if (klass->generic_class) {
7189 generic_inst = mono_class_get_context (klass);
7190 klass = klass->generic_class->container_class;
7196 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7197 if (!mono_error_ok (&error)) {
7198 mono_error_set_pending_exception (&error);
7203 if (klass == method->klass)
7206 /*This is possible if definition == FALSE.
7207 * Do it here to be really sure we don't read invalid memory.
7209 if (slot >= klass->vtable_size)
7212 mono_class_setup_vtable (klass);
7214 result = klass->vtable [slot];
7215 if (result == NULL) {
7216 /* It is an abstract method */
7217 gpointer iter = NULL;
7218 while ((result = mono_class_get_methods (klass, &iter)))
7219 if (result->slot == slot)
7226 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7227 mono_error_raise_exception (&error);
7231 ICALL_EXPORT MonoString*
7232 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7234 MonoMethod *method = m->method;
7236 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7241 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7243 iter->sig = *(MonoMethodSignature**)argsp;
7245 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7246 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7249 /* FIXME: it's not documented what start is exactly... */
7253 iter->args = argsp + sizeof (gpointer);
7255 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7257 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7260 ICALL_EXPORT MonoTypedRef
7261 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7263 guint32 i, arg_size;
7267 i = iter->sig->sentinelpos + iter->next_arg;
7269 g_assert (i < iter->sig->param_count);
7271 res.type = iter->sig->params [i];
7272 res.klass = mono_class_from_mono_type (res.type);
7273 arg_size = mono_type_stack_size (res.type, &align);
7274 #if defined(__arm__) || defined(__mips__)
7275 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7277 res.value = iter->args;
7278 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7279 /* Values are stored as 8 byte register sized objects, but 'value'
7280 * is dereferenced as a pointer in other routines.
7282 res.value = (char*)res.value + 4;
7284 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7285 if (arg_size <= sizeof (gpointer)) {
7287 int padding = arg_size - mono_type_size (res.type, &dummy);
7288 res.value = (guint8*)res.value + padding;
7291 iter->args = (char*)iter->args + arg_size;
7294 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7299 ICALL_EXPORT MonoTypedRef
7300 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7302 guint32 i, arg_size;
7306 i = iter->sig->sentinelpos + iter->next_arg;
7308 g_assert (i < iter->sig->param_count);
7310 while (i < iter->sig->param_count) {
7311 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7313 res.type = iter->sig->params [i];
7314 res.klass = mono_class_from_mono_type (res.type);
7315 /* FIXME: endianess issue... */
7316 arg_size = mono_type_stack_size (res.type, &align);
7317 #if defined(__arm__) || defined(__mips__)
7318 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7320 res.value = iter->args;
7321 iter->args = (char*)iter->args + arg_size;
7323 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7326 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7334 ICALL_EXPORT MonoType*
7335 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7339 i = iter->sig->sentinelpos + iter->next_arg;
7341 g_assert (i < iter->sig->param_count);
7343 return iter->sig->params [i];
7346 ICALL_EXPORT MonoObject*
7347 mono_TypedReference_ToObject (MonoTypedRef* tref)
7349 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7350 MonoObject** objp = (MonoObject **)tref->value;
7354 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
7357 ICALL_EXPORT MonoTypedRef
7358 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7361 MonoReflectionField *f;
7363 MonoType *ftype = NULL;
7367 memset (&res, 0, sizeof (res));
7370 g_assert (mono_array_length (fields) > 0);
7372 klass = target->vtable->klass;
7374 for (i = 0; i < mono_array_length (fields); ++i) {
7375 f = mono_array_get (fields, MonoReflectionField*, i);
7377 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7380 if (f->field->parent != klass) {
7381 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7385 p = (guint8*)target + f->field->offset;
7387 p += f->field->offset - sizeof (MonoObject);
7388 klass = mono_class_from_mono_type (f->field->type);
7389 ftype = f->field->type;
7393 res.klass = mono_class_from_mono_type (ftype);
7400 prelink_method (MonoMethod *method)
7402 const char *exc_class, *exc_arg;
7403 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7405 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7407 mono_raise_exception(
7408 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7410 /* create the wrapper, too? */
7414 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7416 prelink_method (method->method);
7420 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7422 MonoClass *klass = mono_class_from_mono_type (type->type);
7424 gpointer iter = NULL;
7426 mono_class_init_or_throw (klass);
7428 while ((m = mono_class_get_methods (klass, &iter)))
7432 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7434 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7435 gint32 const **exponents,
7436 gunichar2 const **digitLowerTable,
7437 gunichar2 const **digitUpperTable,
7438 gint64 const **tenPowersList,
7439 gint32 const **decHexDigits)
7441 *mantissas = Formatter_MantissaBitsTable;
7442 *exponents = Formatter_TensExponentTable;
7443 *digitLowerTable = Formatter_DigitLowerTable;
7444 *digitUpperTable = Formatter_DigitUpperTable;
7445 *tenPowersList = Formatter_TenPowersList;
7446 *decHexDigits = Formatter_DecHexDigits;
7450 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7451 * and avoid useless allocations.
7456 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7459 MonoReflectionType *rt;
7462 for (i = 0; i < type->num_mods; ++i) {
7463 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7468 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7470 for (i = 0; i < type->num_mods; ++i) {
7471 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7472 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
7473 mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */
7475 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, &error);
7476 mono_error_raise_exception (&error);
7478 mono_array_setref (res, count, rt);
7485 ICALL_EXPORT MonoArray*
7486 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7488 MonoType *type = param->ClassImpl->type;
7489 MonoClass *member_class = mono_object_class (param->MemberImpl);
7490 MonoMethod *method = NULL;
7493 MonoMethodSignature *sig;
7495 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7496 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7497 method = rmethod->method;
7498 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7499 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7500 if (!(method = prop->property->get))
7501 method = prop->property->set;
7504 char *type_name = mono_type_get_full_name (member_class);
7505 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7506 MonoException *ex = mono_get_exception_not_supported (msg);
7509 mono_set_pending_exception (ex);
7513 image = method->klass->image;
7514 pos = param->PositionImpl;
7515 sig = mono_method_signature (method);
7519 type = sig->params [pos];
7521 return type_array_from_modifiers (image, type, optional);
7525 get_property_type (MonoProperty *prop)
7527 MonoMethodSignature *sig;
7529 sig = mono_method_signature (prop->get);
7531 } else if (prop->set) {
7532 sig = mono_method_signature (prop->set);
7533 return sig->params [sig->param_count - 1];
7538 ICALL_EXPORT MonoArray*
7539 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7541 MonoType *type = get_property_type (property->property);
7542 MonoImage *image = property->klass->image;
7546 return type_array_from_modifiers (image, type, optional);
7550 *Construct a MonoType suited to be used to decode a constant blob object.
7552 * @type is the target type which will be constructed
7553 * @blob_type is the blob type, for example, that comes from the constant table
7554 * @real_type is the expected constructed type.
7557 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7559 type->type = blob_type;
7560 type->data.klass = NULL;
7561 if (blob_type == MONO_TYPE_CLASS)
7562 type->data.klass = mono_defaults.object_class;
7563 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7564 /* For enums, we need to use the base type */
7565 type->type = MONO_TYPE_VALUETYPE;
7566 type->data.klass = mono_class_from_mono_type (real_type);
7568 type->data.klass = mono_class_from_mono_type (real_type);
7571 ICALL_EXPORT MonoObject*
7572 property_info_get_default_value (MonoReflectionProperty *property)
7575 MonoProperty *prop = property->property;
7576 MonoType *type = get_property_type (prop);
7577 MonoDomain *domain = mono_object_domain (property);
7578 MonoTypeEnum def_type;
7579 const char *def_value;
7582 mono_class_init (prop->parent);
7584 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7585 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7589 def_value = mono_class_get_property_default_value (prop, &def_type);
7591 mono_type_from_blob_type (&blob_type, def_type, type);
7592 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7597 ICALL_EXPORT MonoBoolean
7598 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7600 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7601 MonoCustomAttrInfo *cinfo;
7604 mono_class_init_or_throw (attr_class);
7606 cinfo = mono_reflection_get_custom_attrs_info (obj);
7609 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7611 mono_custom_attrs_free (cinfo);
7615 ICALL_EXPORT MonoArray*
7616 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7618 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7623 mono_class_init_or_throw (attr_class);
7625 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7626 if (!mono_error_ok (&error)) {
7627 mono_error_set_pending_exception (&error);
7631 if (mono_loader_get_last_error ()) {
7632 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7639 ICALL_EXPORT MonoString*
7640 ves_icall_Mono_Runtime_GetDisplayName (void)
7643 MonoString *display_name;
7645 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7646 display_name = mono_string_new (mono_domain_get (), info);
7648 return display_name;
7651 ICALL_EXPORT MonoString*
7652 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7655 MonoString *message;
7659 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7660 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7663 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7665 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7666 mono_error_raise_exception (&error);
7673 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7676 char *path_str = mono_string_to_utf8 (path);
7678 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7686 #ifndef DISABLE_ICALL_TABLES
7688 #define ICALL_TYPE(id,name,first)
7689 #define ICALL(id,name,func) Icall_ ## id,
7692 #include "metadata/icall-def.h"
7698 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7699 #define ICALL(id,name,func)
7701 #include "metadata/icall-def.h"
7707 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7708 #define ICALL(id,name,func)
7710 guint16 first_icall;
7713 static const IcallTypeDesc
7714 icall_type_descs [] = {
7715 #include "metadata/icall-def.h"
7719 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7722 #define ICALL_TYPE(id,name,first)
7725 #ifdef HAVE_ARRAY_ELEM_INIT
7726 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7727 #define MSGSTRFIELD1(line) str##line
7729 static const struct msgstrtn_t {
7730 #define ICALL(id,name,func)
7732 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7733 #include "metadata/icall-def.h"
7735 } icall_type_names_str = {
7736 #define ICALL_TYPE(id,name,first) (name),
7737 #include "metadata/icall-def.h"
7740 static const guint16 icall_type_names_idx [] = {
7741 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7742 #include "metadata/icall-def.h"
7745 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7747 static const struct msgstr_t {
7749 #define ICALL_TYPE(id,name,first)
7750 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7751 #include "metadata/icall-def.h"
7753 } icall_names_str = {
7754 #define ICALL(id,name,func) (name),
7755 #include "metadata/icall-def.h"
7758 static const guint16 icall_names_idx [] = {
7759 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7760 #include "metadata/icall-def.h"
7763 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7769 #define ICALL_TYPE(id,name,first) name,
7770 #define ICALL(id,name,func)
7771 static const char* const
7772 icall_type_names [] = {
7773 #include "metadata/icall-def.h"
7777 #define icall_type_name_get(id) (icall_type_names [(id)])
7781 #define ICALL_TYPE(id,name,first)
7782 #define ICALL(id,name,func) name,
7783 static const char* const
7785 #include "metadata/icall-def.h"
7788 #define icall_name_get(id) icall_names [(id)]
7790 #endif /* !HAVE_ARRAY_ELEM_INIT */
7794 #define ICALL_TYPE(id,name,first)
7795 #define ICALL(id,name,func) func,
7796 static const gconstpointer
7797 icall_functions [] = {
7798 #include "metadata/icall-def.h"
7802 #ifdef ENABLE_ICALL_SYMBOL_MAP
7805 #define ICALL_TYPE(id,name,first)
7806 #define ICALL(id,name,func) #func,
7807 static const gconstpointer
7808 icall_symbols [] = {
7809 #include "metadata/icall-def.h"
7814 #endif /* DISABLE_ICALL_TABLES */
7816 static mono_mutex_t icall_mutex;
7817 static GHashTable *icall_hash = NULL;
7818 static GHashTable *jit_icall_hash_name = NULL;
7819 static GHashTable *jit_icall_hash_addr = NULL;
7822 mono_icall_init (void)
7824 #ifndef DISABLE_ICALL_TABLES
7827 /* check that tables are sorted: disable in release */
7830 const char *prev_class = NULL;
7831 const char *prev_method;
7833 for (i = 0; i < Icall_type_num; ++i) {
7834 const IcallTypeDesc *desc;
7837 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7838 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7839 prev_class = icall_type_name_get (i);
7840 desc = &icall_type_descs [i];
7841 num_icalls = icall_desc_num_icalls (desc);
7842 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7843 for (j = 0; j < num_icalls; ++j) {
7844 const char *methodn = icall_name_get (desc->first_icall + j);
7845 if (prev_method && strcmp (prev_method, methodn) >= 0)
7846 g_print ("method %s should come before method %s\n", methodn, prev_method);
7847 prev_method = methodn;
7853 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7854 mono_os_mutex_init (&icall_mutex);
7858 mono_icall_lock (void)
7860 mono_locks_os_acquire (&icall_mutex, IcallLock);
7864 mono_icall_unlock (void)
7866 mono_locks_os_release (&icall_mutex, IcallLock);
7870 mono_icall_cleanup (void)
7872 g_hash_table_destroy (icall_hash);
7873 g_hash_table_destroy (jit_icall_hash_name);
7874 g_hash_table_destroy (jit_icall_hash_addr);
7875 mono_os_mutex_destroy (&icall_mutex);
7879 mono_add_internal_call (const char *name, gconstpointer method)
7883 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7885 mono_icall_unlock ();
7888 #ifndef DISABLE_ICALL_TABLES
7890 #ifdef HAVE_ARRAY_ELEM_INIT
7892 compare_method_imap (const void *key, const void *elem)
7894 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7895 return strcmp (key, method_name);
7899 find_method_icall (const IcallTypeDesc *imap, const char *name)
7901 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);
7904 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7908 compare_class_imap (const void *key, const void *elem)
7910 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7911 return strcmp (key, class_name);
7914 static const IcallTypeDesc*
7915 find_class_icalls (const char *name)
7917 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);
7920 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7923 #else /* HAVE_ARRAY_ELEM_INIT */
7926 compare_method_imap (const void *key, const void *elem)
7928 const char** method_name = (const char**)elem;
7929 return strcmp (key, *method_name);
7933 find_method_icall (const IcallTypeDesc *imap, const char *name)
7935 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7938 return (gpointer)icall_functions [(nameslot - icall_names)];
7942 compare_class_imap (const void *key, const void *elem)
7944 const char** class_name = (const char**)elem;
7945 return strcmp (key, *class_name);
7948 static const IcallTypeDesc*
7949 find_class_icalls (const char *name)
7951 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7954 return &icall_type_descs [nameslot - icall_type_names];
7957 #endif /* HAVE_ARRAY_ELEM_INIT */
7959 #endif /* DISABLE_ICALL_TABLES */
7962 * we should probably export this as an helper (handle nested types).
7963 * Returns the number of chars written in buf.
7966 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7968 int nspacelen, cnamelen;
7969 nspacelen = strlen (klass->name_space);
7970 cnamelen = strlen (klass->name);
7971 if (nspacelen + cnamelen + 2 > bufsize)
7974 memcpy (buf, klass->name_space, nspacelen);
7975 buf [nspacelen ++] = '.';
7977 memcpy (buf + nspacelen, klass->name, cnamelen);
7978 buf [nspacelen + cnamelen] = 0;
7979 return nspacelen + cnamelen;
7982 #ifdef DISABLE_ICALL_TABLES
7984 no_icall_table (void)
7986 g_assert_not_reached ();
7991 mono_lookup_internal_call (MonoMethod *method)
7996 int typelen = 0, mlen, siglen;
7998 #ifndef DISABLE_ICALL_TABLES
7999 const IcallTypeDesc *imap = NULL;
8002 g_assert (method != NULL);
8004 if (method->is_inflated)
8005 method = ((MonoMethodInflated *) method)->declaring;
8007 if (method->klass->nested_in) {
8008 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8012 mname [pos++] = '/';
8015 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8021 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8026 #ifndef DISABLE_ICALL_TABLES
8027 imap = find_class_icalls (mname);
8030 mname [typelen] = ':';
8031 mname [typelen + 1] = ':';
8033 mlen = strlen (method->name);
8034 memcpy (mname + typelen + 2, method->name, mlen);
8035 sigstart = mname + typelen + 2 + mlen;
8038 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8039 siglen = strlen (tmpsig);
8040 if (typelen + mlen + siglen + 6 > sizeof (mname))
8043 memcpy (sigstart + 1, tmpsig, siglen);
8044 sigstart [siglen + 1] = ')';
8045 sigstart [siglen + 2] = 0;
8050 res = g_hash_table_lookup (icall_hash, mname);
8052 mono_icall_unlock ();;
8055 /* try without signature */
8057 res = g_hash_table_lookup (icall_hash, mname);
8059 mono_icall_unlock ();
8063 #ifdef DISABLE_ICALL_TABLES
8064 mono_icall_unlock ();
8065 /* Fail only when the result is actually used */
8066 /* mono_marshal_get_native_wrapper () depends on this */
8067 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8068 return ves_icall_System_String_ctor_RedirectToCreateString;
8070 return no_icall_table;
8072 /* it wasn't found in the static call tables */
8074 mono_icall_unlock ();
8077 res = find_method_icall (imap, sigstart - mlen);
8079 mono_icall_unlock ();
8082 /* try _with_ signature */
8084 res = find_method_icall (imap, sigstart - mlen);
8086 mono_icall_unlock ();
8090 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8091 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8092 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8093 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8094 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");
8095 g_print ("If you see other errors or faults after this message they are probably related\n");
8096 g_print ("and you need to fix your mono install first.\n");
8098 mono_icall_unlock ();
8104 #ifdef ENABLE_ICALL_SYMBOL_MAP
8106 func_cmp (gconstpointer key, gconstpointer p)
8108 return (gsize)key - (gsize)*(gsize*)p;
8113 * mono_lookup_icall_symbol:
8115 * Given the icall METHOD, returns its C symbol.
8118 mono_lookup_icall_symbol (MonoMethod *m)
8120 #ifdef DISABLE_ICALL_TABLES
8121 g_assert_not_reached ();
8124 #ifdef ENABLE_ICALL_SYMBOL_MAP
8128 static gconstpointer *functions_sorted;
8129 static const char**symbols_sorted;
8130 static gboolean inited;
8135 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8136 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8137 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8138 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8139 /* Bubble sort the two arrays */
8143 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8144 if (functions_sorted [i] > functions_sorted [i + 1]) {
8147 tmp = functions_sorted [i];
8148 functions_sorted [i] = functions_sorted [i + 1];
8149 functions_sorted [i + 1] = tmp;
8150 tmp = symbols_sorted [i];
8151 symbols_sorted [i] = symbols_sorted [i + 1];
8152 symbols_sorted [i + 1] = tmp;
8159 func = mono_lookup_internal_call (m);
8162 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8166 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8168 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8169 g_assert_not_reached ();
8176 type_from_typename (char *type_name)
8178 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8180 if (!strcmp (type_name, "int"))
8181 klass = mono_defaults.int_class;
8182 else if (!strcmp (type_name, "ptr"))
8183 klass = mono_defaults.int_class;
8184 else if (!strcmp (type_name, "void"))
8185 klass = mono_defaults.void_class;
8186 else if (!strcmp (type_name, "int32"))
8187 klass = mono_defaults.int32_class;
8188 else if (!strcmp (type_name, "uint32"))
8189 klass = mono_defaults.uint32_class;
8190 else if (!strcmp (type_name, "int8"))
8191 klass = mono_defaults.sbyte_class;
8192 else if (!strcmp (type_name, "uint8"))
8193 klass = mono_defaults.byte_class;
8194 else if (!strcmp (type_name, "int16"))
8195 klass = mono_defaults.int16_class;
8196 else if (!strcmp (type_name, "uint16"))
8197 klass = mono_defaults.uint16_class;
8198 else if (!strcmp (type_name, "long"))
8199 klass = mono_defaults.int64_class;
8200 else if (!strcmp (type_name, "ulong"))
8201 klass = mono_defaults.uint64_class;
8202 else if (!strcmp (type_name, "float"))
8203 klass = mono_defaults.single_class;
8204 else if (!strcmp (type_name, "double"))
8205 klass = mono_defaults.double_class;
8206 else if (!strcmp (type_name, "object"))
8207 klass = mono_defaults.object_class;
8208 else if (!strcmp (type_name, "obj"))
8209 klass = mono_defaults.object_class;
8210 else if (!strcmp (type_name, "string"))
8211 klass = mono_defaults.string_class;
8212 else if (!strcmp (type_name, "bool"))
8213 klass = mono_defaults.boolean_class;
8214 else if (!strcmp (type_name, "boolean"))
8215 klass = mono_defaults.boolean_class;
8217 g_error ("%s", type_name);
8218 g_assert_not_reached ();
8220 return &klass->byval_arg;
8224 * LOCKING: Take the corlib image lock.
8226 MonoMethodSignature*
8227 mono_create_icall_signature (const char *sigstr)
8232 MonoMethodSignature *res, *res2;
8233 MonoImage *corlib = mono_defaults.corlib;
8235 mono_image_lock (corlib);
8236 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8237 mono_image_unlock (corlib);
8242 parts = g_strsplit (sigstr, " ", 256);
8251 res = mono_metadata_signature_alloc (corlib, len - 1);
8256 * Under windows, the default pinvoke calling convention is STDCALL but
8259 res->call_convention = MONO_CALL_C;
8262 res->ret = type_from_typename (parts [0]);
8263 for (i = 1; i < len; ++i) {
8264 res->params [i - 1] = type_from_typename (parts [i]);
8269 mono_image_lock (corlib);
8270 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8272 res = res2; /*Value is allocated in the image pool*/
8274 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8275 mono_image_unlock (corlib);
8281 mono_find_jit_icall_by_name (const char *name)
8283 MonoJitICallInfo *info;
8284 g_assert (jit_icall_hash_name);
8287 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8288 mono_icall_unlock ();
8293 mono_find_jit_icall_by_addr (gconstpointer addr)
8295 MonoJitICallInfo *info;
8296 g_assert (jit_icall_hash_addr);
8299 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8300 mono_icall_unlock ();
8306 * mono_get_jit_icall_info:
8308 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8309 * caller should access it while holding the icall lock.
8312 mono_get_jit_icall_info (void)
8314 return jit_icall_hash_name;
8318 * mono_lookup_jit_icall_symbol:
8320 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8323 mono_lookup_jit_icall_symbol (const char *name)
8325 MonoJitICallInfo *info;
8326 const char *res = NULL;
8329 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8331 res = info->c_symbol;
8332 mono_icall_unlock ();
8337 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8340 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8341 mono_icall_unlock ();
8345 * 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
8346 * icalls without wrappers in some cases.
8349 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8351 MonoJitICallInfo *info;
8358 if (!jit_icall_hash_name) {
8359 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8360 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8363 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8364 g_warning ("jit icall already defined \"%s\"\n", name);
8365 g_assert_not_reached ();
8368 info = g_new0 (MonoJitICallInfo, 1);
8373 info->c_symbol = c_symbol;
8374 info->no_raise = no_raise;
8377 info->wrapper = func;
8379 info->wrapper = NULL;
8382 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8383 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8385 mono_icall_unlock ();
8390 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8392 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);