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)
2410 MonoReflectionModule *result = NULL;
2411 MonoClass *klass = mono_class_from_mono_type (type->type);
2412 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2413 if (!mono_error_ok (&error))
2414 mono_error_set_pending_exception (&error);
2418 ICALL_EXPORT MonoReflectionAssembly*
2419 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2421 MonoDomain *domain = mono_domain_get ();
2422 MonoClass *klass = mono_class_from_mono_type (type->type);
2423 return mono_assembly_get_object (domain, klass->image->assembly);
2426 ICALL_EXPORT MonoReflectionType*
2427 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2430 MonoReflectionType *ret;
2431 MonoDomain *domain = mono_domain_get ();
2434 if (type->type->byref)
2436 if (type->type->type == MONO_TYPE_VAR) {
2437 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2438 klass = param ? param->owner.klass : NULL;
2439 } else if (type->type->type == MONO_TYPE_MVAR) {
2440 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2441 klass = param ? param->owner.method->klass : NULL;
2443 klass = mono_class_from_mono_type (type->type)->nested_in;
2449 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2450 mono_error_raise_exception (&error);
2455 ICALL_EXPORT MonoString*
2456 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2458 MonoDomain *domain = mono_domain_get ();
2459 MonoClass *klass = mono_class_from_mono_type (type->type);
2461 if (type->type->byref) {
2462 char *n = g_strdup_printf ("%s&", klass->name);
2463 MonoString *res = mono_string_new (domain, n);
2469 return mono_string_new (domain, klass->name);
2473 ICALL_EXPORT MonoString*
2474 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2476 MonoDomain *domain = mono_domain_get ();
2477 MonoClass *klass = mono_class_from_mono_type (type->type);
2479 while (klass->nested_in)
2480 klass = klass->nested_in;
2482 if (klass->name_space [0] == '\0')
2485 return mono_string_new (domain, klass->name_space);
2489 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2493 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2494 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2498 klass = mono_class_from_mono_type (type->type);
2504 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2507 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2511 ICALL_EXPORT MonoArray*
2512 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2515 MonoReflectionType *rt;
2517 MonoClass *klass, *pklass;
2518 MonoDomain *domain = mono_object_domain (type);
2521 klass = mono_class_from_mono_type (type->type);
2523 if (klass->generic_container) {
2524 MonoGenericContainer *container = klass->generic_container;
2525 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2526 for (i = 0; i < container->type_argc; ++i) {
2527 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2529 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2530 mono_error_raise_exception (&error);
2532 mono_array_setref (res, i, rt);
2534 } else if (klass->generic_class) {
2535 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2536 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2537 for (i = 0; i < inst->type_argc; ++i) {
2538 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2539 mono_error_raise_exception (&error);
2541 mono_array_setref (res, i, rt);
2549 ICALL_EXPORT gboolean
2550 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2554 if (!IS_MONOTYPE (type))
2557 if (type->type->byref)
2560 klass = mono_class_from_mono_type (type->type);
2561 return klass->generic_container != NULL;
2564 ICALL_EXPORT MonoReflectionType*
2565 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2568 MonoReflectionType *ret;
2571 if (type->type->byref)
2574 klass = mono_class_from_mono_type (type->type);
2576 if (klass->generic_container) {
2577 return type; /* check this one */
2579 if (klass->generic_class) {
2580 MonoClass *generic_class = klass->generic_class->container_class;
2583 tb = mono_class_get_ref_info (generic_class);
2585 if (generic_class->wastypebuilder && tb)
2586 return (MonoReflectionType *)tb;
2588 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2589 mono_error_raise_exception (&error);
2597 ICALL_EXPORT MonoReflectionType*
2598 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2601 MonoReflectionType *ret;
2603 MonoType *geninst, **types;
2606 g_assert (IS_MONOTYPE (type));
2607 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2609 count = mono_array_length (type_array);
2610 types = g_new0 (MonoType *, count);
2612 for (i = 0; i < count; i++) {
2613 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2614 types [i] = t->type;
2617 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2622 klass = mono_class_from_mono_type (geninst);
2624 /*we might inflate to the GTD*/
2625 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2626 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2630 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2631 mono_error_raise_exception (&error);
2636 ICALL_EXPORT gboolean
2637 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2641 if (!IS_MONOTYPE (type))
2644 if (type->type->byref)
2647 klass = mono_class_from_mono_type (type->type);
2648 return klass->generic_class != NULL || klass->generic_container != NULL;
2652 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2654 if (!IS_MONOTYPE (type))
2657 if (is_generic_parameter (type->type))
2658 return mono_type_get_generic_param_num (type->type);
2662 ICALL_EXPORT GenericParameterAttributes
2663 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2665 g_assert (IS_MONOTYPE (type));
2666 g_assert (is_generic_parameter (type->type));
2667 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2670 ICALL_EXPORT MonoArray *
2671 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2674 MonoReflectionType *rt;
2675 MonoGenericParamInfo *param_info;
2681 g_assert (IS_MONOTYPE (type));
2683 domain = mono_object_domain (type);
2684 param_info = mono_generic_param_info (type->type->data.generic_param);
2685 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2688 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2689 for (i = 0; i < count; i++) {
2690 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2691 mono_error_raise_exception (&error);
2693 mono_array_setref (res, i, rt);
2700 ICALL_EXPORT MonoBoolean
2701 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2703 return is_generic_parameter (type->type);
2706 ICALL_EXPORT MonoBoolean
2707 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2709 return is_generic_parameter (tb->type.type);
2713 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2714 MonoReflectionType *t)
2716 enumtype->type = t->type;
2719 ICALL_EXPORT MonoReflectionMethod*
2720 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2721 MonoReflectionMethod* generic)
2728 MonoReflectionMethod *ret = NULL;
2730 domain = ((MonoObject *)type)->vtable->domain;
2732 klass = mono_class_from_mono_type (type->type);
2733 mono_class_init_or_throw (klass);
2736 while ((method = mono_class_get_methods (klass, &iter))) {
2737 if (method->token == generic->method->token) {
2738 ret = mono_method_get_object_checked (domain, method, klass, &error);
2739 mono_error_raise_exception (&error);
2746 ICALL_EXPORT MonoReflectionMethod *
2747 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2750 MonoType *type = ref_type->type;
2752 MonoReflectionMethod *ret = NULL;
2754 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2755 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2758 if (type->type == MONO_TYPE_VAR)
2761 method = mono_type_get_generic_param_owner (type)->owner.method;
2764 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2765 if (!mono_error_ok (&error))
2766 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2770 ICALL_EXPORT MonoBoolean
2771 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2773 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2777 ICALL_EXPORT MonoBoolean
2778 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2780 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2785 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2787 MonoDomain *domain = mono_domain_get ();
2788 MonoImage *image = method->method->klass->image;
2789 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2790 MonoTableInfo *tables = image->tables;
2791 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2792 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2793 guint32 im_cols [MONO_IMPLMAP_SIZE];
2794 guint32 scope_token;
2795 const char *import = NULL;
2796 const char *scope = NULL;
2798 if (image_is_dynamic (image)) {
2799 MonoReflectionMethodAux *method_aux =
2800 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2802 import = method_aux->dllentry;
2803 scope = method_aux->dll;
2806 if (!import || !scope) {
2807 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2812 if (piinfo->implmap_idx) {
2813 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2815 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2816 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2817 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2818 scope = mono_metadata_string_heap (image, scope_token);
2822 *flags = piinfo->piflags;
2823 *entry_point = mono_string_new (domain, import);
2824 *dll_name = mono_string_new (domain, scope);
2827 ICALL_EXPORT MonoReflectionMethod *
2828 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2830 MonoMethodInflated *imethod;
2832 MonoReflectionMethod *ret = NULL;
2835 if (method->method->is_generic)
2838 if (!method->method->is_inflated)
2841 imethod = (MonoMethodInflated *) method->method;
2843 result = imethod->declaring;
2844 /* Not a generic method. */
2845 if (!result->is_generic)
2848 if (image_is_dynamic (method->method->klass->image)) {
2849 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2850 MonoReflectionMethod *res;
2853 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2854 * the dynamic case as well ?
2856 mono_image_lock ((MonoImage*)image);
2857 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2858 mono_image_unlock ((MonoImage*)image);
2864 if (imethod->context.class_inst) {
2865 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2866 /*Generic methods gets the context of the GTD.*/
2867 if (mono_class_get_context (klass)) {
2868 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2869 if (!mono_error_ok (&error))
2874 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2876 if (!mono_error_ok (&error))
2877 mono_error_set_pending_exception (&error);
2881 ICALL_EXPORT gboolean
2882 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2884 return mono_method_signature (method->method)->generic_param_count != 0;
2887 ICALL_EXPORT gboolean
2888 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2890 return method->method->is_generic;
2893 ICALL_EXPORT MonoArray*
2894 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2897 MonoReflectionType *rt;
2902 domain = mono_object_domain (method);
2904 if (method->method->is_inflated) {
2905 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2908 count = inst->type_argc;
2909 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2911 for (i = 0; i < count; i++) {
2912 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2913 mono_error_raise_exception (&error);
2915 mono_array_setref (res, i, rt);
2922 count = mono_method_signature (method->method)->generic_param_count;
2923 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2925 for (i = 0; i < count; i++) {
2926 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2927 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2928 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
2930 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2931 mono_error_raise_exception (&error);
2933 mono_array_setref (res, i, rt);
2939 ICALL_EXPORT MonoObject *
2940 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
2944 * Invoke from reflection is supposed to always be a virtual call (the API
2945 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2946 * greater flexibility.
2948 MonoMethod *m = method->method;
2949 MonoMethodSignature *sig = mono_method_signature (m);
2952 void *obj = this_arg;
2956 if (mono_security_core_clr_enabled ())
2957 mono_security_core_clr_ensure_reflection_access_method (m);
2959 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2960 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2961 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2966 if (!mono_object_isinst (this_arg, m->klass)) {
2967 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
2968 char *target_name = mono_type_get_full_name (m->klass);
2969 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2970 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2972 g_free (target_name);
2976 m = mono_object_get_virtual_method (this_arg, m);
2977 /* must pass the pointer to the value for valuetype methods */
2978 if (m->klass->valuetype)
2979 obj = mono_object_unbox (this_arg);
2980 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2981 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2986 if (sig->ret->byref) {
2987 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"));
2991 pcount = params? mono_array_length (params): 0;
2992 if (pcount != sig->param_count) {
2993 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2997 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
2998 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."));
3002 image = m->klass->image;
3003 if (image->assembly->ref_only) {
3004 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."));
3008 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3009 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3013 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3017 intptr_t *lower_bounds;
3018 pcount = mono_array_length (params);
3019 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3020 /* Note: the synthetized array .ctors have int32 as argument type */
3021 for (i = 0; i < pcount; ++i)
3022 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3024 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3025 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3026 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3027 if (!mono_error_ok (&error)) {
3028 mono_error_set_pending_exception (&error);
3032 for (i = 0; i < mono_array_length (arr); ++i) {
3033 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3034 if (!mono_error_ok (&error)) {
3035 mono_error_set_pending_exception (&error);
3038 mono_array_setref_fast (arr, i, subarray);
3040 return (MonoObject*)arr;
3043 if (m->klass->rank == pcount) {
3044 /* Only lengths provided. */
3045 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3046 if (!mono_error_ok (&error)) {
3047 mono_error_set_pending_exception (&error);
3051 return (MonoObject*)arr;
3053 g_assert (pcount == (m->klass->rank * 2));
3054 /* The arguments are lower-bound-length pairs */
3055 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3057 for (i = 0; i < pcount / 2; ++i) {
3058 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3059 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3062 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3063 if (!mono_error_ok (&error)) {
3064 mono_error_set_pending_exception (&error);
3068 return (MonoObject*)arr;
3071 return mono_runtime_invoke_array (m, obj, params, NULL);
3074 #ifndef DISABLE_REMOTING
3075 ICALL_EXPORT MonoObject *
3076 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3078 MonoDomain *domain = mono_object_domain (method);
3079 MonoMethod *m = method->method;
3080 MonoMethodSignature *sig = mono_method_signature (m);
3081 MonoArray *out_args;
3083 int i, j, outarg_count = 0;
3085 if (m->klass == mono_defaults.object_class) {
3086 if (!strcmp (m->name, "FieldGetter")) {
3087 MonoClass *k = this_arg->vtable->klass;
3091 /* If this is a proxy, then it must be a CBO */
3092 if (k == mono_defaults.transparent_proxy_class) {
3093 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3094 this_arg = tp->rp->unwrapped_server;
3095 g_assert (this_arg);
3096 k = this_arg->vtable->klass;
3099 name = mono_array_get (params, MonoString *, 1);
3100 str = mono_string_to_utf8 (name);
3103 MonoClassField* field = mono_class_get_field_from_name (k, str);
3105 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3106 if (field_klass->valuetype)
3107 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
3109 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3111 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3112 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3113 mono_array_setref (out_args, 0, result);
3121 g_assert_not_reached ();
3123 } else if (!strcmp (m->name, "FieldSetter")) {
3124 MonoClass *k = this_arg->vtable->klass;
3130 /* If this is a proxy, then it must be a CBO */
3131 if (k == mono_defaults.transparent_proxy_class) {
3132 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3133 this_arg = tp->rp->unwrapped_server;
3134 g_assert (this_arg);
3135 k = this_arg->vtable->klass;
3138 name = mono_array_get (params, MonoString *, 1);
3139 str = mono_string_to_utf8 (name);
3142 MonoClassField* field = mono_class_get_field_from_name (k, str);
3144 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3145 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3147 if (field_klass->valuetype) {
3148 size = mono_type_size (field->type, &align);
3149 g_assert (size == mono_class_value_size (field_klass, NULL));
3150 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3152 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3155 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3156 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3166 g_assert_not_reached ();
3171 for (i = 0; i < mono_array_length (params); i++) {
3172 if (sig->params [i]->byref)
3176 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3178 /* handle constructors only for objects already allocated */
3179 if (!strcmp (method->method->name, ".ctor"))
3180 g_assert (this_arg);
3182 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3183 g_assert (!method->method->klass->valuetype);
3184 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3186 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3187 if (sig->params [i]->byref) {
3189 arg = mono_array_get (params, gpointer, i);
3190 mono_array_setref (out_args, j, arg);
3195 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3202 read_enum_value (const char *mem, int type)
3205 case MONO_TYPE_BOOLEAN:
3207 return *(guint8*)mem;
3209 return *(gint8*)mem;
3210 case MONO_TYPE_CHAR:
3212 return read16 (mem);
3214 return (gint16) read16 (mem);
3216 return read32 (mem);
3218 return (gint32) read32 (mem);
3221 return read64 (mem);
3223 g_assert_not_reached ();
3229 write_enum_value (char *mem, int type, guint64 value)
3233 case MONO_TYPE_I1: {
3234 guint8 *p = (guint8*)mem;
3239 case MONO_TYPE_I2: {
3240 guint16 *p = (guint16 *)mem;
3245 case MONO_TYPE_I4: {
3246 guint32 *p = (guint32 *)mem;
3251 case MONO_TYPE_I8: {
3252 guint64 *p = (guint64 *)mem;
3257 g_assert_not_reached ();
3262 ICALL_EXPORT MonoObject *
3263 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3271 domain = mono_object_domain (enumType);
3272 enumc = mono_class_from_mono_type (enumType->type);
3274 mono_class_init_or_throw (enumc);
3276 etype = mono_class_enum_basetype (enumc);
3278 res = mono_object_new_checked (domain, enumc, &error);
3279 mono_error_raise_exception (&error);
3280 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3285 ICALL_EXPORT MonoBoolean
3286 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3288 int size = mono_class_value_size (a->vtable->klass, NULL);
3289 guint64 a_val = 0, b_val = 0;
3291 memcpy (&a_val, mono_object_unbox (a), size);
3292 memcpy (&b_val, mono_object_unbox (b), size);
3294 return (a_val & b_val) == b_val;
3297 ICALL_EXPORT MonoObject *
3298 ves_icall_System_Enum_get_value (MonoObject *eobj)
3310 g_assert (eobj->vtable->klass->enumtype);
3312 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3313 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3314 mono_error_raise_exception (&error);
3315 dst = (char *)res + sizeof (MonoObject);
3316 src = (char *)eobj + sizeof (MonoObject);
3317 size = mono_class_value_size (enumc, NULL);
3319 memcpy (dst, src, size);
3324 ICALL_EXPORT MonoReflectionType *
3325 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3328 MonoReflectionType *ret;
3332 klass = mono_class_from_mono_type (type->type);
3333 mono_class_init_or_throw (klass);
3335 etype = mono_class_enum_basetype (klass);
3337 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3341 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3342 mono_error_raise_exception (&error);
3348 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3350 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3351 gpointer odata = (char *)other + sizeof (MonoObject);
3352 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3353 g_assert (basetype);
3358 if (eobj->vtable->klass != other->vtable->klass)
3361 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3362 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3363 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3366 return me > other ? 1 : -1; \
3369 switch (basetype->type) {
3371 COMPARE_ENUM_VALUES (guint8);
3373 COMPARE_ENUM_VALUES (gint8);
3374 case MONO_TYPE_CHAR:
3376 COMPARE_ENUM_VALUES (guint16);
3378 COMPARE_ENUM_VALUES (gint16);
3380 COMPARE_ENUM_VALUES (guint32);
3382 COMPARE_ENUM_VALUES (gint32);
3384 COMPARE_ENUM_VALUES (guint64);
3386 COMPARE_ENUM_VALUES (gint64);
3390 #undef COMPARE_ENUM_VALUES
3391 /* indicates that the enum was of an unsupported unerlying type */
3396 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3398 gpointer data = (char *)eobj + sizeof (MonoObject);
3399 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3400 g_assert (basetype);
3402 switch (basetype->type) {
3403 case MONO_TYPE_I1: {
3404 gint8 value = *((gint8*)data);
3405 return ((int)value ^ (int)value << 8);
3408 return *((guint8*)data);
3409 case MONO_TYPE_CHAR:
3411 return *((guint16*)data);
3413 case MONO_TYPE_I2: {
3414 gint16 value = *((gint16*)data);
3415 return ((int)(guint16)value | (((int)value) << 16));
3418 return *((guint32*)data);
3420 return *((gint32*)data);
3422 case MONO_TYPE_I8: {
3423 gint64 value = *((gint64*)data);
3424 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3427 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3432 ICALL_EXPORT MonoBoolean
3433 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3435 MonoDomain *domain = mono_object_domain (type);
3436 MonoClass *enumc = mono_class_from_mono_type (type->type);
3437 guint j = 0, nvalues;
3439 MonoClassField *field;
3441 guint64 field_value, previous_value = 0;
3442 gboolean sorted = TRUE;
3444 mono_class_init_or_throw (enumc);
3446 if (!enumc->enumtype) {
3447 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3451 base_type = mono_class_enum_basetype (enumc)->type;
3453 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3454 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3455 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3458 while ((field = mono_class_get_fields (enumc, &iter))) {
3460 MonoTypeEnum def_type;
3462 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3464 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3466 if (mono_field_is_deleted (field))
3468 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3470 p = mono_class_get_field_default_value (field, &def_type);
3471 /* len = */ mono_metadata_decode_blob_size (p, &p);
3473 field_value = read_enum_value (p, base_type);
3474 mono_array_set (*values, guint64, j, field_value);
3476 if (previous_value > field_value)
3479 previous_value = field_value;
3487 BFLAGS_IgnoreCase = 1,
3488 BFLAGS_DeclaredOnly = 2,
3489 BFLAGS_Instance = 4,
3491 BFLAGS_Public = 0x10,
3492 BFLAGS_NonPublic = 0x20,
3493 BFLAGS_FlattenHierarchy = 0x40,
3494 BFLAGS_InvokeMethod = 0x100,
3495 BFLAGS_CreateInstance = 0x200,
3496 BFLAGS_GetField = 0x400,
3497 BFLAGS_SetField = 0x800,
3498 BFLAGS_GetProperty = 0x1000,
3499 BFLAGS_SetProperty = 0x2000,
3500 BFLAGS_ExactBinding = 0x10000,
3501 BFLAGS_SuppressChangeType = 0x20000,
3502 BFLAGS_OptionalParamBinding = 0x40000
3505 ICALL_EXPORT MonoArray*
3506 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3510 MonoClass *startklass, *klass, *refklass;
3515 char *utf8_name = NULL;
3516 int (*compare_func) (const char *s1, const char *s2) = NULL;
3517 MonoClassField *field;
3518 MonoPtrArray tmp_array;
3520 domain = ((MonoObject *)type)->vtable->domain;
3521 if (type->type->byref)
3522 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3524 klass = startklass = mono_class_from_mono_type (type->type);
3525 refklass = mono_class_from_mono_type (reftype->type);
3527 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3530 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3531 mono_ptr_array_destroy (tmp_array);
3532 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3537 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3538 guint32 flags = mono_field_get_flags (field);
3540 if (mono_field_is_deleted_with_flags (field, flags))
3542 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3543 if (bflags & BFLAGS_Public)
3545 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3546 if (bflags & BFLAGS_NonPublic) {
3553 if (flags & FIELD_ATTRIBUTE_STATIC) {
3554 if (bflags & BFLAGS_Static)
3555 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3558 if (bflags & BFLAGS_Instance)
3566 if (utf8_name == NULL) {
3567 utf8_name = mono_string_to_utf8 (name);
3568 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3571 if (compare_func (mono_field_get_name (field), utf8_name))
3575 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3576 if (!mono_error_ok (&error))
3578 mono_ptr_array_append (tmp_array, member);
3580 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3583 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3585 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3586 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3588 mono_ptr_array_destroy (tmp_array);
3590 if (utf8_name != NULL)
3595 mono_ptr_array_destroy (tmp_array);
3596 mono_error_raise_exception (&error);
3597 g_assert_not_reached ();
3601 method_nonpublic (MonoMethod* method, gboolean start_klass)
3603 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3604 case METHOD_ATTRIBUTE_ASSEM:
3605 return (start_klass || mono_defaults.generic_ilist_class);
3606 case METHOD_ATTRIBUTE_PRIVATE:
3608 case METHOD_ATTRIBUTE_PUBLIC:
3616 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3619 MonoClass *startklass;
3623 /*FIXME, use MonoBitSet*/
3624 guint32 method_slots_default [8];
3625 guint32 *method_slots = NULL;
3626 int (*compare_func) (const char *s1, const char *s2) = NULL;
3628 array = g_ptr_array_new ();
3633 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3635 /* An optimization for calls made from Delegate:CreateDelegate () */
3636 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3637 method = mono_get_delegate_invoke (klass);
3638 if (mono_loader_get_last_error ())
3641 g_ptr_array_add (array, method);
3645 mono_class_setup_methods (klass);
3646 mono_class_setup_vtable (klass);
3647 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3650 if (is_generic_parameter (&klass->byval_arg))
3651 nslots = mono_class_get_vtable_size (klass->parent);
3653 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3654 if (nslots >= sizeof (method_slots_default) * 8) {
3655 method_slots = g_new0 (guint32, nslots / 32 + 1);
3657 method_slots = method_slots_default;
3658 memset (method_slots, 0, sizeof (method_slots_default));
3661 mono_class_setup_methods (klass);
3662 mono_class_setup_vtable (klass);
3663 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3667 while ((method = mono_class_get_methods (klass, &iter))) {
3669 if (method->slot != -1) {
3670 g_assert (method->slot < nslots);
3671 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3673 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3674 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3677 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3679 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3680 if (bflags & BFLAGS_Public)
3682 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3688 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3689 if (bflags & BFLAGS_Static)
3690 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3693 if (bflags & BFLAGS_Instance)
3701 if (compare_func (name, method->name))
3706 g_ptr_array_add (array, method);
3708 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3710 if (method_slots != method_slots_default)
3711 g_free (method_slots);
3716 if (method_slots != method_slots_default)
3717 g_free (method_slots);
3718 g_ptr_array_free (array, TRUE);
3720 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3721 *ex = mono_class_get_exception_for_failure (klass);
3723 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3724 mono_loader_clear_error ();
3729 ICALL_EXPORT MonoArray*
3730 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3732 static MonoClass *MethodInfo_array;
3736 MonoVTable *array_vtable;
3737 MonoException *ex = NULL;
3738 const char *mname = NULL;
3739 GPtrArray *method_array;
3740 MonoClass *klass, *refklass;
3743 mono_error_init (&error);
3745 if (!MethodInfo_array) {
3746 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3747 mono_memory_barrier ();
3748 MethodInfo_array = klass;
3751 klass = mono_class_from_mono_type (type->type);
3752 refklass = mono_class_from_mono_type (reftype->type);
3753 domain = ((MonoObject *)type)->vtable->domain;
3754 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3755 if (type->type->byref) {
3756 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3757 mono_error_set_pending_exception (&error);
3763 mname = mono_string_to_utf8 (name);
3765 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3766 g_free ((char*)mname);
3768 mono_set_pending_exception (ex);
3772 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3773 if (!mono_error_ok (&error)) {
3774 mono_error_set_pending_exception (&error);
3778 for (i = 0; i < method_array->len; ++i) {
3779 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3780 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3781 if (!mono_error_ok (&error))
3783 mono_array_setref (res, i, rm);
3787 g_ptr_array_free (method_array, TRUE);
3788 if (!mono_error_ok (&error))
3789 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3793 ICALL_EXPORT MonoArray*
3794 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3797 static MonoClass *System_Reflection_ConstructorInfo;
3798 MonoClass *startklass, *klass, *refklass;
3803 gpointer iter = NULL;
3804 MonoPtrArray tmp_array;
3807 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3809 domain = ((MonoObject *)type)->vtable->domain;
3810 if (type->type->byref)
3811 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3812 klass = startklass = mono_class_from_mono_type (type->type);
3813 refklass = mono_class_from_mono_type (reftype->type);
3815 if (!System_Reflection_ConstructorInfo)
3816 System_Reflection_ConstructorInfo = mono_class_from_name (
3817 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3819 mono_class_setup_methods (klass);
3820 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3821 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3826 while ((method = mono_class_get_methods (klass, &iter))) {
3828 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3830 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3831 if (bflags & BFLAGS_Public)
3834 if (bflags & BFLAGS_NonPublic)
3840 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3841 if (bflags & BFLAGS_Static)
3842 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3845 if (bflags & BFLAGS_Instance)
3851 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3852 if (!mono_error_ok (&error)) {
3853 mono_error_set_pending_exception (&error);
3857 mono_ptr_array_append (tmp_array, member);
3860 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3862 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3863 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3865 mono_ptr_array_destroy (tmp_array);
3871 property_hash (gconstpointer data)
3873 MonoProperty *prop = (MonoProperty*)data;
3875 return g_str_hash (prop->name);
3879 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3881 if (method1->is_inflated)
3882 method1 = ((MonoMethodInflated*) method1)->declaring;
3883 if (method2->is_inflated)
3884 method2 = ((MonoMethodInflated*) method2)->declaring;
3886 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3890 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3892 // Properties are hide-by-name-and-signature
3893 if (!g_str_equal (prop1->name, prop2->name))
3896 /* If we see a property in a generic method, we want to
3897 compare the generic signatures, not the inflated signatures
3898 because we might conflate two properties that were
3902 public T this[T t] { getter { return t; } } // method 1
3903 public U this[U u] { getter { return u; } } // method 2
3906 If we see int Foo<int,int>::Item[int] we need to know if
3907 the indexer came from method 1 or from method 2, and we
3908 shouldn't conflate them. (Bugzilla 36283)
3910 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
3913 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
3920 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3925 return method_nonpublic (accessor, start_klass);
3928 ICALL_EXPORT MonoArray*
3929 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3933 static MonoClass *System_Reflection_PropertyInfo;
3934 MonoClass *startklass, *klass;
3940 gchar *propname = NULL;
3941 int (*compare_func) (const char *s1, const char *s2) = NULL;
3943 GHashTable *properties = NULL;
3944 MonoPtrArray tmp_array;
3946 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
3948 if (!System_Reflection_PropertyInfo)
3949 System_Reflection_PropertyInfo = mono_class_from_name (
3950 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3952 domain = ((MonoObject *)type)->vtable->domain;
3953 if (type->type->byref)
3954 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3955 klass = startklass = mono_class_from_mono_type (type->type);
3958 propname = mono_string_to_utf8 (name);
3959 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3962 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3964 mono_class_setup_methods (klass);
3965 mono_class_setup_vtable (klass);
3966 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3970 while ((prop = mono_class_get_properties (klass, &iter))) {
3976 flags = method->flags;
3979 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3980 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3981 if (bflags & BFLAGS_Public)
3983 } else if (bflags & BFLAGS_NonPublic) {
3984 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3985 property_accessor_nonpublic(prop->set, startklass == klass)) {
3992 if (flags & METHOD_ATTRIBUTE_STATIC) {
3993 if (bflags & BFLAGS_Static)
3994 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3997 if (bflags & BFLAGS_Instance)
4006 if (compare_func (propname, prop->name))
4010 if (g_hash_table_lookup (properties, prop))
4013 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
4015 g_hash_table_insert (properties, prop, prop);
4017 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4020 g_hash_table_destroy (properties);
4023 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
4024 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4025 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4027 mono_ptr_array_destroy (tmp_array);
4033 g_hash_table_destroy (properties);
4036 mono_ptr_array_destroy (tmp_array);
4038 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4039 ex = mono_class_get_exception_for_failure (klass);
4041 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4042 mono_loader_clear_error ();
4044 mono_set_pending_exception (ex);
4049 event_hash (gconstpointer data)
4051 MonoEvent *event = (MonoEvent*)data;
4053 return g_str_hash (event->name);
4057 event_equal (MonoEvent *event1, MonoEvent *event2)
4059 // Events are hide-by-name
4060 return g_str_equal (event1->name, event2->name);
4063 ICALL_EXPORT MonoArray*
4064 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4068 static MonoClass *System_Reflection_EventInfo;
4069 MonoClass *startklass, *klass;
4075 char *utf8_name = NULL;
4076 int (*compare_func) (const char *s1, const char *s2) = NULL;
4077 GHashTable *events = NULL;
4078 MonoPtrArray tmp_array;
4080 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4082 if (!System_Reflection_EventInfo)
4083 System_Reflection_EventInfo = mono_class_from_name (
4084 mono_defaults.corlib, "System.Reflection", "EventInfo");
4086 domain = mono_object_domain (type);
4087 if (type->type->byref)
4088 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
4089 klass = startklass = mono_class_from_mono_type (type->type);
4091 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4093 mono_class_setup_methods (klass);
4094 mono_class_setup_vtable (klass);
4095 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
4099 while ((event = mono_class_get_events (klass, &iter))) {
4101 method = event->add;
4103 method = event->remove;
4105 method = event->raise;
4107 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4108 if (bflags & BFLAGS_Public)
4110 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4111 if (bflags & BFLAGS_NonPublic)
4116 if (bflags & BFLAGS_NonPublic)
4122 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4123 if (bflags & BFLAGS_Static)
4124 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4127 if (bflags & BFLAGS_Instance)
4132 if (bflags & BFLAGS_Instance)
4138 if (utf8_name == NULL) {
4139 utf8_name = mono_string_to_utf8 (name);
4140 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4143 if (compare_func (event->name, utf8_name))
4147 if (g_hash_table_lookup (events, event))
4150 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
4152 g_hash_table_insert (events, event, event);
4154 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4157 g_hash_table_destroy (events);
4159 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
4161 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4162 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4164 mono_ptr_array_destroy (tmp_array);
4166 if (utf8_name != NULL)
4172 mono_ptr_array_destroy (tmp_array);
4173 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4174 ex = mono_class_get_exception_for_failure (klass);
4176 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4177 mono_loader_clear_error ();
4179 mono_set_pending_exception (ex);
4183 ICALL_EXPORT MonoArray*
4184 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4187 MonoReflectionType *rt;
4195 MonoPtrArray tmp_array;
4197 domain = ((MonoObject *)type)->vtable->domain;
4198 if (type->type->byref)
4199 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4200 klass = mono_class_from_mono_type (type->type);
4203 * If a nested type is generic, return its generic type definition.
4204 * Note that this means that the return value is essentially the set
4205 * of nested types of the generic type definition of @klass.
4207 * A note in MSDN claims that a generic type definition can have
4208 * nested types that aren't generic. In any case, the container of that
4209 * nested type would be the generic type definition.
4211 if (klass->generic_class)
4212 klass = klass->generic_class->container_class;
4214 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4216 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4218 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4219 if (bflags & BFLAGS_Public)
4222 if (bflags & BFLAGS_NonPublic)
4230 str = mono_string_to_utf8 (name);
4231 mono_identifier_unescape_type_name_chars (str);
4234 if (strcmp (nested->name, str))
4238 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4239 mono_error_raise_exception (&error);
4241 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4244 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4246 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4247 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4249 mono_ptr_array_destroy (tmp_array);
4257 ICALL_EXPORT MonoReflectionType*
4258 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4261 MonoReflectionType *ret;
4263 MonoType *type = NULL;
4264 MonoTypeNameParse info;
4265 gboolean type_resolve;
4267 /* On MS.NET, this does not fire a TypeResolve event */
4268 type_resolve = TRUE;
4269 str = mono_string_to_utf8 (name);
4270 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4271 if (!mono_reflection_parse_type (str, &info)) {
4273 mono_reflection_free_type_info (&info);
4275 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4278 /*g_print ("failed parse\n");*/
4282 if (info.assembly.name) {
4284 mono_reflection_free_type_info (&info);
4286 /* 1.0 and 2.0 throw different exceptions */
4287 if (mono_defaults.generic_ilist_class)
4288 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4290 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4296 if (module != NULL) {
4298 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4303 if (assembly_is_dynamic (assembly->assembly)) {
4304 /* Enumerate all modules */
4305 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4309 if (abuilder->modules) {
4310 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4311 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4312 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4318 if (!type && abuilder->loaded_modules) {
4319 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4320 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4321 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4328 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4330 mono_reflection_free_type_info (&info);
4332 MonoException *e = NULL;
4335 e = mono_get_exception_type_load (name, NULL);
4337 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4338 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4340 mono_loader_clear_error ();
4343 mono_set_pending_exception (e);
4345 } else if (mono_loader_get_last_error ()) {
4347 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4350 mono_loader_clear_error ();
4353 if (type->type == MONO_TYPE_CLASS) {
4354 MonoClass *klass = mono_type_get_class (type);
4356 /* need to report exceptions ? */
4357 if (throwOnError && klass->exception_type) {
4358 /* report SecurityException (or others) that occured when loading the assembly */
4359 MonoException *exc = mono_class_get_exception_for_failure (klass);
4360 mono_loader_clear_error ();
4361 mono_set_pending_exception (exc);
4366 /* g_print ("got it\n"); */
4367 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4368 mono_error_raise_exception (&error);
4374 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4377 gchar *shadow_ini_file;
4380 /* Check for shadow-copied assembly */
4381 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4382 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4384 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4385 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4391 g_free (shadow_ini_file);
4392 if (content != NULL) {
4395 *filename = content;
4402 ICALL_EXPORT MonoString *
4403 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4405 MonoDomain *domain = mono_object_domain (assembly);
4406 MonoAssembly *mass = assembly->assembly;
4407 MonoString *res = NULL;
4412 if (g_path_is_absolute (mass->image->name)) {
4413 absolute = g_strdup (mass->image->name);
4414 dirname = g_path_get_dirname (absolute);
4416 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4417 dirname = g_strdup (mass->basedir);
4420 replace_shadow_path (domain, dirname, &absolute);
4425 for (i = strlen (absolute) - 1; i >= 0; i--)
4426 if (absolute [i] == '\\')
4431 uri = g_filename_to_uri (absolute, NULL, NULL);
4433 const char *prepend = "file://";
4435 if (*absolute == '/' && *(absolute + 1) == '/') {
4438 prepend = "file:///";
4441 uri = g_strconcat (prepend, absolute, NULL);
4445 res = mono_string_new (domain, uri);
4452 ICALL_EXPORT MonoBoolean
4453 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4455 MonoAssembly *mass = assembly->assembly;
4457 return mass->in_gac;
4460 ICALL_EXPORT MonoReflectionAssembly*
4461 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4465 MonoImageOpenStatus status;
4467 name = mono_string_to_utf8 (mname);
4468 res = mono_assembly_load_with_partial_name (name, &status);
4474 return mono_assembly_get_object (mono_domain_get (), res);
4477 ICALL_EXPORT MonoString *
4478 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4480 MonoDomain *domain = mono_object_domain (assembly);
4483 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4488 ICALL_EXPORT MonoBoolean
4489 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4491 return assembly->assembly->ref_only;
4494 ICALL_EXPORT MonoString *
4495 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4497 MonoDomain *domain = mono_object_domain (assembly);
4499 return mono_string_new (domain, assembly->assembly->image->version);
4502 ICALL_EXPORT MonoReflectionMethod*
4503 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4506 MonoReflectionMethod *res = NULL;
4509 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4513 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4514 if (!mono_error_ok (&error))
4517 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4520 if (!mono_error_ok (&error))
4521 mono_error_set_pending_exception (&error);
4525 ICALL_EXPORT MonoReflectionModule*
4526 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4529 MonoReflectionModule *result = NULL;
4530 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4531 if (!mono_error_ok (&error))
4532 mono_error_set_pending_exception (&error);
4536 ICALL_EXPORT MonoArray*
4537 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4539 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4540 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4544 for (i = 0; i < table->rows; ++i) {
4545 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4546 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4552 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4554 static MonoClass *System_Version = NULL;
4555 static MonoMethod *create_version = NULL;
4560 if (!System_Version) {
4561 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4562 g_assert (System_Version);
4565 if (!create_version) {
4566 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4567 create_version = mono_method_desc_search_in_class (desc, System_Version);
4568 g_assert (create_version);
4569 mono_method_desc_free (desc);
4575 args [3] = &revision;
4576 result = mono_object_new_checked (domain, System_Version, &error);
4577 mono_error_raise_exception (&error); /* FIXME don't raise here */
4578 mono_runtime_invoke (create_version, result, args, NULL);
4583 ICALL_EXPORT MonoArray*
4584 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4586 static MonoClass *System_Reflection_AssemblyName;
4589 MonoDomain *domain = mono_object_domain (assembly);
4591 static MonoMethod *create_culture = NULL;
4592 MonoImage *image = assembly->assembly->image;
4595 if (!System_Reflection_AssemblyName)
4596 System_Reflection_AssemblyName = mono_class_from_name (
4597 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4599 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4602 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4604 if (count > 0 && !create_culture) {
4605 MonoMethodDesc *desc = mono_method_desc_new (
4606 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4607 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4608 g_assert (create_culture);
4609 mono_method_desc_free (desc);
4612 for (i = 0; i < count; i++) {
4613 MonoReflectionAssemblyName *aname;
4614 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4616 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4618 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4619 domain, System_Reflection_AssemblyName, &error);
4620 mono_error_raise_exception (&error);
4622 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4624 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4625 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4626 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4627 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4628 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4629 aname->versioncompat = 1; /* SameMachine (default) */
4630 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4631 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4633 if (create_culture) {
4635 MonoBoolean assembly_ref = 1;
4636 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4637 args [1] = &assembly_ref;
4638 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4641 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4642 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4643 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4645 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4646 /* public key token isn't copied - the class library will
4647 automatically generate it from the public key if required */
4648 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4649 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4651 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4652 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4655 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4658 /* note: this function doesn't return the codebase on purpose (i.e. it can
4659 be used under partial trust as path information isn't present). */
4661 mono_array_setref (result, i, aname);
4666 /* move this in some file in mono/util/ */
4668 g_concat_dir_and_file (const char *dir, const char *file)
4670 g_return_val_if_fail (dir != NULL, NULL);
4671 g_return_val_if_fail (file != NULL, NULL);
4674 * If the directory name doesn't have a / on the end, we need
4675 * to add one so we get a proper path to the file
4677 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4678 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4680 return g_strconcat (dir, file, NULL);
4684 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4687 char *n = mono_string_to_utf8 (name);
4688 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4690 guint32 cols [MONO_MANIFEST_SIZE];
4691 guint32 impl, file_idx;
4695 for (i = 0; i < table->rows; ++i) {
4696 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4697 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4698 if (strcmp (val, n) == 0)
4702 if (i == table->rows)
4705 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4708 * this code should only be called after obtaining the
4709 * ResourceInfo and handling the other cases.
4711 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4712 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4714 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4719 module = assembly->assembly->image;
4722 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4723 mono_error_raise_exception (&error);
4724 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4726 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4729 ICALL_EXPORT gboolean
4730 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4732 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4734 guint32 cols [MONO_MANIFEST_SIZE];
4735 guint32 file_cols [MONO_FILE_SIZE];
4739 n = mono_string_to_utf8 (name);
4740 for (i = 0; i < table->rows; ++i) {
4741 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4742 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4743 if (strcmp (val, n) == 0)
4747 if (i == table->rows)
4750 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4751 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4754 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4755 case MONO_IMPLEMENTATION_FILE:
4756 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4757 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4758 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4759 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4760 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4761 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4764 info->location = RESOURCE_LOCATION_EMBEDDED;
4767 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4768 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4769 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4770 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4771 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4772 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4774 mono_set_pending_exception (ex);
4777 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4779 /* Obtain info recursively */
4780 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4781 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4784 case MONO_IMPLEMENTATION_EXP_TYPE:
4785 g_assert_not_reached ();
4793 ICALL_EXPORT MonoObject*
4794 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4796 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4797 MonoArray *result = NULL;
4802 /* check hash if needed */
4804 n = mono_string_to_utf8 (name);
4805 for (i = 0; i < table->rows; ++i) {
4806 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4807 if (strcmp (val, n) == 0) {
4810 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4811 fn = mono_string_new (mono_object_domain (assembly), n);
4813 return (MonoObject*)fn;
4821 for (i = 0; i < table->rows; ++i) {
4822 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4826 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4829 for (i = 0; i < table->rows; ++i) {
4830 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4831 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4832 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4833 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4838 return (MonoObject*)result;
4841 ICALL_EXPORT MonoArray*
4842 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4845 MonoDomain *domain = mono_domain_get();
4848 int i, j, file_count = 0;
4849 MonoImage **modules;
4850 guint32 module_count, real_module_count;
4851 MonoTableInfo *table;
4852 guint32 cols [MONO_FILE_SIZE];
4853 MonoImage *image = assembly->assembly->image;
4855 g_assert (image != NULL);
4856 g_assert (!assembly_is_dynamic (assembly->assembly));
4858 table = &image->tables [MONO_TABLE_FILE];
4859 file_count = table->rows;
4861 modules = image->modules;
4862 module_count = image->module_count;
4864 real_module_count = 0;
4865 for (i = 0; i < module_count; ++i)
4867 real_module_count ++;
4869 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4870 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4872 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
4873 mono_error_raise_exception (&error);
4874 mono_array_setref (res, 0, image_obj);
4876 for (i = 0; i < module_count; ++i)
4878 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
4879 mono_error_raise_exception (&error);
4880 mono_array_setref (res, j, rm);
4884 for (i = 0; i < file_count; ++i, ++j) {
4885 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4886 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4887 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4889 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4891 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4892 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
4895 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
4896 mono_error_raise_exception (&error);
4897 mono_array_setref (res, j, rm);
4904 ICALL_EXPORT MonoReflectionMethod*
4905 ves_icall_GetCurrentMethod (void)
4907 MonoReflectionMethod *res = NULL;
4910 MonoMethod *m = mono_method_get_last_managed ();
4913 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
4917 while (m->is_inflated)
4918 m = ((MonoMethodInflated*)m)->declaring;
4920 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
4921 mono_error_raise_exception (&error);
4927 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4930 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4933 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4934 //method is inflated, we should inflate it on the other class
4935 MonoGenericContext ctx;
4936 ctx.method_inst = inflated->context.method_inst;
4937 ctx.class_inst = inflated->context.class_inst;
4938 if (klass->generic_class)
4939 ctx.class_inst = klass->generic_class->context.class_inst;
4940 else if (klass->generic_container)
4941 ctx.class_inst = klass->generic_container->context.class_inst;
4942 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
4943 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4947 mono_class_setup_methods (method->klass);
4948 if (method->klass->exception_type)
4950 for (i = 0; i < method->klass->method.count; ++i) {
4951 if (method->klass->methods [i] == method) {
4956 mono_class_setup_methods (klass);
4957 if (klass->exception_type)
4959 g_assert (offset >= 0 && offset < klass->method.count);
4960 return klass->methods [offset];
4963 ICALL_EXPORT MonoReflectionMethod*
4964 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4966 MonoReflectionMethod *res = NULL;
4970 klass = mono_class_from_mono_type (type);
4971 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4973 if (method->klass != klass) {
4974 method = mono_method_get_equivalent_method (method, klass);
4979 klass = method->klass;
4980 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
4981 mono_error_raise_exception (&error);
4985 ICALL_EXPORT MonoReflectionMethodBody*
4986 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4988 return mono_method_body_get_object (mono_domain_get (), method);
4991 ICALL_EXPORT MonoReflectionAssembly*
4992 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4994 MonoMethod *dest = NULL;
4996 mono_stack_walk_no_il (get_executing, &dest);
4998 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5002 ICALL_EXPORT MonoReflectionAssembly*
5003 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5005 MonoDomain* domain = mono_domain_get ();
5007 if (!domain->entry_assembly)
5010 return mono_assembly_get_object (domain, domain->entry_assembly);
5013 ICALL_EXPORT MonoReflectionAssembly*
5014 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5020 mono_stack_walk_no_il (get_executing, &dest);
5022 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5026 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5029 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5032 ICALL_EXPORT MonoString *
5033 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5034 gboolean assembly_qualified)
5036 MonoDomain *domain = mono_object_domain (object);
5037 MonoTypeNameFormat format;
5042 format = assembly_qualified ?
5043 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5044 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5046 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5048 name = mono_type_get_name_full (object->type, format);
5052 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5057 res = mono_string_new (domain, name);
5064 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5066 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5067 mono_class_init_or_throw (klass);
5068 return mono_security_core_clr_class_level (klass);
5072 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5074 MonoClassField *field = rfield->field;
5075 return mono_security_core_clr_field_level (field, TRUE);
5079 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5081 MonoMethod *method = rfield->method;
5082 return mono_security_core_clr_method_level (method, TRUE);
5086 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
5088 static MonoMethod *create_culture = NULL;
5091 const char *pkey_ptr;
5093 MonoBoolean assembly_ref = 0;
5095 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5096 aname->major = name->major;
5097 aname->minor = name->minor;
5098 aname->build = name->build;
5099 aname->flags = name->flags;
5100 aname->revision = name->revision;
5101 aname->hashalg = name->hash_alg;
5102 aname->versioncompat = 1; /* SameMachine (default) */
5103 aname->processor_architecture = name->arch;
5105 if (by_default_version)
5106 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
5109 if (absolute != NULL && *absolute != '\0') {
5110 const gchar *prepend = "file://";
5113 codebase = g_strdup (absolute);
5118 for (i = strlen (codebase) - 1; i >= 0; i--)
5119 if (codebase [i] == '\\')
5122 if (*codebase == '/' && *(codebase + 1) == '/') {
5125 prepend = "file:///";
5129 result = g_strconcat (prepend, codebase, NULL);
5135 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5139 if (!create_culture) {
5140 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5141 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5142 g_assert (create_culture);
5143 mono_method_desc_free (desc);
5146 if (name->culture) {
5147 args [0] = mono_string_new (domain, name->culture);
5148 args [1] = &assembly_ref;
5149 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5152 if (name->public_key) {
5153 pkey_ptr = (char*)name->public_key;
5154 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5156 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5157 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5158 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5159 } else if (default_publickey) {
5160 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5161 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5164 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5165 if (name->public_key_token [0]) {
5169 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5170 p = mono_array_addr (aname->keyToken, char, 0);
5172 for (i = 0, j = 0; i < 8; i++) {
5173 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5174 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5177 } else if (default_token) {
5178 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5182 ICALL_EXPORT MonoString *
5183 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5185 MonoDomain *domain = mono_object_domain (assembly);
5186 MonoAssembly *mass = assembly->assembly;
5190 name = mono_stringify_assembly_name (&mass->aname);
5191 res = mono_string_new (domain, name);
5198 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5201 MonoAssembly *mass = assembly->assembly;
5203 if (g_path_is_absolute (mass->image->name)) {
5204 fill_reflection_assembly_name (mono_object_domain (assembly),
5205 aname, &mass->aname, mass->image->name, TRUE,
5209 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5211 fill_reflection_assembly_name (mono_object_domain (assembly),
5212 aname, &mass->aname, absolute, TRUE, TRUE,
5219 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5222 MonoImageOpenStatus status = MONO_IMAGE_OK;
5225 MonoAssemblyName name;
5228 filename = mono_string_to_utf8 (fname);
5230 dirname = g_path_get_dirname (filename);
5231 replace_shadow_path (mono_domain_get (), dirname, &filename);
5234 image = mono_image_open (filename, &status);
5240 if (status == MONO_IMAGE_IMAGE_INVALID)
5241 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5243 exc = mono_get_exception_file_not_found2 (NULL, fname);
5244 mono_set_pending_exception (exc);
5248 res = mono_assembly_fill_assembly_name (image, &name);
5250 mono_image_close (image);
5252 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5256 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5260 mono_image_close (image);
5263 ICALL_EXPORT MonoBoolean
5264 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5265 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5267 MonoBoolean result = FALSE;
5268 MonoDeclSecurityEntry entry;
5270 /* SecurityAction.RequestMinimum */
5271 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5272 *minimum = entry.blob;
5273 *minLength = entry.size;
5276 /* SecurityAction.RequestOptional */
5277 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5278 *optional = entry.blob;
5279 *optLength = entry.size;
5282 /* SecurityAction.RequestRefuse */
5283 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5284 *refused = entry.blob;
5285 *refLength = entry.size;
5293 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5295 guint32 attrs, visibility;
5297 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5298 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5299 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5302 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5308 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5311 MonoReflectionType *rt;
5314 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5317 /* we start the count from 1 because we skip the special type <Module> */
5320 for (i = 1; i < tdef->rows; ++i) {
5321 if (mono_module_type_is_visible (tdef, image, i + 1))
5325 count = tdef->rows - 1;
5327 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5328 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5330 for (i = 1; i < tdef->rows; ++i) {
5331 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5332 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, &error);
5333 mono_loader_assert_no_error (); /* Plug any leaks */
5334 g_assert (mono_error_ok (&error));
5337 rt = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5338 mono_error_raise_exception (&error); /* FIXME don't raise here */
5340 mono_array_setref (res, count, rt);
5342 MonoException *ex = mono_error_convert_to_exception (&error);
5343 mono_array_setref (*exceptions, count, ex);
5352 ICALL_EXPORT MonoArray*
5353 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5355 MonoArray *res = NULL;
5356 MonoArray *exceptions = NULL;
5357 MonoImage *image = NULL;
5358 MonoTableInfo *table = NULL;
5361 int i, len, ex_count;
5363 domain = mono_object_domain (assembly);
5365 g_assert (!assembly_is_dynamic (assembly->assembly));
5366 image = assembly->assembly->image;
5367 table = &image->tables [MONO_TABLE_FILE];
5368 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5370 /* Append data from all modules in the assembly */
5371 for (i = 0; i < table->rows; ++i) {
5372 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5373 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5376 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5377 /* Append the new types to the end of the array */
5378 if (mono_array_length (res2) > 0) {
5380 MonoArray *res3, *ex3;
5382 len1 = mono_array_length (res);
5383 len2 = mono_array_length (res2);
5385 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5386 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5387 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5390 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5391 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5392 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5399 /* the ReflectionTypeLoadException must have all the types (Types property),
5400 * NULL replacing types which throws an exception. The LoaderException must
5401 * contain all exceptions for NULL items.
5404 len = mono_array_length (res);
5407 for (i = 0; i < len; i++) {
5408 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5412 klass = mono_type_get_class (t->type);
5413 if ((klass != NULL) && klass->exception_type) {
5414 /* keep the class in the list */
5415 list = g_list_append (list, klass);
5416 /* and replace Type with NULL */
5417 mono_array_setref (res, i, NULL);
5424 if (list || ex_count) {
5426 MonoException *exc = NULL;
5427 MonoArray *exl = NULL;
5428 int j, length = g_list_length (list) + ex_count;
5430 mono_loader_clear_error ();
5432 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5433 /* Types for which mono_class_get_checked () succeeded */
5434 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5435 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5436 mono_array_setref (exl, i, exc);
5438 /* Types for which it don't */
5439 for (j = 0; j < mono_array_length (exceptions); ++j) {
5440 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5442 g_assert (i < length);
5443 mono_array_setref (exl, i, exc);
5450 exc = mono_get_exception_reflection_type_load (res, exl);
5451 mono_loader_clear_error ();
5452 mono_set_pending_exception (exc);
5459 ICALL_EXPORT gboolean
5460 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5462 MonoAssemblyName aname;
5463 MonoDomain *domain = mono_object_domain (name);
5465 gboolean is_version_defined;
5466 gboolean is_token_defined;
5468 aname.public_key = NULL;
5469 val = mono_string_to_utf8 (assname);
5470 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5471 g_free ((guint8*) aname.public_key);
5476 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5477 FALSE, is_token_defined);
5479 mono_assembly_name_free (&aname);
5480 g_free ((guint8*) aname.public_key);
5486 ICALL_EXPORT MonoReflectionType*
5487 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5490 MonoReflectionType *ret;
5491 MonoDomain *domain = mono_object_domain (module);
5494 g_assert (module->image);
5496 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5497 /* These images do not have a global type */
5500 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5501 if (!mono_error_ok (&error)) {
5502 mono_error_set_pending_exception (&error);
5506 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5507 if (!mono_error_ok (&error)) {
5508 mono_error_set_pending_exception (&error);
5516 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5518 /*if (module->image)
5519 mono_image_close (module->image);*/
5522 ICALL_EXPORT MonoString*
5523 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5525 MonoDomain *domain = mono_object_domain (module);
5527 g_assert (module->image);
5528 return mono_string_new (domain, module->image->guid);
5531 ICALL_EXPORT gpointer
5532 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5535 if (module->image && module->image->is_module_handle)
5536 return module->image->raw_data;
5539 return (gpointer) (-1);
5543 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5545 if (image_is_dynamic (image)) {
5546 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5547 *pe_kind = dyn->pe_kind;
5548 *machine = dyn->machine;
5551 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5552 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5557 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5559 return (image->md_version_major << 16) | (image->md_version_minor);
5562 ICALL_EXPORT MonoArray*
5563 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5565 MonoArray *exceptions;
5569 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5571 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5572 for (i = 0; i < mono_array_length (exceptions); ++i) {
5573 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5575 mono_set_pending_exception (ex);
5584 mono_memberref_is_method (MonoImage *image, guint32 token)
5586 if (!image_is_dynamic (image)) {
5587 guint32 cols [MONO_MEMBERREF_SIZE];
5589 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5590 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5591 mono_metadata_decode_blob_size (sig, &sig);
5592 return (*sig != 0x6);
5594 MonoClass *handle_class;
5596 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5599 return mono_defaults.methodhandle_class == handle_class;
5604 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5607 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5608 mono_array_addr (type_args, MonoType*, 0));
5610 context->class_inst = NULL;
5612 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5613 mono_array_addr (method_args, MonoType*, 0));
5615 context->method_inst = NULL;
5618 ICALL_EXPORT MonoType*
5619 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5622 int table = mono_metadata_token_table (token);
5623 int index = mono_metadata_token_index (token);
5624 MonoGenericContext context;
5627 *resolve_error = ResolveTokenError_Other;
5629 /* Validate token */
5630 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5631 (table != MONO_TABLE_TYPESPEC)) {
5632 *resolve_error = ResolveTokenError_BadTable;
5636 if (image_is_dynamic (image)) {
5637 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5638 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5639 return klass ? &klass->byval_arg : NULL;
5642 init_generic_context_from_args (&context, type_args, method_args);
5643 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5644 return klass ? &klass->byval_arg : NULL;
5647 if ((index <= 0) || (index > image->tables [table].rows)) {
5648 *resolve_error = ResolveTokenError_OutOfRange;
5652 init_generic_context_from_args (&context, type_args, method_args);
5653 klass = mono_class_get_checked (image, token, &error);
5655 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5656 if (!mono_error_ok (&error)) {
5657 mono_error_set_pending_exception (&error);
5662 return &klass->byval_arg;
5667 ICALL_EXPORT MonoMethod*
5668 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5671 int table = mono_metadata_token_table (token);
5672 int index = mono_metadata_token_index (token);
5673 MonoGenericContext context;
5676 *resolve_error = ResolveTokenError_Other;
5678 /* Validate token */
5679 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5680 (table != MONO_TABLE_MEMBERREF)) {
5681 *resolve_error = ResolveTokenError_BadTable;
5685 if (image_is_dynamic (image)) {
5686 if (table == MONO_TABLE_METHOD)
5687 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5689 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5690 *resolve_error = ResolveTokenError_BadTable;
5694 init_generic_context_from_args (&context, type_args, method_args);
5695 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5698 if ((index <= 0) || (index > image->tables [table].rows)) {
5699 *resolve_error = ResolveTokenError_OutOfRange;
5702 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5703 *resolve_error = ResolveTokenError_BadTable;
5707 init_generic_context_from_args (&context, type_args, method_args);
5708 method = mono_get_method_checked (image, token, NULL, &context, &error);
5709 mono_error_set_pending_exception (&error);
5714 ICALL_EXPORT MonoString*
5715 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5717 int index = mono_metadata_token_index (token);
5719 *error = ResolveTokenError_Other;
5721 /* Validate token */
5722 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5723 *error = ResolveTokenError_BadTable;
5727 if (image_is_dynamic (image))
5728 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5730 if ((index <= 0) || (index >= image->heap_us.size)) {
5731 *error = ResolveTokenError_OutOfRange;
5735 /* FIXME: What to do if the index points into the middle of a string ? */
5737 return mono_ldstr (mono_domain_get (), image, index);
5740 ICALL_EXPORT MonoClassField*
5741 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5745 int table = mono_metadata_token_table (token);
5746 int index = mono_metadata_token_index (token);
5747 MonoGenericContext context;
5748 MonoClassField *field;
5750 *resolve_error = ResolveTokenError_Other;
5752 /* Validate token */
5753 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5754 *resolve_error = ResolveTokenError_BadTable;
5758 if (image_is_dynamic (image)) {
5759 if (table == MONO_TABLE_FIELD)
5760 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5762 if (mono_memberref_is_method (image, token)) {
5763 *resolve_error = ResolveTokenError_BadTable;
5767 init_generic_context_from_args (&context, type_args, method_args);
5768 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5771 if ((index <= 0) || (index > image->tables [table].rows)) {
5772 *resolve_error = ResolveTokenError_OutOfRange;
5775 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5776 *resolve_error = ResolveTokenError_BadTable;
5780 init_generic_context_from_args (&context, type_args, method_args);
5781 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5782 mono_error_set_pending_exception (&error);
5788 ICALL_EXPORT MonoObject*
5789 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5793 int table = mono_metadata_token_table (token);
5795 *error = ResolveTokenError_Other;
5798 case MONO_TABLE_TYPEDEF:
5799 case MONO_TABLE_TYPEREF:
5800 case MONO_TABLE_TYPESPEC: {
5801 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5803 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
5804 mono_error_raise_exception (&merror);
5811 case MONO_TABLE_METHOD:
5812 case MONO_TABLE_METHODSPEC: {
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);
5822 case MONO_TABLE_FIELD: {
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);
5832 case MONO_TABLE_MEMBERREF:
5833 if (mono_memberref_is_method (image, token)) {
5834 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5836 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5837 mono_error_raise_exception (&merror);
5844 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5846 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5847 mono_error_raise_exception (&merror);
5856 *error = ResolveTokenError_BadTable;
5862 ICALL_EXPORT MonoArray*
5863 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5865 int table = mono_metadata_token_table (token);
5866 int idx = mono_metadata_token_index (token);
5867 MonoTableInfo *tables = image->tables;
5872 *error = ResolveTokenError_OutOfRange;
5874 /* FIXME: Support other tables ? */
5875 if (table != MONO_TABLE_STANDALONESIG)
5878 if (image_is_dynamic (image))
5881 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5884 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5886 ptr = mono_metadata_blob_heap (image, sig);
5887 len = mono_metadata_decode_blob_size (ptr, &ptr);
5889 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5890 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5894 ICALL_EXPORT MonoReflectionType*
5895 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5898 MonoReflectionType *ret;
5900 int isbyref = 0, rank;
5901 char *str = mono_string_to_utf8 (smodifiers);
5904 klass = mono_class_from_mono_type (tb->type.type);
5906 /* logic taken from mono_reflection_parse_type(): keep in sync */
5910 if (isbyref) { /* only one level allowed by the spec */
5919 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
5920 mono_error_raise_exception (&error);
5924 klass = mono_ptr_class_get (&klass->byval_arg);
5925 mono_class_init (klass);
5936 else if (*p != '*') { /* '*' means unknown lower bound */
5947 klass = mono_array_class_get (klass, rank);
5948 mono_class_init (klass);
5957 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
5958 mono_error_raise_exception (&error);
5963 ICALL_EXPORT MonoBoolean
5964 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5970 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5976 check_for_invalid_type (MonoClass *klass)
5980 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5983 name = mono_type_get_full_name (klass);
5984 str = mono_string_new (mono_domain_get (), name);
5986 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5989 ICALL_EXPORT MonoReflectionType *
5990 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5993 MonoReflectionType *ret;
5994 MonoClass *klass, *aklass;
5996 klass = mono_class_from_mono_type (type->type);
5997 check_for_invalid_type (klass);
5999 if (rank == 0) //single dimentional array
6000 aklass = mono_array_class_get (klass, 1);
6002 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6004 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6005 mono_error_raise_exception (&error);
6010 ICALL_EXPORT MonoReflectionType *
6011 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6014 MonoReflectionType *ret;
6017 klass = mono_class_from_mono_type (type->type);
6018 mono_class_init_or_throw (klass);
6019 check_for_invalid_type (klass);
6021 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6022 mono_error_raise_exception (&error);
6027 ICALL_EXPORT MonoReflectionType *
6028 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6031 MonoReflectionType *ret;
6032 MonoClass *klass, *pklass;
6034 klass = mono_class_from_mono_type (type->type);
6035 mono_class_init_or_throw (klass);
6036 check_for_invalid_type (klass);
6038 pklass = mono_ptr_class_get (type->type);
6040 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6041 mono_error_raise_exception (&error);
6046 ICALL_EXPORT MonoObject *
6047 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6048 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6051 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6052 MonoObject *delegate;
6054 MonoMethod *method = info->method;
6056 mono_class_init_or_throw (delegate_class);
6058 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
6060 if (mono_security_core_clr_enabled ()) {
6061 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6065 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6066 mono_error_raise_exception (&error);
6068 if (method_is_dynamic (method)) {
6069 /* Creating a trampoline would leak memory */
6070 func = mono_compile_method (method);
6072 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6073 method = mono_object_get_virtual_method (target, method);
6074 func = mono_create_ftnptr (mono_domain_get (),
6075 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6078 mono_delegate_ctor_with_method (delegate, target, func, method);
6083 ICALL_EXPORT MonoMulticastDelegate *
6084 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6087 MonoMulticastDelegate *ret;
6089 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6091 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6092 mono_error_raise_exception (&error);
6093 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6098 ICALL_EXPORT MonoReflectionMethod*
6099 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6101 MonoReflectionMethod *ret = NULL;
6103 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6104 mono_error_raise_exception (&error);
6110 static inline gint32
6111 mono_array_get_byte_length (MonoArray *array)
6117 klass = array->obj.vtable->klass;
6119 if (array->bounds == NULL)
6120 length = array->max_length;
6123 for (i = 0; i < klass->rank; ++ i)
6124 length *= array->bounds [i].length;
6127 switch (klass->element_class->byval_arg.type) {
6130 case MONO_TYPE_BOOLEAN:
6134 case MONO_TYPE_CHAR:
6142 return length * sizeof (gpointer);
6153 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6155 return mono_array_get_byte_length (array);
6159 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6161 return mono_array_get (array, gint8, idx);
6165 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6167 mono_array_set (array, gint8, idx, value);
6170 ICALL_EXPORT MonoBoolean
6171 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6173 guint8 *src_buf, *dest_buf;
6176 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6180 g_assert (count >= 0);
6182 /* This is called directly from the class libraries without going through the managed wrapper */
6183 MONO_CHECK_ARG_NULL (src, FALSE);
6184 MONO_CHECK_ARG_NULL (dest, FALSE);
6186 /* watch out for integer overflow */
6187 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6190 src_buf = (guint8 *)src->vector + src_offset;
6191 dest_buf = (guint8 *)dest->vector + dest_offset;
6194 memcpy (dest_buf, src_buf, count);
6196 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6201 #ifndef DISABLE_REMOTING
6202 ICALL_EXPORT MonoObject *
6203 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6206 MonoDomain *domain = mono_object_domain (this_obj);
6208 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6209 MonoTransparentProxy *tp;
6213 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6214 mono_error_raise_exception (&error);
6215 tp = (MonoTransparentProxy*) res;
6217 MONO_OBJECT_SETREF (tp, rp, rp);
6218 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6219 klass = mono_class_from_mono_type (type);
6221 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6222 mono_class_setup_vtable (klass);
6223 if (klass->exception_type) {
6224 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6228 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
6229 tp->remote_class = mono_remote_class (domain, class_name, klass);
6231 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6235 ICALL_EXPORT MonoReflectionType *
6236 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6239 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6240 mono_error_raise_exception (&error);
6246 /* System.Environment */
6249 ves_icall_System_Environment_get_UserName (void)
6251 /* using glib is more portable */
6252 return mono_string_new (mono_domain_get (), g_get_user_name ());
6256 ICALL_EXPORT MonoString *
6257 ves_icall_System_Environment_get_MachineName (void)
6259 #if defined (HOST_WIN32)
6264 len = MAX_COMPUTERNAME_LENGTH + 1;
6265 buf = g_new (gunichar2, len);
6268 if (GetComputerName (buf, (PDWORD) &len)) {
6270 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6271 mono_error_raise_exception (&error);
6276 #elif !defined(DISABLE_SOCKETS)
6280 #if defined _SC_HOST_NAME_MAX
6281 n = sysconf (_SC_HOST_NAME_MAX);
6285 buf = g_malloc (n+1);
6287 if (gethostname (buf, n) == 0){
6289 result = mono_string_new (mono_domain_get (), buf);
6296 return mono_string_new (mono_domain_get (), "mono");
6301 ves_icall_System_Environment_get_Platform (void)
6303 #if defined (TARGET_WIN32)
6306 #elif defined(__MACH__)
6309 // Notice that the value is hidden from user code, and only exposed
6310 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6311 // define and making assumptions based on Unix/128/4 values before there
6312 // was a MacOS define. Lots of code would assume that not-Unix meant
6313 // Windows, but in this case, it would be OSX.
6322 ICALL_EXPORT MonoString *
6323 ves_icall_System_Environment_get_NewLine (void)
6325 #if defined (HOST_WIN32)
6326 return mono_string_new (mono_domain_get (), "\r\n");
6328 return mono_string_new (mono_domain_get (), "\n");
6332 ICALL_EXPORT MonoBoolean
6333 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6335 #if SIZEOF_VOID_P == 8
6339 gboolean isWow64Process = FALSE;
6340 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6341 return (MonoBoolean)isWow64Process;
6343 #elif defined(HAVE_SYS_UTSNAME_H)
6344 struct utsname name;
6346 if (uname (&name) >= 0) {
6347 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6354 ICALL_EXPORT MonoString *
6355 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6363 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6364 value = g_getenv (utf8_name);
6371 return mono_string_new (mono_domain_get (), value);
6375 * There is no standard way to get at environ.
6378 #ifndef __MINGW32_VERSION
6379 #if defined(__APPLE__)
6380 #if defined (TARGET_OSX)
6381 /* Apple defines this in crt_externs.h but doesn't provide that header for
6382 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6383 * in fact exist on all implementations (so far)
6385 gchar ***_NSGetEnviron(void);
6386 #define environ (*_NSGetEnviron())
6388 static char *mono_environ[1] = { NULL };
6389 #define environ mono_environ
6390 #endif /* defined (TARGET_OSX) */
6398 ICALL_EXPORT MonoArray *
6399 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6410 env_strings = GetEnvironmentStrings();
6413 env_string = env_strings;
6414 while (*env_string != '\0') {
6415 /* weird case that MS seems to skip */
6416 if (*env_string != '=')
6418 while (*env_string != '\0')
6424 domain = mono_domain_get ();
6425 names = mono_array_new (domain, mono_defaults.string_class, n);
6429 env_string = env_strings;
6430 while (*env_string != '\0') {
6431 /* weird case that MS seems to skip */
6432 if (*env_string != '=') {
6433 equal_str = wcschr(env_string, '=');
6434 g_assert(equal_str);
6436 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6437 mono_error_raise_exception (&error);
6438 mono_array_setref (names, n, str);
6441 while (*env_string != '\0')
6446 FreeEnvironmentStrings (env_strings);
6459 for (e = environ; *e != 0; ++ e)
6462 domain = mono_domain_get ();
6463 names = mono_array_new (domain, mono_defaults.string_class, n);
6466 for (e = environ; *e != 0; ++ e) {
6467 parts = g_strsplit (*e, "=", 2);
6469 str = mono_string_new (domain, *parts);
6470 mono_array_setref (names, n, str);
6483 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6485 #if !GLIB_CHECK_VERSION(2,4,0)
6486 #define g_setenv(a,b,c) setenv(a,b,c)
6487 #define g_unsetenv(a) unsetenv(a)
6491 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6494 gunichar2 *utf16_name, *utf16_value;
6496 gchar *utf8_name, *utf8_value;
6501 utf16_name = mono_string_to_utf16 (name);
6502 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6503 SetEnvironmentVariable (utf16_name, NULL);
6504 g_free (utf16_name);
6508 utf16_value = mono_string_to_utf16 (value);
6510 SetEnvironmentVariable (utf16_name, utf16_value);
6512 g_free (utf16_name);
6513 g_free (utf16_value);
6515 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6517 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6518 g_unsetenv (utf8_name);
6523 utf8_value = mono_string_to_utf8_checked (value, &error);
6524 if (!mono_error_ok (&error)) {
6526 mono_error_set_pending_exception (&error);
6529 g_setenv (utf8_name, utf8_value, TRUE);
6532 g_free (utf8_value);
6537 ves_icall_System_Environment_Exit (int result)
6539 mono_environment_exitcode_set (result);
6541 /* FIXME: There are some cleanup hangs that should be worked out, but
6542 * if the program is going to exit, everything will be cleaned up when
6543 * NaCl exits anyway.
6545 #ifndef __native_client__
6546 if (!mono_runtime_try_shutdown ())
6547 mono_thread_exit ();
6549 /* Suspend all managed threads since the runtime is going away */
6550 mono_thread_suspend_all_other_threads ();
6552 mono_runtime_quit ();
6555 /* we may need to do some cleanup here... */
6559 ICALL_EXPORT MonoString*
6560 ves_icall_System_Environment_GetGacPath (void)
6562 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6565 ICALL_EXPORT MonoString*
6566 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6568 #if defined (HOST_WIN32)
6569 #ifndef CSIDL_FLAG_CREATE
6570 #define CSIDL_FLAG_CREATE 0x8000
6573 WCHAR path [MAX_PATH];
6574 /* Create directory if no existing */
6575 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6580 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6581 mono_error_raise_exception (&error);
6585 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6587 return mono_string_new (mono_domain_get (), "");
6590 ICALL_EXPORT MonoArray *
6591 ves_icall_System_Environment_GetLogicalDrives (void)
6594 gunichar2 buf [256], *ptr, *dname;
6596 guint initial_size = 127, size = 128;
6599 MonoString *drivestr;
6600 MonoDomain *domain = mono_domain_get ();
6606 while (size > initial_size) {
6607 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6608 if (size > initial_size) {
6611 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6612 initial_size = size;
6626 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6631 while (*u16) { u16++; len ++; }
6632 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6633 mono_error_raise_exception (&error);
6634 mono_array_setref (result, ndrives++, drivestr);
6644 ICALL_EXPORT MonoString *
6645 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6647 gunichar2 volume_name [MAX_PATH + 1];
6649 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6651 return mono_string_from_utf16 (volume_name);
6654 ICALL_EXPORT MonoString *
6655 ves_icall_System_Environment_InternalGetHome (void)
6657 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6660 static const char *encodings [] = {
6662 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6663 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6664 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6666 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6667 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6668 "x_unicode_2_0_utf_7",
6670 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6671 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6673 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6676 "unicodefffe", "utf_16be",
6683 * Returns the internal codepage, if the value of "int_code_page" is
6684 * 1 at entry, and we can not compute a suitable code page number,
6685 * returns the code page as a string
6687 ICALL_EXPORT MonoString*
6688 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6693 char *codepage = NULL;
6695 int want_name = *int_code_page;
6698 *int_code_page = -1;
6700 g_get_charset (&cset);
6701 c = codepage = strdup (cset);
6702 for (c = codepage; *c; c++){
6703 if (isascii (*c) && isalpha (*c))
6708 /* g_print ("charset: %s\n", cset); */
6710 /* handle some common aliases */
6713 for (i = 0; p != 0; ){
6716 p = encodings [++i];
6719 if (strcmp (p, codepage) == 0){
6720 *int_code_page = code;
6723 p = encodings [++i];
6726 if (strstr (codepage, "utf_8") != NULL)
6727 *int_code_page |= 0x10000000;
6730 if (want_name && *int_code_page == -1)
6731 return mono_string_new (mono_domain_get (), cset);
6736 ICALL_EXPORT MonoBoolean
6737 ves_icall_System_Environment_get_HasShutdownStarted (void)
6739 if (mono_runtime_is_shutting_down ())
6742 if (mono_domain_is_unloading (mono_domain_get ()))
6749 ves_icall_System_Environment_BroadcastSettingChange (void)
6752 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6757 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6763 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6764 MonoReflectionMethod *method,
6765 MonoArray *out_args)
6767 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6770 #ifndef DISABLE_REMOTING
6771 ICALL_EXPORT MonoBoolean
6772 ves_icall_IsTransparentProxy (MonoObject *proxy)
6777 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6783 ICALL_EXPORT MonoReflectionMethod *
6784 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6785 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6787 MonoReflectionMethod *ret = NULL;
6792 MonoMethod **vtable;
6793 MonoMethod *res = NULL;
6795 MONO_CHECK_ARG_NULL (rtype, NULL);
6796 MONO_CHECK_ARG_NULL (rmethod, NULL);
6798 method = rmethod->method;
6799 klass = mono_class_from_mono_type (rtype->type);
6800 mono_class_init_or_throw (klass);
6802 if (MONO_CLASS_IS_INTERFACE (klass))
6805 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6808 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6809 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6815 mono_class_setup_vtable (klass);
6816 vtable = klass->vtable;
6818 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6819 gboolean variance_used = FALSE;
6820 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6821 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6823 res = vtable [offs + method->slot];
6825 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6828 if (method->slot != -1)
6829 res = vtable [method->slot];
6835 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
6836 mono_error_raise_exception (&error);
6841 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6846 klass = mono_class_from_mono_type (type->type);
6847 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6849 mono_vtable_set_is_remote (vtable, enable);
6852 #else /* DISABLE_REMOTING */
6855 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6857 g_assert_not_reached ();
6862 ICALL_EXPORT MonoObject *
6863 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6870 domain = mono_object_domain (type);
6871 klass = mono_class_from_mono_type (type->type);
6872 mono_class_init_or_throw (klass);
6874 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
6875 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6879 if (klass->rank >= 1) {
6880 g_assert (klass->rank == 1);
6881 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6883 /* Bypass remoting object creation check */
6884 ret = mono_object_new_alloc_specific_checked (mono_class_vtable_full (domain, klass, TRUE), &error);
6885 mono_error_set_pending_exception (&error);
6891 ICALL_EXPORT MonoString *
6892 ves_icall_System_IO_get_temp_path (void)
6894 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6897 #ifndef PLATFORM_NO_DRIVEINFO
6898 ICALL_EXPORT MonoBoolean
6899 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6900 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6904 ULARGE_INTEGER wapi_free_bytes_avail;
6905 ULARGE_INTEGER wapi_total_number_of_bytes;
6906 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6908 *error = ERROR_SUCCESS;
6909 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6910 &wapi_total_number_of_free_bytes);
6913 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6914 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6915 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6917 *free_bytes_avail = 0;
6918 *total_number_of_bytes = 0;
6919 *total_number_of_free_bytes = 0;
6920 *error = GetLastError ();
6926 ICALL_EXPORT guint32
6927 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6929 return GetDriveType (mono_string_chars (root_path_name));
6933 ICALL_EXPORT gpointer
6934 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6936 return mono_compile_method (method);
6939 ICALL_EXPORT MonoString *
6940 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6945 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6947 #if defined (HOST_WIN32)
6948 /* Avoid mixing '/' and '\\' */
6951 for (i = strlen (path) - 1; i >= 0; i--)
6952 if (path [i] == '/')
6956 mcpath = mono_string_new (mono_domain_get (), path);
6963 get_bundled_app_config (void)
6965 const gchar *app_config;
6968 gchar *config_file_name, *config_file_path;
6969 gsize len, config_file_path_length, config_ext_length;
6972 domain = mono_domain_get ();
6973 file = domain->setup->configuration_file;
6974 if (!file || file->length == 0)
6977 // Retrieve config file and remove the extension
6978 config_file_name = mono_string_to_utf8 (file);
6979 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6980 if (!config_file_path)
6981 config_file_path = config_file_name;
6983 config_file_path_length = strlen (config_file_path);
6984 config_ext_length = strlen (".config");
6985 if (config_file_path_length <= config_ext_length)
6988 len = config_file_path_length - config_ext_length;
6989 module = (gchar *)g_malloc0 (len + 1);
6990 memcpy (module, config_file_path, len);
6991 // Get the config file from the module name
6992 app_config = mono_config_string_for_assembly_file (module);
6995 if (config_file_name != config_file_path)
6996 g_free (config_file_name);
6997 g_free (config_file_path);
7002 return mono_string_new (mono_domain_get (), app_config);
7006 get_bundled_machine_config (void)
7008 const gchar *machine_config;
7010 machine_config = mono_get_machine_config ();
7012 if (!machine_config)
7015 return mono_string_new (mono_domain_get (), machine_config);
7018 ICALL_EXPORT MonoString *
7019 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7024 path = g_path_get_dirname (mono_get_config_dir ());
7026 #if defined (HOST_WIN32)
7027 /* Avoid mixing '/' and '\\' */
7030 for (i = strlen (path) - 1; i >= 0; i--)
7031 if (path [i] == '/')
7035 ipath = mono_string_new (mono_domain_get (), path);
7041 ICALL_EXPORT gboolean
7042 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7044 MonoPEResourceDataEntry *entry;
7047 if (!assembly || !result || !size)
7052 image = assembly->assembly->image;
7053 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7057 *result = mono_image_rva_map (image, entry->rde_data_offset);
7062 *size = entry->rde_size;
7067 ICALL_EXPORT MonoBoolean
7068 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7070 return mono_is_debugger_attached ();
7073 ICALL_EXPORT MonoBoolean
7074 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7076 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7077 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7083 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7085 if (mono_get_runtime_callbacks ()->debug_log)
7086 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7090 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7092 #if defined (HOST_WIN32)
7093 OutputDebugString (mono_string_chars (message));
7095 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7099 /* Only used for value types */
7100 ICALL_EXPORT MonoObject *
7101 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7108 domain = mono_object_domain (type);
7109 klass = mono_class_from_mono_type (type->type);
7110 mono_class_init_or_throw (klass);
7112 if (mono_class_is_nullable (klass))
7113 /* No arguments -> null */
7116 result = mono_object_new_checked (domain, klass, &error);
7117 mono_error_raise_exception (&error);
7121 ICALL_EXPORT MonoReflectionMethod *
7122 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7124 MonoReflectionMethod *ret = NULL;
7127 MonoClass *klass, *parent;
7128 MonoGenericContext *generic_inst = NULL;
7129 MonoMethod *method = m->method;
7130 MonoMethod *result = NULL;
7133 if (method->klass == NULL)
7136 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7137 MONO_CLASS_IS_INTERFACE (method->klass) ||
7138 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7141 slot = mono_method_get_vtable_slot (method);
7145 klass = method->klass;
7146 if (klass->generic_class) {
7147 generic_inst = mono_class_get_context (klass);
7148 klass = klass->generic_class->container_class;
7152 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7153 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7154 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7155 or klass is the generic container class and generic_inst is the instantiation.
7157 when we go to the parent, if the parent is an open constructed type, we need to
7158 replace the type parameters by the definitions from the generic_inst, and then take it
7159 apart again into the klass and the generic_inst.
7161 For cases like this:
7162 class C<T> : B<T, int> {
7163 public override void Foo () { ... }
7165 class B<U,V> : A<HashMap<U,V>> {
7166 public override void Foo () { ... }
7169 public virtual void Foo () { ... }
7172 if at each iteration the parent isn't open, we can skip inflating it. if at some
7173 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7176 MonoGenericContext *parent_inst = NULL;
7177 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7179 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7180 if (!mono_error_ok (&error)) {
7181 mono_error_set_pending_exception (&error);
7185 if (parent->generic_class) {
7186 parent_inst = mono_class_get_context (parent);
7187 parent = parent->generic_class->container_class;
7190 mono_class_setup_vtable (parent);
7191 if (parent->vtable_size <= slot)
7194 generic_inst = parent_inst;
7197 klass = klass->parent;
7200 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7201 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7202 if (!mono_error_ok (&error)) {
7203 mono_error_set_pending_exception (&error);
7207 generic_inst = NULL;
7209 if (klass->generic_class) {
7210 generic_inst = mono_class_get_context (klass);
7211 klass = klass->generic_class->container_class;
7217 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7218 if (!mono_error_ok (&error)) {
7219 mono_error_set_pending_exception (&error);
7224 if (klass == method->klass)
7227 /*This is possible if definition == FALSE.
7228 * Do it here to be really sure we don't read invalid memory.
7230 if (slot >= klass->vtable_size)
7233 mono_class_setup_vtable (klass);
7235 result = klass->vtable [slot];
7236 if (result == NULL) {
7237 /* It is an abstract method */
7238 gpointer iter = NULL;
7239 while ((result = mono_class_get_methods (klass, &iter)))
7240 if (result->slot == slot)
7247 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7248 mono_error_raise_exception (&error);
7252 ICALL_EXPORT MonoString*
7253 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7255 MonoMethod *method = m->method;
7257 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7262 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7264 iter->sig = *(MonoMethodSignature**)argsp;
7266 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7267 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7270 /* FIXME: it's not documented what start is exactly... */
7274 iter->args = argsp + sizeof (gpointer);
7276 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7278 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7281 ICALL_EXPORT MonoTypedRef
7282 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7284 guint32 i, arg_size;
7288 i = iter->sig->sentinelpos + iter->next_arg;
7290 g_assert (i < iter->sig->param_count);
7292 res.type = iter->sig->params [i];
7293 res.klass = mono_class_from_mono_type (res.type);
7294 arg_size = mono_type_stack_size (res.type, &align);
7295 #if defined(__arm__) || defined(__mips__)
7296 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7298 res.value = iter->args;
7299 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7300 /* Values are stored as 8 byte register sized objects, but 'value'
7301 * is dereferenced as a pointer in other routines.
7303 res.value = (char*)res.value + 4;
7305 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7306 if (arg_size <= sizeof (gpointer)) {
7308 int padding = arg_size - mono_type_size (res.type, &dummy);
7309 res.value = (guint8*)res.value + padding;
7312 iter->args = (char*)iter->args + arg_size;
7315 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7320 ICALL_EXPORT MonoTypedRef
7321 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7323 guint32 i, arg_size;
7327 i = iter->sig->sentinelpos + iter->next_arg;
7329 g_assert (i < iter->sig->param_count);
7331 while (i < iter->sig->param_count) {
7332 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7334 res.type = iter->sig->params [i];
7335 res.klass = mono_class_from_mono_type (res.type);
7336 /* FIXME: endianess issue... */
7337 arg_size = mono_type_stack_size (res.type, &align);
7338 #if defined(__arm__) || defined(__mips__)
7339 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7341 res.value = iter->args;
7342 iter->args = (char*)iter->args + arg_size;
7344 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7347 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7355 ICALL_EXPORT MonoType*
7356 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7360 i = iter->sig->sentinelpos + iter->next_arg;
7362 g_assert (i < iter->sig->param_count);
7364 return iter->sig->params [i];
7367 ICALL_EXPORT MonoObject*
7368 mono_TypedReference_ToObject (MonoTypedRef* tref)
7370 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7371 MonoObject** objp = (MonoObject **)tref->value;
7375 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
7378 ICALL_EXPORT MonoTypedRef
7379 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7382 MonoReflectionField *f;
7384 MonoType *ftype = NULL;
7388 memset (&res, 0, sizeof (res));
7391 g_assert (mono_array_length (fields) > 0);
7393 klass = target->vtable->klass;
7395 for (i = 0; i < mono_array_length (fields); ++i) {
7396 f = mono_array_get (fields, MonoReflectionField*, i);
7398 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7401 if (f->field->parent != klass) {
7402 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7406 p = (guint8*)target + f->field->offset;
7408 p += f->field->offset - sizeof (MonoObject);
7409 klass = mono_class_from_mono_type (f->field->type);
7410 ftype = f->field->type;
7414 res.klass = mono_class_from_mono_type (ftype);
7421 prelink_method (MonoMethod *method)
7423 const char *exc_class, *exc_arg;
7424 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7426 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7428 mono_raise_exception(
7429 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7431 /* create the wrapper, too? */
7435 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7437 prelink_method (method->method);
7441 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7443 MonoClass *klass = mono_class_from_mono_type (type->type);
7445 gpointer iter = NULL;
7447 mono_class_init_or_throw (klass);
7449 while ((m = mono_class_get_methods (klass, &iter)))
7453 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7455 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7456 gint32 const **exponents,
7457 gunichar2 const **digitLowerTable,
7458 gunichar2 const **digitUpperTable,
7459 gint64 const **tenPowersList,
7460 gint32 const **decHexDigits)
7462 *mantissas = Formatter_MantissaBitsTable;
7463 *exponents = Formatter_TensExponentTable;
7464 *digitLowerTable = Formatter_DigitLowerTable;
7465 *digitUpperTable = Formatter_DigitUpperTable;
7466 *tenPowersList = Formatter_TenPowersList;
7467 *decHexDigits = Formatter_DecHexDigits;
7471 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7472 * and avoid useless allocations.
7477 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7480 MonoReflectionType *rt;
7483 for (i = 0; i < type->num_mods; ++i) {
7484 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7489 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7491 for (i = 0; i < type->num_mods; ++i) {
7492 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7493 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
7494 mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */
7496 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, &error);
7497 mono_error_raise_exception (&error);
7499 mono_array_setref (res, count, rt);
7506 ICALL_EXPORT MonoArray*
7507 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7509 MonoType *type = param->ClassImpl->type;
7510 MonoClass *member_class = mono_object_class (param->MemberImpl);
7511 MonoMethod *method = NULL;
7514 MonoMethodSignature *sig;
7516 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7517 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7518 method = rmethod->method;
7519 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7520 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7521 if (!(method = prop->property->get))
7522 method = prop->property->set;
7525 char *type_name = mono_type_get_full_name (member_class);
7526 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7527 MonoException *ex = mono_get_exception_not_supported (msg);
7530 mono_set_pending_exception (ex);
7534 image = method->klass->image;
7535 pos = param->PositionImpl;
7536 sig = mono_method_signature (method);
7540 type = sig->params [pos];
7542 return type_array_from_modifiers (image, type, optional);
7546 get_property_type (MonoProperty *prop)
7548 MonoMethodSignature *sig;
7550 sig = mono_method_signature (prop->get);
7552 } else if (prop->set) {
7553 sig = mono_method_signature (prop->set);
7554 return sig->params [sig->param_count - 1];
7559 ICALL_EXPORT MonoArray*
7560 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7562 MonoType *type = get_property_type (property->property);
7563 MonoImage *image = property->klass->image;
7567 return type_array_from_modifiers (image, type, optional);
7571 *Construct a MonoType suited to be used to decode a constant blob object.
7573 * @type is the target type which will be constructed
7574 * @blob_type is the blob type, for example, that comes from the constant table
7575 * @real_type is the expected constructed type.
7578 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7580 type->type = blob_type;
7581 type->data.klass = NULL;
7582 if (blob_type == MONO_TYPE_CLASS)
7583 type->data.klass = mono_defaults.object_class;
7584 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7585 /* For enums, we need to use the base type */
7586 type->type = MONO_TYPE_VALUETYPE;
7587 type->data.klass = mono_class_from_mono_type (real_type);
7589 type->data.klass = mono_class_from_mono_type (real_type);
7592 ICALL_EXPORT MonoObject*
7593 property_info_get_default_value (MonoReflectionProperty *property)
7596 MonoProperty *prop = property->property;
7597 MonoType *type = get_property_type (prop);
7598 MonoDomain *domain = mono_object_domain (property);
7599 MonoTypeEnum def_type;
7600 const char *def_value;
7603 mono_class_init (prop->parent);
7605 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7606 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7610 def_value = mono_class_get_property_default_value (prop, &def_type);
7612 mono_type_from_blob_type (&blob_type, def_type, type);
7613 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7618 ICALL_EXPORT MonoBoolean
7619 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7621 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7622 MonoCustomAttrInfo *cinfo;
7625 mono_class_init_or_throw (attr_class);
7627 cinfo = mono_reflection_get_custom_attrs_info (obj);
7630 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7632 mono_custom_attrs_free (cinfo);
7636 ICALL_EXPORT MonoArray*
7637 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7639 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7644 mono_class_init_or_throw (attr_class);
7646 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7647 if (!mono_error_ok (&error)) {
7648 mono_error_set_pending_exception (&error);
7652 if (mono_loader_get_last_error ()) {
7653 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7660 ICALL_EXPORT MonoString*
7661 ves_icall_Mono_Runtime_GetDisplayName (void)
7664 MonoString *display_name;
7666 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7667 display_name = mono_string_new (mono_domain_get (), info);
7669 return display_name;
7672 ICALL_EXPORT MonoString*
7673 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7676 MonoString *message;
7680 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7681 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7684 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7686 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7687 mono_error_raise_exception (&error);
7694 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7697 char *path_str = mono_string_to_utf8 (path);
7699 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7707 #ifndef DISABLE_ICALL_TABLES
7709 #define ICALL_TYPE(id,name,first)
7710 #define ICALL(id,name,func) Icall_ ## id,
7713 #include "metadata/icall-def.h"
7719 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7720 #define ICALL(id,name,func)
7722 #include "metadata/icall-def.h"
7728 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7729 #define ICALL(id,name,func)
7731 guint16 first_icall;
7734 static const IcallTypeDesc
7735 icall_type_descs [] = {
7736 #include "metadata/icall-def.h"
7740 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7743 #define ICALL_TYPE(id,name,first)
7746 #ifdef HAVE_ARRAY_ELEM_INIT
7747 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7748 #define MSGSTRFIELD1(line) str##line
7750 static const struct msgstrtn_t {
7751 #define ICALL(id,name,func)
7753 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7754 #include "metadata/icall-def.h"
7756 } icall_type_names_str = {
7757 #define ICALL_TYPE(id,name,first) (name),
7758 #include "metadata/icall-def.h"
7761 static const guint16 icall_type_names_idx [] = {
7762 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7763 #include "metadata/icall-def.h"
7766 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7768 static const struct msgstr_t {
7770 #define ICALL_TYPE(id,name,first)
7771 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7772 #include "metadata/icall-def.h"
7774 } icall_names_str = {
7775 #define ICALL(id,name,func) (name),
7776 #include "metadata/icall-def.h"
7779 static const guint16 icall_names_idx [] = {
7780 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7781 #include "metadata/icall-def.h"
7784 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7790 #define ICALL_TYPE(id,name,first) name,
7791 #define ICALL(id,name,func)
7792 static const char* const
7793 icall_type_names [] = {
7794 #include "metadata/icall-def.h"
7798 #define icall_type_name_get(id) (icall_type_names [(id)])
7802 #define ICALL_TYPE(id,name,first)
7803 #define ICALL(id,name,func) name,
7804 static const char* const
7806 #include "metadata/icall-def.h"
7809 #define icall_name_get(id) icall_names [(id)]
7811 #endif /* !HAVE_ARRAY_ELEM_INIT */
7815 #define ICALL_TYPE(id,name,first)
7816 #define ICALL(id,name,func) func,
7817 static const gconstpointer
7818 icall_functions [] = {
7819 #include "metadata/icall-def.h"
7823 #ifdef ENABLE_ICALL_SYMBOL_MAP
7826 #define ICALL_TYPE(id,name,first)
7827 #define ICALL(id,name,func) #func,
7828 static const gconstpointer
7829 icall_symbols [] = {
7830 #include "metadata/icall-def.h"
7835 #endif /* DISABLE_ICALL_TABLES */
7837 static mono_mutex_t icall_mutex;
7838 static GHashTable *icall_hash = NULL;
7839 static GHashTable *jit_icall_hash_name = NULL;
7840 static GHashTable *jit_icall_hash_addr = NULL;
7843 mono_icall_init (void)
7845 #ifndef DISABLE_ICALL_TABLES
7848 /* check that tables are sorted: disable in release */
7851 const char *prev_class = NULL;
7852 const char *prev_method;
7854 for (i = 0; i < Icall_type_num; ++i) {
7855 const IcallTypeDesc *desc;
7858 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7859 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7860 prev_class = icall_type_name_get (i);
7861 desc = &icall_type_descs [i];
7862 num_icalls = icall_desc_num_icalls (desc);
7863 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7864 for (j = 0; j < num_icalls; ++j) {
7865 const char *methodn = icall_name_get (desc->first_icall + j);
7866 if (prev_method && strcmp (prev_method, methodn) >= 0)
7867 g_print ("method %s should come before method %s\n", methodn, prev_method);
7868 prev_method = methodn;
7874 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7875 mono_os_mutex_init (&icall_mutex);
7879 mono_icall_lock (void)
7881 mono_locks_os_acquire (&icall_mutex, IcallLock);
7885 mono_icall_unlock (void)
7887 mono_locks_os_release (&icall_mutex, IcallLock);
7891 mono_icall_cleanup (void)
7893 g_hash_table_destroy (icall_hash);
7894 g_hash_table_destroy (jit_icall_hash_name);
7895 g_hash_table_destroy (jit_icall_hash_addr);
7896 mono_os_mutex_destroy (&icall_mutex);
7900 mono_add_internal_call (const char *name, gconstpointer method)
7904 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7906 mono_icall_unlock ();
7909 #ifndef DISABLE_ICALL_TABLES
7911 #ifdef HAVE_ARRAY_ELEM_INIT
7913 compare_method_imap (const void *key, const void *elem)
7915 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7916 return strcmp (key, method_name);
7920 find_method_icall (const IcallTypeDesc *imap, const char *name)
7922 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);
7925 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7929 compare_class_imap (const void *key, const void *elem)
7931 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7932 return strcmp (key, class_name);
7935 static const IcallTypeDesc*
7936 find_class_icalls (const char *name)
7938 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);
7941 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7944 #else /* HAVE_ARRAY_ELEM_INIT */
7947 compare_method_imap (const void *key, const void *elem)
7949 const char** method_name = (const char**)elem;
7950 return strcmp (key, *method_name);
7954 find_method_icall (const IcallTypeDesc *imap, const char *name)
7956 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7959 return (gpointer)icall_functions [(nameslot - icall_names)];
7963 compare_class_imap (const void *key, const void *elem)
7965 const char** class_name = (const char**)elem;
7966 return strcmp (key, *class_name);
7969 static const IcallTypeDesc*
7970 find_class_icalls (const char *name)
7972 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7975 return &icall_type_descs [nameslot - icall_type_names];
7978 #endif /* HAVE_ARRAY_ELEM_INIT */
7980 #endif /* DISABLE_ICALL_TABLES */
7983 * we should probably export this as an helper (handle nested types).
7984 * Returns the number of chars written in buf.
7987 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7989 int nspacelen, cnamelen;
7990 nspacelen = strlen (klass->name_space);
7991 cnamelen = strlen (klass->name);
7992 if (nspacelen + cnamelen + 2 > bufsize)
7995 memcpy (buf, klass->name_space, nspacelen);
7996 buf [nspacelen ++] = '.';
7998 memcpy (buf + nspacelen, klass->name, cnamelen);
7999 buf [nspacelen + cnamelen] = 0;
8000 return nspacelen + cnamelen;
8003 #ifdef DISABLE_ICALL_TABLES
8005 no_icall_table (void)
8007 g_assert_not_reached ();
8012 mono_lookup_internal_call (MonoMethod *method)
8017 int typelen = 0, mlen, siglen;
8019 #ifndef DISABLE_ICALL_TABLES
8020 const IcallTypeDesc *imap = NULL;
8023 g_assert (method != NULL);
8025 if (method->is_inflated)
8026 method = ((MonoMethodInflated *) method)->declaring;
8028 if (method->klass->nested_in) {
8029 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8033 mname [pos++] = '/';
8036 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8042 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8047 #ifndef DISABLE_ICALL_TABLES
8048 imap = find_class_icalls (mname);
8051 mname [typelen] = ':';
8052 mname [typelen + 1] = ':';
8054 mlen = strlen (method->name);
8055 memcpy (mname + typelen + 2, method->name, mlen);
8056 sigstart = mname + typelen + 2 + mlen;
8059 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8060 siglen = strlen (tmpsig);
8061 if (typelen + mlen + siglen + 6 > sizeof (mname))
8064 memcpy (sigstart + 1, tmpsig, siglen);
8065 sigstart [siglen + 1] = ')';
8066 sigstart [siglen + 2] = 0;
8071 res = g_hash_table_lookup (icall_hash, mname);
8073 mono_icall_unlock ();;
8076 /* try without signature */
8078 res = g_hash_table_lookup (icall_hash, mname);
8080 mono_icall_unlock ();
8084 #ifdef DISABLE_ICALL_TABLES
8085 mono_icall_unlock ();
8086 /* Fail only when the result is actually used */
8087 /* mono_marshal_get_native_wrapper () depends on this */
8088 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8089 return ves_icall_System_String_ctor_RedirectToCreateString;
8091 return no_icall_table;
8093 /* it wasn't found in the static call tables */
8095 mono_icall_unlock ();
8098 res = find_method_icall (imap, sigstart - mlen);
8100 mono_icall_unlock ();
8103 /* try _with_ signature */
8105 res = find_method_icall (imap, sigstart - mlen);
8107 mono_icall_unlock ();
8111 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8112 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8113 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8114 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8115 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");
8116 g_print ("If you see other errors or faults after this message they are probably related\n");
8117 g_print ("and you need to fix your mono install first.\n");
8119 mono_icall_unlock ();
8125 #ifdef ENABLE_ICALL_SYMBOL_MAP
8127 func_cmp (gconstpointer key, gconstpointer p)
8129 return (gsize)key - (gsize)*(gsize*)p;
8134 * mono_lookup_icall_symbol:
8136 * Given the icall METHOD, returns its C symbol.
8139 mono_lookup_icall_symbol (MonoMethod *m)
8141 #ifdef DISABLE_ICALL_TABLES
8142 g_assert_not_reached ();
8145 #ifdef ENABLE_ICALL_SYMBOL_MAP
8149 static gconstpointer *functions_sorted;
8150 static const char**symbols_sorted;
8151 static gboolean inited;
8156 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8157 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8158 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8159 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8160 /* Bubble sort the two arrays */
8164 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8165 if (functions_sorted [i] > functions_sorted [i + 1]) {
8168 tmp = functions_sorted [i];
8169 functions_sorted [i] = functions_sorted [i + 1];
8170 functions_sorted [i + 1] = tmp;
8171 tmp = symbols_sorted [i];
8172 symbols_sorted [i] = symbols_sorted [i + 1];
8173 symbols_sorted [i + 1] = tmp;
8180 func = mono_lookup_internal_call (m);
8183 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8187 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8189 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8190 g_assert_not_reached ();
8197 type_from_typename (char *type_name)
8199 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8201 if (!strcmp (type_name, "int"))
8202 klass = mono_defaults.int_class;
8203 else if (!strcmp (type_name, "ptr"))
8204 klass = mono_defaults.int_class;
8205 else if (!strcmp (type_name, "void"))
8206 klass = mono_defaults.void_class;
8207 else if (!strcmp (type_name, "int32"))
8208 klass = mono_defaults.int32_class;
8209 else if (!strcmp (type_name, "uint32"))
8210 klass = mono_defaults.uint32_class;
8211 else if (!strcmp (type_name, "int8"))
8212 klass = mono_defaults.sbyte_class;
8213 else if (!strcmp (type_name, "uint8"))
8214 klass = mono_defaults.byte_class;
8215 else if (!strcmp (type_name, "int16"))
8216 klass = mono_defaults.int16_class;
8217 else if (!strcmp (type_name, "uint16"))
8218 klass = mono_defaults.uint16_class;
8219 else if (!strcmp (type_name, "long"))
8220 klass = mono_defaults.int64_class;
8221 else if (!strcmp (type_name, "ulong"))
8222 klass = mono_defaults.uint64_class;
8223 else if (!strcmp (type_name, "float"))
8224 klass = mono_defaults.single_class;
8225 else if (!strcmp (type_name, "double"))
8226 klass = mono_defaults.double_class;
8227 else if (!strcmp (type_name, "object"))
8228 klass = mono_defaults.object_class;
8229 else if (!strcmp (type_name, "obj"))
8230 klass = mono_defaults.object_class;
8231 else if (!strcmp (type_name, "string"))
8232 klass = mono_defaults.string_class;
8233 else if (!strcmp (type_name, "bool"))
8234 klass = mono_defaults.boolean_class;
8235 else if (!strcmp (type_name, "boolean"))
8236 klass = mono_defaults.boolean_class;
8238 g_error ("%s", type_name);
8239 g_assert_not_reached ();
8241 return &klass->byval_arg;
8245 * LOCKING: Take the corlib image lock.
8247 MonoMethodSignature*
8248 mono_create_icall_signature (const char *sigstr)
8253 MonoMethodSignature *res, *res2;
8254 MonoImage *corlib = mono_defaults.corlib;
8256 mono_image_lock (corlib);
8257 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8258 mono_image_unlock (corlib);
8263 parts = g_strsplit (sigstr, " ", 256);
8272 res = mono_metadata_signature_alloc (corlib, len - 1);
8277 * Under windows, the default pinvoke calling convention is STDCALL but
8280 res->call_convention = MONO_CALL_C;
8283 res->ret = type_from_typename (parts [0]);
8284 for (i = 1; i < len; ++i) {
8285 res->params [i - 1] = type_from_typename (parts [i]);
8290 mono_image_lock (corlib);
8291 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8293 res = res2; /*Value is allocated in the image pool*/
8295 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8296 mono_image_unlock (corlib);
8302 mono_find_jit_icall_by_name (const char *name)
8304 MonoJitICallInfo *info;
8305 g_assert (jit_icall_hash_name);
8308 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8309 mono_icall_unlock ();
8314 mono_find_jit_icall_by_addr (gconstpointer addr)
8316 MonoJitICallInfo *info;
8317 g_assert (jit_icall_hash_addr);
8320 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8321 mono_icall_unlock ();
8327 * mono_get_jit_icall_info:
8329 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8330 * caller should access it while holding the icall lock.
8333 mono_get_jit_icall_info (void)
8335 return jit_icall_hash_name;
8339 * mono_lookup_jit_icall_symbol:
8341 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8344 mono_lookup_jit_icall_symbol (const char *name)
8346 MonoJitICallInfo *info;
8347 const char *res = NULL;
8350 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8352 res = info->c_symbol;
8353 mono_icall_unlock ();
8358 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8361 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8362 mono_icall_unlock ();
8366 * 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
8367 * icalls without wrappers in some cases.
8370 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8372 MonoJitICallInfo *info;
8379 if (!jit_icall_hash_name) {
8380 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8381 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8384 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8385 g_warning ("jit icall already defined \"%s\"\n", name);
8386 g_assert_not_reached ();
8389 info = g_new0 (MonoJitICallInfo, 1);
8394 info->c_symbol = c_symbol;
8395 info->no_raise = no_raise;
8398 info->wrapper = func;
8400 info->wrapper = NULL;
8403 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8404 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8406 mono_icall_unlock ();
8411 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8413 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);