5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
9 * Aleksey Kliger (aleksey@xamarin.com)
11 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
12 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
24 #ifdef HAVE_SYS_TIME_H
30 #if defined (HOST_WIN32)
33 #if defined (HAVE_WCHAR_H)
37 #include "mono/utils/mono-membar.h"
38 #include <mono/metadata/object.h>
39 #include <mono/metadata/threads.h>
40 #include <mono/metadata/threads-types.h>
41 #include <mono/metadata/threadpool-ms.h>
42 #include <mono/metadata/threadpool-ms-io.h>
43 #include <mono/metadata/monitor.h>
44 #include <mono/metadata/reflection.h>
45 #include <mono/metadata/assembly.h>
46 #include <mono/metadata/tabledefs.h>
47 #include <mono/metadata/exception.h>
48 #include <mono/metadata/file-io.h>
49 #include <mono/metadata/console-io.h>
50 #include <mono/metadata/mono-route.h>
51 #include <mono/metadata/socket-io.h>
52 #include <mono/metadata/mono-endian.h>
53 #include <mono/metadata/tokentype.h>
54 #include <mono/metadata/domain-internals.h>
55 #include <mono/metadata/metadata-internals.h>
56 #include <mono/metadata/class-internals.h>
57 #include <mono/metadata/reflection-internals.h>
58 #include <mono/metadata/marshal.h>
59 #include <mono/metadata/gc-internals.h>
60 #include <mono/metadata/mono-gc.h>
61 #include <mono/metadata/rand.h>
62 #include <mono/metadata/sysmath.h>
63 #include <mono/metadata/string-icalls.h>
64 #include <mono/metadata/debug-helpers.h>
65 #include <mono/metadata/process.h>
66 #include <mono/metadata/environment.h>
67 #include <mono/metadata/profiler-private.h>
68 #include <mono/metadata/locales.h>
69 #include <mono/metadata/filewatcher.h>
70 #include <mono/metadata/security.h>
71 #include <mono/metadata/mono-config.h>
72 #include <mono/metadata/cil-coff.h>
73 #include <mono/metadata/number-formatter.h>
74 #include <mono/metadata/security-manager.h>
75 #include <mono/metadata/security-core-clr.h>
76 #include <mono/metadata/mono-perfcounters.h>
77 #include <mono/metadata/mono-debug.h>
78 #include <mono/metadata/mono-ptr-array.h>
79 #include <mono/metadata/verify-internals.h>
80 #include <mono/metadata/runtime.h>
81 #include <mono/metadata/file-mmap.h>
82 #include <mono/metadata/seq-points-data.h>
83 #include <mono/io-layer/io-layer.h>
84 #include <mono/utils/monobitset.h>
85 #include <mono/utils/mono-time.h>
86 #include <mono/utils/mono-proclib.h>
87 #include <mono/utils/mono-string.h>
88 #include <mono/utils/mono-error-internals.h>
89 #include <mono/utils/mono-mmap.h>
90 #include <mono/utils/mono-io-portability.h>
91 #include <mono/utils/mono-digest.h>
92 #include <mono/utils/bsearch.h>
93 #include <mono/utils/mono-os-mutex.h>
94 #include <mono/utils/mono-threads.h>
96 #if defined (HOST_WIN32)
100 #include "decimal-ms.h"
101 #include "number-ms.h"
103 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
104 #include <sys/utsname.h>
107 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
109 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
112 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
114 static inline MonoBoolean
115 is_generic_parameter (MonoType *type)
117 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
121 mono_class_init_or_throw (MonoClass *klass)
123 if (!mono_class_init (klass))
124 mono_raise_exception (mono_class_get_exception_for_failure (klass));
127 ICALL_EXPORT MonoObject *
128 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
134 ac = (MonoClass *)arr->obj.vtable->klass;
136 esize = mono_array_element_size (ac);
137 ea = (gpointer*)((char*)arr->vector + (pos * esize));
139 if (ac->element_class->valuetype)
140 return mono_value_box (arr->obj.vtable->domain, ac->element_class, ea);
142 return (MonoObject *)*ea;
145 ICALL_EXPORT MonoObject *
146 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
152 MONO_CHECK_ARG_NULL (idxs, NULL);
155 ic = (MonoClass *)io->obj.vtable->klass;
157 ac = (MonoClass *)arr->obj.vtable->klass;
159 g_assert (ic->rank == 1);
160 if (io->bounds != NULL || io->max_length != ac->rank) {
161 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
165 ind = (gint32 *)io->vector;
167 if (arr->bounds == NULL) {
168 if (*ind < 0 || *ind >= arr->max_length) {
169 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
173 return ves_icall_System_Array_GetValueImpl (arr, *ind);
176 for (i = 0; i < ac->rank; i++) {
177 if ((ind [i] < arr->bounds [i].lower_bound) ||
178 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
179 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
184 pos = ind [0] - arr->bounds [0].lower_bound;
185 for (i = 1; i < ac->rank; i++)
186 pos = pos * arr->bounds [i].length + ind [i] -
187 arr->bounds [i].lower_bound;
189 return ves_icall_System_Array_GetValueImpl (arr, pos);
193 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
195 MonoClass *ac, *vc, *ec;
205 vc = value->vtable->klass;
209 ac = arr->obj.vtable->klass;
210 ec = ac->element_class;
212 esize = mono_array_element_size (ac);
213 ea = (gpointer*)((char*)arr->vector + (pos * esize));
214 va = (gpointer*)((char*)value + sizeof (MonoObject));
216 if (mono_class_is_nullable (ec)) {
217 mono_nullable_init ((guint8*)ea, value, ec);
222 mono_gc_bzero_atomic (ea, esize);
226 #define NO_WIDENING_CONVERSION G_STMT_START{\
227 mono_set_pending_exception (mono_get_exception_argument ( \
228 "value", "not a widening conversion")); \
232 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
233 if (esize < vsize + (extra)) { \
234 mono_set_pending_exception (mono_get_exception_argument ( \
235 "value", "not a widening conversion")); \
240 #define INVALID_CAST G_STMT_START{ \
241 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
242 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
246 /* Check element (destination) type. */
247 switch (ec->byval_arg.type) {
248 case MONO_TYPE_STRING:
249 switch (vc->byval_arg.type) {
250 case MONO_TYPE_STRING:
256 case MONO_TYPE_BOOLEAN:
257 switch (vc->byval_arg.type) {
258 case MONO_TYPE_BOOLEAN:
271 NO_WIDENING_CONVERSION;
280 if (!ec->valuetype) {
281 if (!mono_object_isinst (value, ec))
283 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
287 if (mono_object_isinst (value, ec)) {
288 if (ec->has_references)
289 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
291 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
298 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
300 et = ec->byval_arg.type;
301 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
302 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
304 vt = vc->byval_arg.type;
305 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
306 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
308 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
314 case MONO_TYPE_CHAR: \
315 CHECK_WIDENING_CONVERSION(0); \
316 *(etype *) ea = (etype) u64; \
318 /* You can't assign a signed value to an unsigned array. */ \
323 /* You can't assign a floating point number to an integer array. */ \
326 NO_WIDENING_CONVERSION; \
330 #define ASSIGN_SIGNED(etype) G_STMT_START{\
336 CHECK_WIDENING_CONVERSION(0); \
337 *(etype *) ea = (etype) i64; \
339 /* You can assign an unsigned value to a signed array if the array's */ \
340 /* element size is larger than the value size. */ \
345 case MONO_TYPE_CHAR: \
346 CHECK_WIDENING_CONVERSION(1); \
347 *(etype *) ea = (etype) u64; \
349 /* You can't assign a floating point number to an integer array. */ \
352 NO_WIDENING_CONVERSION; \
356 #define ASSIGN_REAL(etype) G_STMT_START{\
360 CHECK_WIDENING_CONVERSION(0); \
361 *(etype *) ea = (etype) r64; \
363 /* All integer values fit into a floating point array, so we don't */ \
364 /* need to CHECK_WIDENING_CONVERSION here. */ \
369 *(etype *) ea = (etype) i64; \
375 case MONO_TYPE_CHAR: \
376 *(etype *) ea = (etype) u64; \
383 u64 = *(guint8 *) va;
386 u64 = *(guint16 *) va;
389 u64 = *(guint32 *) va;
392 u64 = *(guint64 *) va;
398 i64 = *(gint16 *) va;
401 i64 = *(gint32 *) va;
404 i64 = *(gint64 *) va;
407 r64 = *(gfloat *) va;
410 r64 = *(gdouble *) va;
413 u64 = *(guint16 *) va;
415 case MONO_TYPE_BOOLEAN:
416 /* Boolean is only compatible with itself. */
429 NO_WIDENING_CONVERSION;
436 /* If we can't do a direct copy, let's try a widening conversion. */
439 ASSIGN_UNSIGNED (guint16);
441 ASSIGN_UNSIGNED (guint8);
443 ASSIGN_UNSIGNED (guint16);
445 ASSIGN_UNSIGNED (guint32);
447 ASSIGN_UNSIGNED (guint64);
449 ASSIGN_SIGNED (gint8);
451 ASSIGN_SIGNED (gint16);
453 ASSIGN_SIGNED (gint32);
455 ASSIGN_SIGNED (gint64);
457 ASSIGN_REAL (gfloat);
459 ASSIGN_REAL (gdouble);
463 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
467 #undef NO_WIDENING_CONVERSION
468 #undef CHECK_WIDENING_CONVERSION
469 #undef ASSIGN_UNSIGNED
475 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
481 MONO_CHECK_ARG_NULL (idxs,);
483 ic = idxs->obj.vtable->klass;
484 ac = arr->obj.vtable->klass;
486 g_assert (ic->rank == 1);
487 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
488 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
492 ind = (gint32 *)idxs->vector;
494 if (arr->bounds == NULL) {
495 if (*ind < 0 || *ind >= arr->max_length) {
496 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
500 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
504 for (i = 0; i < ac->rank; i++)
505 if ((ind [i] < arr->bounds [i].lower_bound) ||
506 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
507 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
511 pos = ind [0] - arr->bounds [0].lower_bound;
512 for (i = 1; i < ac->rank; i++)
513 pos = pos * arr->bounds [i].length + ind [i] -
514 arr->bounds [i].lower_bound;
516 ves_icall_System_Array_SetValueImpl (arr, value, pos);
519 ICALL_EXPORT MonoArray *
520 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
523 MonoClass *aklass, *klass;
526 gboolean bounded = FALSE;
528 MONO_CHECK_ARG_NULL (type, NULL);
529 MONO_CHECK_ARG_NULL (lengths, NULL);
531 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
533 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
535 for (i = 0; i < mono_array_length (lengths); i++) {
536 if (mono_array_get (lengths, gint32, i) < 0) {
537 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
542 klass = mono_class_from_mono_type (type->type);
543 mono_class_init_or_throw (klass);
545 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
546 /* vectors are not the same as one dimensional arrays with no-zero bounds */
551 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
553 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
554 for (i = 0; i < aklass->rank; ++i) {
555 sizes [i] = mono_array_get (lengths, guint32, i);
557 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
559 sizes [i + aklass->rank] = 0;
562 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
563 mono_error_set_pending_exception (&error);
568 ICALL_EXPORT MonoArray *
569 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
572 MonoClass *aklass, *klass;
575 gboolean bounded = FALSE;
577 MONO_CHECK_ARG_NULL (type, NULL);
578 MONO_CHECK_ARG_NULL (lengths, NULL);
580 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
582 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
584 for (i = 0; i < mono_array_length (lengths); i++) {
585 if ((mono_array_get (lengths, gint64, i) < 0) ||
586 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
587 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
592 klass = mono_class_from_mono_type (type->type);
593 mono_class_init_or_throw (klass);
595 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
596 /* vectors are not the same as one dimensional arrays with no-zero bounds */
601 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
603 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
604 for (i = 0; i < aklass->rank; ++i) {
605 sizes [i] = mono_array_get (lengths, guint64, i);
607 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
609 sizes [i + aklass->rank] = 0;
612 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
613 mono_error_set_pending_exception (&error);
619 ves_icall_System_Array_GetRank (MonoObject *arr)
621 return arr->vtable->klass->rank;
625 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
627 gint32 rank = arr->obj.vtable->klass->rank;
630 if ((dimension < 0) || (dimension >= rank)) {
631 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
635 if (arr->bounds == NULL)
636 length = arr->max_length;
638 length = arr->bounds [dimension].length;
640 #ifdef MONO_BIG_ARRAYS
641 if (length > G_MAXINT32) {
642 mono_set_pending_exception (mono_get_exception_overflow ());
650 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
652 gint32 rank = arr->obj.vtable->klass->rank;
654 if ((dimension < 0) || (dimension >= rank)) {
655 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
659 if (arr->bounds == NULL)
660 return arr->max_length;
662 return arr->bounds [dimension].length;
666 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
668 gint32 rank = arr->obj.vtable->klass->rank;
670 if ((dimension < 0) || (dimension >= rank)) {
671 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
675 if (arr->bounds == NULL)
678 return arr->bounds [dimension].lower_bound;
682 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
684 int sz = mono_array_element_size (mono_object_class (arr));
685 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
688 ICALL_EXPORT gboolean
689 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
694 MonoVTable *src_vtable;
695 MonoVTable *dest_vtable;
696 MonoClass *src_class;
697 MonoClass *dest_class;
699 src_vtable = source->obj.vtable;
700 dest_vtable = dest->obj.vtable;
702 if (src_vtable->rank != dest_vtable->rank)
705 if (source->bounds || dest->bounds)
708 /* there's no integer overflow since mono_array_length returns an unsigned integer */
709 if ((dest_idx + length > mono_array_length_fast (dest)) ||
710 (source_idx + length > mono_array_length_fast (source)))
713 src_class = src_vtable->klass->element_class;
714 dest_class = dest_vtable->klass->element_class;
717 * Handle common cases.
720 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
721 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
723 if (src_class == mono_defaults.object_class && dest_class->valuetype)
726 /* Check if we're copying a char[] <==> (u)short[] */
727 if (src_class != dest_class) {
728 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
731 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
732 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
736 if (dest_class->valuetype) {
737 element_size = mono_array_element_size (source->obj.vtable->klass);
738 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
739 if (dest_class->has_references) {
740 mono_value_copy_array (dest, dest_idx, source_addr, length);
742 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
743 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
746 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
753 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
759 ac = (MonoClass *)arr->obj.vtable->klass;
761 esize = mono_array_element_size (ac);
762 ea = (gpointer*)((char*)arr->vector + (pos * esize));
764 mono_gc_memmove_atomic (value, ea, esize);
768 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
774 ac = (MonoClass *)arr->obj.vtable->klass;
775 ec = ac->element_class;
777 esize = mono_array_element_size (ac);
778 ea = (gpointer*)((char*)arr->vector + (pos * esize));
780 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
781 g_assert (esize == sizeof (gpointer));
782 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
784 g_assert (ec->inited);
785 g_assert (esize == mono_class_value_size (ec, NULL));
786 if (ec->has_references)
787 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
789 mono_gc_memmove_atomic (ea, value, esize);
794 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
796 MonoClass *klass = array->obj.vtable->klass;
797 guint32 size = mono_array_element_size (klass);
798 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
800 const char *field_data;
802 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
803 MonoException *exc = mono_get_exception_argument("array",
804 "Cannot initialize array of non-primitive type.");
805 mono_set_pending_exception (exc);
809 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
810 MonoException *exc = mono_get_exception_argument("field_handle",
811 "Field doesn't have an RVA");
812 mono_set_pending_exception (exc);
816 size *= array->max_length;
817 field_data = mono_field_get_data (field_handle);
819 if (size > mono_type_size (field_handle->type, &align)) {
820 MonoException *exc = mono_get_exception_argument("field_handle",
821 "Field not large enough to fill array");
822 mono_set_pending_exception (exc);
826 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
828 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
829 guint ## n *src = (guint ## n *) field_data; \
831 nEnt = (size / sizeof(guint ## n)); \
833 for (i = 0; i < nEnt; i++) { \
834 data[i] = read ## n (&src[i]); \
838 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
840 switch (type->type) {
857 memcpy (mono_array_addr (array, char, 0), field_data, size);
861 memcpy (mono_array_addr (array, char, 0), field_data, size);
866 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
868 return offsetof (MonoString, chars);
871 ICALL_EXPORT MonoObject *
872 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
874 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
878 MonoObject *ret = mono_object_clone_checked (obj, &error);
879 mono_error_set_pending_exception (&error);
886 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
891 MONO_CHECK_ARG_NULL (handle,);
893 klass = mono_class_from_mono_type (handle);
894 MONO_CHECK_ARG (handle, klass,);
896 if (klass->generic_container)
899 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
901 /* This will call the type constructor */
902 mono_runtime_class_init (vtable);
906 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
910 mono_image_check_for_module_cctor (image);
911 if (image->has_module_cctor) {
912 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
913 if (!mono_error_ok (&error)) {
914 mono_error_set_pending_exception (&error);
917 /*It's fine to raise the exception here*/
918 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
922 ICALL_EXPORT MonoBoolean
923 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
928 /* later make this configurable and per-arch */
929 int min_size = 4096 * 4 * sizeof (void*);
930 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
931 /* if we have no info we are optimistic and assume there is enough room */
935 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
939 current = (guint8 *)&stack_addr;
940 if (current > stack_addr) {
941 if ((current - stack_addr) < min_size)
944 if (current - (stack_addr - stack_size) < min_size)
950 ICALL_EXPORT MonoObject *
951 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
954 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
955 mono_error_set_pending_exception (&error);
961 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
964 MonoObject **values = NULL;
967 gint32 result = (int)(gsize)mono_defaults.int32_class;
968 MonoClassField* field;
971 klass = mono_object_class (this_obj);
973 if (mono_class_num_fields (klass) == 0)
977 * Compute the starting value of the hashcode for fields of primitive
978 * types, and return the remaining fields in an array to the managed side.
979 * This way, we can avoid costly reflection operations in managed code.
982 while ((field = mono_class_get_fields (klass, &iter))) {
983 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
985 if (mono_field_is_deleted (field))
987 /* FIXME: Add more types */
988 switch (field->type->type) {
990 result ^= *(gint32*)((guint8*)this_obj + field->offset);
992 case MONO_TYPE_STRING: {
994 s = *(MonoString**)((guint8*)this_obj + field->offset);
996 result ^= mono_string_hash (s);
1001 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1002 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1003 values [count++] = o;
1009 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1010 for (i = 0; i < count; ++i)
1011 mono_array_setref (*fields, i, values [i]);
1018 ICALL_EXPORT MonoBoolean
1019 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1022 MonoObject **values = NULL;
1024 MonoClassField* field;
1028 MONO_CHECK_ARG_NULL (that, FALSE);
1030 if (this_obj->vtable != that->vtable)
1033 klass = mono_object_class (this_obj);
1035 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1036 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1039 * Do the comparison for fields of primitive type and return a result if
1040 * possible. Otherwise, return the remaining fields in an array to the
1041 * managed side. This way, we can avoid costly reflection operations in
1046 while ((field = mono_class_get_fields (klass, &iter))) {
1047 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1049 if (mono_field_is_deleted (field))
1051 /* FIXME: Add more types */
1052 switch (field->type->type) {
1055 case MONO_TYPE_BOOLEAN:
1056 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1061 case MONO_TYPE_CHAR:
1062 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1067 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1072 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1076 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1080 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1085 case MONO_TYPE_STRING: {
1086 MonoString *s1, *s2;
1087 guint32 s1len, s2len;
1088 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1089 s2 = *(MonoString**)((guint8*)that + field->offset);
1092 if ((s1 == NULL) || (s2 == NULL))
1094 s1len = mono_string_length (s1);
1095 s2len = mono_string_length (s2);
1099 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1105 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1106 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1107 values [count++] = o;
1108 o = mono_field_get_value_object (mono_object_domain (this_obj), field, that);
1109 values [count++] = o;
1112 if (klass->enumtype)
1113 /* enums only have one non-static field */
1119 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1120 for (i = 0; i < count; ++i)
1121 mono_array_setref_fast (*fields, i, values [i]);
1128 ICALL_EXPORT MonoReflectionType *
1129 ves_icall_System_Object_GetType (MonoObject *obj)
1132 MonoReflectionType *ret;
1133 #ifndef DISABLE_REMOTING
1134 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1135 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1138 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1140 mono_error_raise_exception (&error);
1146 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1148 mtype->type = &obj->vtable->klass->byval_arg;
1149 g_assert (mtype->type->type);
1153 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1155 MONO_CHECK_ARG_NULL (obj, 0);
1157 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1161 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1162 MonoReflectionMethod *method,
1163 MonoArray *opt_param_types)
1165 MONO_CHECK_ARG_NULL (method, 0);
1167 return mono_image_create_method_token (
1168 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1172 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1174 mono_image_create_pefile (mb, file);
1178 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1180 mono_image_build_metadata (mb);
1184 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1186 mono_image_register_token (mb->dynamic_image, token, obj);
1189 ICALL_EXPORT MonoObject*
1190 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1194 mono_loader_lock ();
1195 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1196 mono_loader_unlock ();
1202 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1204 MonoMethod **dest = (MonoMethod **)data;
1206 /* skip unmanaged frames */
1222 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1224 MonoMethod **dest = (MonoMethod **)data;
1226 /* skip unmanaged frames */
1231 if (!strcmp (m->klass->name_space, "System.Reflection"))
1240 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1242 MonoMethod **dest = (MonoMethod **)data;
1244 /* skip unmanaged frames */
1248 if (m->wrapper_type != MONO_WRAPPER_NONE)
1251 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1265 static MonoReflectionType *
1266 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase)
1269 MonoReflectionType *ret;
1270 MonoMethod *m, *dest;
1272 MonoType *type = NULL;
1273 MonoAssembly *assembly = NULL;
1274 gboolean type_resolve = FALSE;
1277 * We must compute the calling assembly as type loading must happen under a metadata context.
1278 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1279 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1281 m = mono_method_get_last_managed ();
1284 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1289 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1290 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1291 * to crash. This only seems to happen in some strange remoting
1292 * scenarios and I was unable to figure out what's happening there.
1293 * Dec 10, 2005 - Martin.
1297 assembly = dest->klass->image->assembly;
1298 type_resolve = TRUE;
1300 g_warning (G_STRLOC);
1303 if (info->assembly.name)
1304 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1308 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1309 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1312 if (!info->assembly.name && !type) /* try mscorlib */
1313 type = mono_reflection_get_type (NULL, info, ignoreCase, &type_resolve);
1315 if (assembly && !type && type_resolve) {
1316 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1317 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1323 ret = mono_type_get_object_checked (mono_domain_get (), type, &error);
1324 mono_error_raise_exception (&error); /* FIXME don't raise here */
1330 MonoReflectionType *
1331 mono_type_get (const char *str)
1333 char *copy = g_strdup (str);
1334 MonoTypeNameParse info;
1335 MonoReflectionType *type;
1338 parsedOk = mono_reflection_parse_type(copy, &info);
1340 mono_reflection_free_type_info (&info);
1345 type = type_from_parsed_name (&info, FALSE);
1347 mono_reflection_free_type_info (&info);
1354 ICALL_EXPORT MonoReflectionType*
1355 ves_icall_type_from_name (MonoString *name,
1356 MonoBoolean throwOnError,
1357 MonoBoolean ignoreCase)
1359 char *str = mono_string_to_utf8 (name);
1360 MonoTypeNameParse info;
1361 MonoReflectionType *type;
1364 parsedOk = mono_reflection_parse_type (str, &info);
1366 /* mono_reflection_parse_type() mangles the string */
1368 mono_reflection_free_type_info (&info);
1371 mono_set_pending_exception (mono_get_exception_argument("typeName", "failed parse"));
1376 type = type_from_parsed_name (&info, ignoreCase);
1378 mono_reflection_free_type_info (&info);
1382 MonoException *e = NULL;
1385 e = mono_get_exception_type_load (name, NULL);
1387 mono_loader_clear_error ();
1389 mono_set_pending_exception (e);
1398 ICALL_EXPORT MonoReflectionType*
1399 ves_icall_type_from_handle (MonoType *handle)
1402 MonoReflectionType *ret;
1403 MonoDomain *domain = mono_domain_get ();
1405 ret = mono_type_get_object_checked (domain, handle, &error);
1406 mono_error_raise_exception (&error);
1411 /* System.TypeCode */
1430 TYPECODE_STRING = 18
1433 ICALL_EXPORT guint32
1434 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1436 int t = type->type->type;
1438 if (type->type->byref)
1439 return TYPECODE_OBJECT;
1443 case MONO_TYPE_VOID:
1444 return TYPECODE_OBJECT;
1445 case MONO_TYPE_BOOLEAN:
1446 return TYPECODE_BOOLEAN;
1448 return TYPECODE_BYTE;
1450 return TYPECODE_SBYTE;
1452 return TYPECODE_UINT16;
1454 return TYPECODE_INT16;
1455 case MONO_TYPE_CHAR:
1456 return TYPECODE_CHAR;
1460 return TYPECODE_OBJECT;
1462 return TYPECODE_UINT32;
1464 return TYPECODE_INT32;
1466 return TYPECODE_UINT64;
1468 return TYPECODE_INT64;
1470 return TYPECODE_SINGLE;
1472 return TYPECODE_DOUBLE;
1473 case MONO_TYPE_VALUETYPE: {
1474 MonoClass *klass = type->type->data.klass;
1476 if (klass->enumtype) {
1477 t = mono_class_enum_basetype (klass)->type;
1479 } else if (mono_is_corlib_image (klass->image)) {
1480 if (strcmp (klass->name_space, "System") == 0) {
1481 if (strcmp (klass->name, "Decimal") == 0)
1482 return TYPECODE_DECIMAL;
1483 else if (strcmp (klass->name, "DateTime") == 0)
1484 return TYPECODE_DATETIME;
1487 return TYPECODE_OBJECT;
1489 case MONO_TYPE_STRING:
1490 return TYPECODE_STRING;
1491 case MONO_TYPE_SZARRAY:
1492 case MONO_TYPE_ARRAY:
1493 case MONO_TYPE_OBJECT:
1495 case MONO_TYPE_MVAR:
1496 case MONO_TYPE_TYPEDBYREF:
1497 return TYPECODE_OBJECT;
1498 case MONO_TYPE_CLASS:
1500 MonoClass *klass = type->type->data.klass;
1501 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1502 if (strcmp (klass->name, "DBNull") == 0)
1503 return TYPECODE_DBNULL;
1506 return TYPECODE_OBJECT;
1507 case MONO_TYPE_GENERICINST:
1508 return TYPECODE_OBJECT;
1510 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1516 mono_type_is_primitive (MonoType *type)
1518 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1519 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1523 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1525 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1526 return mono_class_enum_basetype (type->data.klass);
1527 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1528 return mono_class_enum_basetype (type->data.generic_class->container_class);
1532 ICALL_EXPORT guint32
1533 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1538 g_assert (type != NULL);
1540 klass = mono_class_from_mono_type (type->type);
1541 klassc = mono_class_from_mono_type (c->type);
1543 if (type->type->byref ^ c->type->byref)
1546 if (type->type->byref) {
1547 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1548 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1550 klass = mono_class_from_mono_type (t);
1551 klassc = mono_class_from_mono_type (ot);
1553 if (mono_type_is_primitive (t)) {
1554 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1555 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1556 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1557 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1558 return t->type == ot->type;
1560 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1563 if (klass->valuetype)
1564 return klass == klassc;
1565 return klass->valuetype == klassc->valuetype;
1568 return mono_class_is_assignable_from (klass, klassc);
1571 ICALL_EXPORT guint32
1572 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1574 MonoClass *klass = mono_class_from_mono_type (type->type);
1575 mono_class_init_or_throw (klass);
1576 return mono_object_isinst (obj, klass) != NULL;
1579 ICALL_EXPORT guint32
1580 ves_icall_get_attributes (MonoReflectionType *type)
1582 MonoClass *klass = mono_class_from_mono_type (type->type);
1583 return klass->flags;
1586 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1587 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1589 MonoClass *klass = field->field->parent;
1590 MonoMarshalType *info;
1594 if (klass->generic_container ||
1595 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1598 ftype = mono_field_get_type (field->field);
1599 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1602 info = mono_marshal_load_type_info (klass);
1604 for (i = 0; i < info->num_fields; ++i) {
1605 if (info->fields [i].field == field->field) {
1606 if (!info->fields [i].mspec)
1609 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1616 ICALL_EXPORT MonoReflectionField*
1617 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1620 gboolean found = FALSE;
1627 klass = handle->parent;
1629 klass = mono_class_from_mono_type (type);
1631 /* Check that the field belongs to the class */
1632 for (k = klass; k; k = k->parent) {
1633 if (k == handle->parent) {
1640 /* The managed code will throw the exception */
1644 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1645 mono_error_raise_exception (&error);
1649 ICALL_EXPORT MonoArray*
1650 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1653 MonoType *type = mono_field_get_type_checked (field->field, &error);
1654 if (!mono_error_ok (&error)) {
1655 mono_error_set_pending_exception (&error);
1659 return type_array_from_modifiers (field->field->parent->image, type, optional);
1663 vell_icall_get_method_attributes (MonoMethod *method)
1665 return method->flags;
1669 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1672 MonoReflectionType *rt;
1673 MonoDomain *domain = mono_domain_get ();
1674 MonoMethodSignature* sig;
1676 sig = mono_method_signature_checked (method, &error);
1677 if (!mono_error_ok (&error)) {
1678 mono_error_set_pending_exception (&error);
1682 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1683 if (!mono_error_ok (&error)) {
1684 mono_error_set_pending_exception (&error);
1688 MONO_STRUCT_SETREF (info, parent, rt);
1690 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1691 if (!mono_error_ok (&error)) {
1692 mono_error_set_pending_exception (&error);
1696 MONO_STRUCT_SETREF (info, ret, rt);
1698 info->attrs = method->flags;
1699 info->implattrs = method->iflags;
1700 if (sig->call_convention == MONO_CALL_DEFAULT)
1701 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1703 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1708 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1711 ICALL_EXPORT MonoArray*
1712 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1714 MonoDomain *domain = mono_domain_get ();
1716 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1719 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1720 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1722 MonoDomain *domain = mono_domain_get ();
1723 MonoReflectionMarshalAsAttribute* res = NULL;
1724 MonoMarshalSpec **mspecs;
1727 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1728 mono_method_get_marshal_info (method, mspecs);
1731 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1733 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1735 mono_metadata_free_marshal_spec (mspecs [i]);
1742 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1744 MonoClass *parent = field->field->parent;
1745 if (!parent->size_inited)
1746 mono_class_init (parent);
1747 mono_class_setup_fields_locking (parent);
1749 return field->field->offset - sizeof (MonoObject);
1752 ICALL_EXPORT MonoReflectionType*
1753 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1756 MonoReflectionType *ret;
1759 parent = declaring? field->field->parent: field->klass;
1761 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1762 mono_error_raise_exception (&error);
1768 ICALL_EXPORT MonoObject *
1769 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1771 MonoClass *fklass = field->klass;
1772 MonoClassField *cf = field->field;
1773 MonoDomain *domain = mono_object_domain (field);
1775 if (fklass->image->assembly->ref_only) {
1776 mono_set_pending_exception (mono_get_exception_invalid_operation (
1777 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1781 if (mono_security_core_clr_enabled ())
1782 mono_security_core_clr_ensure_reflection_access_field (cf);
1784 return mono_field_get_value_object (domain, cf, obj);
1788 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1791 MonoClassField *cf = field->field;
1795 if (field->klass->image->assembly->ref_only) {
1796 mono_set_pending_exception (mono_get_exception_invalid_operation (
1797 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1801 if (mono_security_core_clr_enabled ())
1802 mono_security_core_clr_ensure_reflection_access_field (cf);
1804 type = mono_field_get_type_checked (cf, &error);
1805 if (!mono_error_ok (&error)) {
1806 mono_error_set_pending_exception (&error);
1810 v = (gchar *) value;
1812 switch (type->type) {
1815 case MONO_TYPE_BOOLEAN:
1818 case MONO_TYPE_CHAR:
1827 case MONO_TYPE_VALUETYPE:
1830 v += sizeof (MonoObject);
1832 case MONO_TYPE_STRING:
1833 case MONO_TYPE_OBJECT:
1834 case MONO_TYPE_CLASS:
1835 case MONO_TYPE_ARRAY:
1836 case MONO_TYPE_SZARRAY:
1839 case MONO_TYPE_GENERICINST: {
1840 MonoGenericClass *gclass = type->data.generic_class;
1841 g_assert (!gclass->context.class_inst->is_open);
1843 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1844 MonoClass *nklass = mono_class_from_mono_type (type);
1845 MonoObject *nullable;
1848 * Convert the boxed vtype into a Nullable structure.
1849 * This is complicated by the fact that Nullables have
1850 * a variable structure.
1852 nullable = mono_object_new (mono_domain_get (), nklass);
1854 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1856 v = (gchar *)mono_object_unbox (nullable);
1859 if (gclass->container_class->valuetype && (v != NULL))
1860 v += sizeof (MonoObject);
1864 g_error ("type 0x%x not handled in "
1865 "ves_icall_FieldInfo_SetValueInternal", type->type);
1870 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1871 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1872 if (!vtable->initialized)
1873 mono_runtime_class_init (vtable);
1874 mono_field_static_set_value (vtable, cf, v);
1876 mono_field_set_value (obj, cf, v);
1881 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1890 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1891 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1895 if (MONO_TYPE_IS_REFERENCE (f->type))
1896 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1898 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1901 ICALL_EXPORT MonoObject *
1902 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1904 MonoObject *o = NULL;
1905 MonoClassField *field = rfield->field;
1907 MonoDomain *domain = mono_object_domain (rfield);
1909 MonoTypeEnum def_type;
1910 const char *def_value;
1914 mono_class_init (field->parent);
1916 t = mono_field_get_type_checked (field, &error);
1917 if (!mono_error_ok (&error)) {
1918 mono_error_set_pending_exception (&error);
1922 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
1923 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1927 if (image_is_dynamic (field->parent->image)) {
1928 MonoClass *klass = field->parent;
1929 int fidx = field - klass->fields;
1931 g_assert (fidx >= 0 && fidx < klass->field.count);
1932 g_assert (klass->ext);
1933 g_assert (klass->ext->field_def_values);
1934 def_type = klass->ext->field_def_values [fidx].def_type;
1935 def_value = klass->ext->field_def_values [fidx].data;
1936 if (def_type == MONO_TYPE_END) {
1937 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1941 def_value = mono_class_get_field_default_value (field, &def_type);
1942 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
1944 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1949 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1953 case MONO_TYPE_BOOLEAN:
1956 case MONO_TYPE_CHAR:
1964 case MONO_TYPE_R8: {
1967 /* boxed value type */
1968 t = g_new0 (MonoType, 1);
1970 klass = mono_class_from_mono_type (t);
1972 o = mono_object_new (domain, klass);
1973 v = ((gchar *) o) + sizeof (MonoObject);
1974 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1977 case MONO_TYPE_STRING:
1978 case MONO_TYPE_CLASS:
1979 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1982 g_assert_not_reached ();
1988 ICALL_EXPORT MonoReflectionType*
1989 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1992 MonoReflectionType *ret;
1995 type = mono_field_get_type_checked (ref_field->field, &error);
1996 if (!mono_error_ok (&error)) {
1997 mono_error_set_pending_exception (&error);
2001 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2002 if (!mono_error_ok (&error)) {
2003 mono_error_set_pending_exception (&error);
2010 /* From MonoProperty.cs */
2012 PInfo_Attributes = 1,
2013 PInfo_GetMethod = 1 << 1,
2014 PInfo_SetMethod = 1 << 2,
2015 PInfo_ReflectedType = 1 << 3,
2016 PInfo_DeclaringType = 1 << 4,
2021 ves_icall_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2024 MonoReflectionType *rt;
2025 MonoDomain *domain = mono_object_domain (property);
2026 const MonoProperty *pproperty = property->property;
2028 if ((req_info & PInfo_ReflectedType) != 0) {
2029 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2030 mono_error_raise_exception (&error);
2032 MONO_STRUCT_SETREF (info, parent, rt);
2034 if ((req_info & PInfo_DeclaringType) != 0) {
2035 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2036 mono_error_raise_exception (&error);
2038 MONO_STRUCT_SETREF (info, declaring_type, rt);
2041 if ((req_info & PInfo_Name) != 0)
2042 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2044 if ((req_info & PInfo_Attributes) != 0)
2045 info->attrs = pproperty->attrs;
2047 if ((req_info & PInfo_GetMethod) != 0)
2048 MONO_STRUCT_SETREF (info, get, pproperty->get &&
2049 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) || pproperty->get->klass == property->klass) ?
2050 mono_method_get_object (domain, pproperty->get, property->klass): NULL);
2051 if ((req_info & PInfo_SetMethod) != 0)
2052 MONO_STRUCT_SETREF (info, set, pproperty->set &&
2053 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) || pproperty->set->klass == property->klass) ?
2054 mono_method_get_object (domain, pproperty->set, property->klass): NULL);
2056 * There may be other methods defined for properties, though, it seems they are not exposed
2057 * in the reflection API
2062 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2065 MonoReflectionType *rt;
2066 MonoDomain *domain = mono_object_domain (event);
2068 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2069 mono_error_raise_exception (&error);
2071 MONO_STRUCT_SETREF (info, reflected_type, rt);
2073 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2074 mono_error_raise_exception (&error);
2076 MONO_STRUCT_SETREF (info, declaring_type, rt);
2078 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2079 info->attrs = event->event->attrs;
2080 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2081 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2082 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2084 #ifndef MONO_SMALL_CONFIG
2085 if (event->event->other) {
2087 while (event->event->other [n])
2089 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2091 for (i = 0; i < n; i++)
2092 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2098 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2103 mono_class_setup_interfaces (klass, error);
2104 if (!mono_error_ok (error))
2107 for (i = 0; i < klass->interface_count; i++) {
2108 ic = klass->interfaces [i];
2109 g_hash_table_insert (ifaces, ic, ic);
2111 collect_interfaces (ic, ifaces, error);
2112 if (!mono_error_ok (error))
2118 MonoArray *iface_array;
2119 MonoGenericContext *context;
2123 } FillIfaceArrayData;
2126 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2128 MonoReflectionType *rt;
2129 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2130 MonoClass *ic = (MonoClass *)key;
2131 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2133 if (!mono_error_ok (data->error))
2136 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2137 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2138 if (!mono_error_ok (data->error))
2142 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2143 if (!mono_error_ok (data->error))
2146 mono_array_setref (data->iface_array, data->next_idx++, rt);
2149 mono_metadata_free_type (inflated);
2153 get_interfaces_hash (gconstpointer v1)
2155 MonoClass *k = (MonoClass*)v1;
2157 return k->type_token;
2160 ICALL_EXPORT MonoArray*
2161 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2164 MonoClass *klass = mono_class_from_mono_type (type->type);
2166 FillIfaceArrayData data = { 0 };
2169 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2171 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2172 data.context = mono_class_get_context (klass);
2173 klass = klass->generic_class->container_class;
2176 for (parent = klass; parent; parent = parent->parent) {
2177 mono_class_setup_interfaces (parent, &error);
2178 if (!mono_error_ok (&error))
2180 collect_interfaces (parent, iface_hash, &error);
2181 if (!mono_error_ok (&error))
2185 data.error = &error;
2186 data.domain = mono_object_domain (type);
2188 len = g_hash_table_size (iface_hash);
2190 g_hash_table_destroy (iface_hash);
2191 if (!data.domain->empty_types)
2192 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2193 return data.domain->empty_types;
2196 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2197 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2198 if (!mono_error_ok (&error))
2201 g_hash_table_destroy (iface_hash);
2202 return data.iface_array;
2205 g_hash_table_destroy (iface_hash);
2206 mono_error_set_pending_exception (&error);
2211 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2213 gboolean variance_used;
2214 MonoClass *klass = mono_class_from_mono_type (type->type);
2215 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2216 MonoReflectionMethod *member;
2219 int i = 0, len, ioffset;
2222 mono_class_init_or_throw (klass);
2223 mono_class_init_or_throw (iclass);
2225 mono_class_setup_vtable (klass);
2227 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2231 len = mono_class_num_methods (iclass);
2232 domain = mono_object_domain (type);
2233 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2234 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2236 while ((method = mono_class_get_methods (iclass, &iter))) {
2237 member = mono_method_get_object (domain, method, iclass);
2238 mono_array_setref (*methods, i, member);
2239 member = mono_method_get_object (domain, klass->vtable [i + ioffset], klass);
2240 mono_array_setref (*targets, i, member);
2247 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2249 MonoClass *klass = mono_class_from_mono_type (type->type);
2250 mono_class_init_or_throw (klass);
2252 if (image_is_dynamic (klass->image)) {
2253 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2254 *packing = tb->packing_size;
2255 *size = tb->class_size;
2257 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2261 ICALL_EXPORT MonoReflectionType*
2262 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2265 MonoReflectionType *ret;
2268 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2269 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2270 mono_error_raise_exception (&error);
2275 klass = mono_class_from_mono_type (type->type);
2276 mono_class_init_or_throw (klass);
2278 // GetElementType should only return a type for:
2279 // Array Pointer PassedByRef
2280 if (type->type->byref)
2281 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2282 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2283 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2284 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2285 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2289 mono_error_raise_exception (&error);
2294 ICALL_EXPORT MonoReflectionType*
2295 ves_icall_get_type_parent (MonoReflectionType *type)
2298 MonoReflectionType *ret;
2300 if (type->type->byref)
2303 MonoClass *klass = mono_class_from_mono_type (type->type);
2307 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2308 mono_error_raise_exception (&error);
2313 ICALL_EXPORT MonoBoolean
2314 ves_icall_type_ispointer (MonoReflectionType *type)
2316 return type->type->type == MONO_TYPE_PTR;
2319 ICALL_EXPORT MonoBoolean
2320 ves_icall_type_isprimitive (MonoReflectionType *type)
2322 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)));
2325 ICALL_EXPORT MonoBoolean
2326 ves_icall_type_isbyref (MonoReflectionType *type)
2328 return type->type->byref;
2331 ICALL_EXPORT MonoBoolean
2332 ves_icall_type_iscomobject (MonoReflectionType *type)
2334 MonoClass *klass = mono_class_from_mono_type (type->type);
2335 mono_class_init_or_throw (klass);
2337 return mono_class_is_com_object (klass);
2340 ICALL_EXPORT MonoReflectionModule*
2341 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2343 MonoClass *klass = mono_class_from_mono_type (type->type);
2344 return mono_module_get_object (mono_object_domain (type), klass->image);
2347 ICALL_EXPORT MonoReflectionAssembly*
2348 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2350 MonoDomain *domain = mono_domain_get ();
2351 MonoClass *klass = mono_class_from_mono_type (type->type);
2352 return mono_assembly_get_object (domain, klass->image->assembly);
2355 ICALL_EXPORT MonoReflectionType*
2356 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2359 MonoReflectionType *ret;
2360 MonoDomain *domain = mono_domain_get ();
2363 if (type->type->byref)
2365 if (type->type->type == MONO_TYPE_VAR) {
2366 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2367 klass = param ? param->owner.klass : NULL;
2368 } else if (type->type->type == MONO_TYPE_MVAR) {
2369 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2370 klass = param ? param->owner.method->klass : NULL;
2372 klass = mono_class_from_mono_type (type->type)->nested_in;
2378 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2379 mono_error_raise_exception (&error);
2384 ICALL_EXPORT MonoString*
2385 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2387 MonoDomain *domain = mono_domain_get ();
2388 MonoClass *klass = mono_class_from_mono_type (type->type);
2390 if (type->type->byref) {
2391 char *n = g_strdup_printf ("%s&", klass->name);
2392 MonoString *res = mono_string_new (domain, n);
2398 return mono_string_new (domain, klass->name);
2402 ICALL_EXPORT MonoString*
2403 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2405 MonoDomain *domain = mono_domain_get ();
2406 MonoClass *klass = mono_class_from_mono_type (type->type);
2408 while (klass->nested_in)
2409 klass = klass->nested_in;
2411 if (klass->name_space [0] == '\0')
2414 return mono_string_new (domain, klass->name_space);
2418 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2422 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2423 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2427 klass = mono_class_from_mono_type (type->type);
2433 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2436 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2440 ICALL_EXPORT MonoArray*
2441 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2444 MonoReflectionType *rt;
2446 MonoClass *klass, *pklass;
2447 MonoDomain *domain = mono_object_domain (type);
2450 klass = mono_class_from_mono_type (type->type);
2452 if (klass->generic_container) {
2453 MonoGenericContainer *container = klass->generic_container;
2454 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2455 for (i = 0; i < container->type_argc; ++i) {
2456 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2458 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2459 mono_error_raise_exception (&error);
2461 mono_array_setref (res, i, rt);
2463 } else if (klass->generic_class) {
2464 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2465 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2466 for (i = 0; i < inst->type_argc; ++i) {
2467 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2468 mono_error_raise_exception (&error);
2470 mono_array_setref (res, i, rt);
2478 ICALL_EXPORT gboolean
2479 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2483 if (!IS_MONOTYPE (type))
2486 if (type->type->byref)
2489 klass = mono_class_from_mono_type (type->type);
2490 return klass->generic_container != NULL;
2493 ICALL_EXPORT MonoReflectionType*
2494 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2497 MonoReflectionType *ret;
2500 if (type->type->byref)
2503 klass = mono_class_from_mono_type (type->type);
2505 if (klass->generic_container) {
2506 return type; /* check this one */
2508 if (klass->generic_class) {
2509 MonoClass *generic_class = klass->generic_class->container_class;
2512 tb = mono_class_get_ref_info (generic_class);
2514 if (generic_class->wastypebuilder && tb)
2515 return (MonoReflectionType *)tb;
2517 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2518 mono_error_raise_exception (&error);
2526 ICALL_EXPORT MonoReflectionType*
2527 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2530 MonoReflectionType *ret;
2532 MonoType *geninst, **types;
2535 g_assert (IS_MONOTYPE (type));
2536 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2538 count = mono_array_length (type_array);
2539 types = g_new0 (MonoType *, count);
2541 for (i = 0; i < count; i++) {
2542 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2543 types [i] = t->type;
2546 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2551 klass = mono_class_from_mono_type (geninst);
2553 /*we might inflate to the GTD*/
2554 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2555 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2559 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2560 mono_error_raise_exception (&error);
2565 ICALL_EXPORT gboolean
2566 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2570 if (!IS_MONOTYPE (type))
2573 if (type->type->byref)
2576 klass = mono_class_from_mono_type (type->type);
2577 return klass->generic_class != NULL || klass->generic_container != NULL;
2581 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2583 if (!IS_MONOTYPE (type))
2586 if (is_generic_parameter (type->type))
2587 return mono_type_get_generic_param_num (type->type);
2591 ICALL_EXPORT GenericParameterAttributes
2592 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2594 g_assert (IS_MONOTYPE (type));
2595 g_assert (is_generic_parameter (type->type));
2596 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2599 ICALL_EXPORT MonoArray *
2600 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2603 MonoReflectionType *rt;
2604 MonoGenericParamInfo *param_info;
2610 g_assert (IS_MONOTYPE (type));
2612 domain = mono_object_domain (type);
2613 param_info = mono_generic_param_info (type->type->data.generic_param);
2614 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2617 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2618 for (i = 0; i < count; i++) {
2619 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2620 mono_error_raise_exception (&error);
2622 mono_array_setref (res, i, rt);
2629 ICALL_EXPORT MonoBoolean
2630 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2632 return is_generic_parameter (type->type);
2635 ICALL_EXPORT MonoBoolean
2636 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2638 return is_generic_parameter (tb->type.type);
2642 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2643 MonoReflectionType *t)
2645 enumtype->type = t->type;
2648 ICALL_EXPORT MonoReflectionMethod*
2649 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2650 MonoReflectionMethod* generic)
2657 domain = ((MonoObject *)type)->vtable->domain;
2659 klass = mono_class_from_mono_type (type->type);
2660 mono_class_init_or_throw (klass);
2663 while ((method = mono_class_get_methods (klass, &iter))) {
2664 if (method->token == generic->method->token)
2665 return mono_method_get_object (domain, method, klass);
2671 ICALL_EXPORT MonoReflectionMethod *
2672 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2675 MonoType *type = ref_type->type;
2677 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2678 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2681 if (type->type == MONO_TYPE_VAR)
2684 method = mono_type_get_generic_param_owner (type)->owner.method;
2686 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2689 ICALL_EXPORT MonoBoolean
2690 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2692 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2696 ICALL_EXPORT MonoBoolean
2697 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2699 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2704 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2706 MonoDomain *domain = mono_domain_get ();
2707 MonoImage *image = method->method->klass->image;
2708 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2709 MonoTableInfo *tables = image->tables;
2710 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2711 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2712 guint32 im_cols [MONO_IMPLMAP_SIZE];
2713 guint32 scope_token;
2714 const char *import = NULL;
2715 const char *scope = NULL;
2717 if (image_is_dynamic (image)) {
2718 MonoReflectionMethodAux *method_aux =
2719 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2721 import = method_aux->dllentry;
2722 scope = method_aux->dll;
2725 if (!import || !scope) {
2726 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2731 if (piinfo->implmap_idx) {
2732 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2734 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2735 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2736 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2737 scope = mono_metadata_string_heap (image, scope_token);
2741 *flags = piinfo->piflags;
2742 *entry_point = mono_string_new (domain, import);
2743 *dll_name = mono_string_new (domain, scope);
2746 ICALL_EXPORT MonoReflectionMethod *
2747 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2749 MonoMethodInflated *imethod;
2752 if (method->method->is_generic)
2755 if (!method->method->is_inflated)
2758 imethod = (MonoMethodInflated *) method->method;
2760 result = imethod->declaring;
2761 /* Not a generic method. */
2762 if (!result->is_generic)
2765 if (image_is_dynamic (method->method->klass->image)) {
2766 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2767 MonoReflectionMethod *res;
2770 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2771 * the dynamic case as well ?
2773 mono_image_lock ((MonoImage*)image);
2774 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2775 mono_image_unlock ((MonoImage*)image);
2781 if (imethod->context.class_inst) {
2782 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2783 /*Generic methods gets the context of the GTD.*/
2784 if (mono_class_get_context (klass)) {
2786 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2787 if (!mono_error_ok (&error)) {
2788 mono_error_set_pending_exception (&error);
2794 return mono_method_get_object (mono_object_domain (method), result, NULL);
2797 ICALL_EXPORT gboolean
2798 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2800 return mono_method_signature (method->method)->generic_param_count != 0;
2803 ICALL_EXPORT gboolean
2804 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2806 return method->method->is_generic;
2809 ICALL_EXPORT MonoArray*
2810 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2813 MonoReflectionType *rt;
2818 domain = mono_object_domain (method);
2820 if (method->method->is_inflated) {
2821 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2824 count = inst->type_argc;
2825 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2827 for (i = 0; i < count; i++) {
2828 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2829 mono_error_raise_exception (&error);
2831 mono_array_setref (res, i, rt);
2838 count = mono_method_signature (method->method)->generic_param_count;
2839 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2841 for (i = 0; i < count; i++) {
2842 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2843 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2844 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
2846 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2847 mono_error_raise_exception (&error);
2849 mono_array_setref (res, i, rt);
2855 ICALL_EXPORT MonoObject *
2856 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
2860 * Invoke from reflection is supposed to always be a virtual call (the API
2861 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2862 * greater flexibility.
2864 MonoMethod *m = method->method;
2865 MonoMethodSignature *sig = mono_method_signature (m);
2868 void *obj = this_arg;
2872 if (mono_security_core_clr_enabled ())
2873 mono_security_core_clr_ensure_reflection_access_method (m);
2875 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2876 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2877 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2882 if (!mono_object_isinst (this_arg, m->klass)) {
2883 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
2884 char *target_name = mono_type_get_full_name (m->klass);
2885 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2886 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2888 g_free (target_name);
2892 m = mono_object_get_virtual_method (this_arg, m);
2893 /* must pass the pointer to the value for valuetype methods */
2894 if (m->klass->valuetype)
2895 obj = mono_object_unbox (this_arg);
2896 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2897 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2902 if (sig->ret->byref) {
2903 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"));
2907 pcount = params? mono_array_length (params): 0;
2908 if (pcount != sig->param_count) {
2909 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2913 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
2914 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."));
2918 image = m->klass->image;
2919 if (image->assembly->ref_only) {
2920 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."));
2924 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
2925 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2929 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2933 intptr_t *lower_bounds;
2934 pcount = mono_array_length (params);
2935 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
2936 /* Note: the synthetized array .ctors have int32 as argument type */
2937 for (i = 0; i < pcount; ++i)
2938 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2940 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
2941 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
2942 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
2943 if (!mono_error_ok (&error)) {
2944 mono_error_set_pending_exception (&error);
2948 for (i = 0; i < mono_array_length (arr); ++i) {
2949 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
2950 if (!mono_error_ok (&error)) {
2951 mono_error_set_pending_exception (&error);
2954 mono_array_setref_fast (arr, i, subarray);
2956 return (MonoObject*)arr;
2959 if (m->klass->rank == pcount) {
2960 /* Only lengths provided. */
2961 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
2962 if (!mono_error_ok (&error)) {
2963 mono_error_set_pending_exception (&error);
2967 return (MonoObject*)arr;
2969 g_assert (pcount == (m->klass->rank * 2));
2970 /* The arguments are lower-bound-length pairs */
2971 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
2973 for (i = 0; i < pcount / 2; ++i) {
2974 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
2975 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
2978 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
2979 if (!mono_error_ok (&error)) {
2980 mono_error_set_pending_exception (&error);
2984 return (MonoObject*)arr;
2987 return mono_runtime_invoke_array (m, obj, params, NULL);
2990 #ifndef DISABLE_REMOTING
2991 ICALL_EXPORT MonoObject *
2992 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
2994 MonoDomain *domain = mono_object_domain (method);
2995 MonoMethod *m = method->method;
2996 MonoMethodSignature *sig = mono_method_signature (m);
2997 MonoArray *out_args;
2999 int i, j, outarg_count = 0;
3001 if (m->klass == mono_defaults.object_class) {
3002 if (!strcmp (m->name, "FieldGetter")) {
3003 MonoClass *k = this_arg->vtable->klass;
3007 /* If this is a proxy, then it must be a CBO */
3008 if (k == mono_defaults.transparent_proxy_class) {
3009 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3010 this_arg = tp->rp->unwrapped_server;
3011 g_assert (this_arg);
3012 k = this_arg->vtable->klass;
3015 name = mono_array_get (params, MonoString *, 1);
3016 str = mono_string_to_utf8 (name);
3019 MonoClassField* field = mono_class_get_field_from_name (k, str);
3021 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3022 if (field_klass->valuetype)
3023 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
3025 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3027 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3028 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3029 mono_array_setref (out_args, 0, result);
3037 g_assert_not_reached ();
3039 } else if (!strcmp (m->name, "FieldSetter")) {
3040 MonoClass *k = this_arg->vtable->klass;
3046 /* If this is a proxy, then it must be a CBO */
3047 if (k == mono_defaults.transparent_proxy_class) {
3048 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3049 this_arg = tp->rp->unwrapped_server;
3050 g_assert (this_arg);
3051 k = this_arg->vtable->klass;
3054 name = mono_array_get (params, MonoString *, 1);
3055 str = mono_string_to_utf8 (name);
3058 MonoClassField* field = mono_class_get_field_from_name (k, str);
3060 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3061 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3063 if (field_klass->valuetype) {
3064 size = mono_type_size (field->type, &align);
3065 g_assert (size == mono_class_value_size (field_klass, NULL));
3066 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3068 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3071 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3072 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3082 g_assert_not_reached ();
3087 for (i = 0; i < mono_array_length (params); i++) {
3088 if (sig->params [i]->byref)
3092 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3094 /* handle constructors only for objects already allocated */
3095 if (!strcmp (method->method->name, ".ctor"))
3096 g_assert (this_arg);
3098 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3099 g_assert (!method->method->klass->valuetype);
3100 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3102 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3103 if (sig->params [i]->byref) {
3105 arg = mono_array_get (params, gpointer, i);
3106 mono_array_setref (out_args, j, arg);
3111 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3118 read_enum_value (const char *mem, int type)
3121 case MONO_TYPE_BOOLEAN:
3123 return *(guint8*)mem;
3125 return *(gint8*)mem;
3126 case MONO_TYPE_CHAR:
3128 return read16 (mem);
3130 return (gint16) read16 (mem);
3132 return read32 (mem);
3134 return (gint32) read32 (mem);
3137 return read64 (mem);
3139 g_assert_not_reached ();
3145 write_enum_value (char *mem, int type, guint64 value)
3149 case MONO_TYPE_I1: {
3150 guint8 *p = (guint8*)mem;
3155 case MONO_TYPE_I2: {
3156 guint16 *p = (guint16 *)mem;
3161 case MONO_TYPE_I4: {
3162 guint32 *p = (guint32 *)mem;
3167 case MONO_TYPE_I8: {
3168 guint64 *p = (guint64 *)mem;
3173 g_assert_not_reached ();
3178 ICALL_EXPORT MonoObject *
3179 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3186 domain = mono_object_domain (enumType);
3187 enumc = mono_class_from_mono_type (enumType->type);
3189 mono_class_init_or_throw (enumc);
3191 etype = mono_class_enum_basetype (enumc);
3193 res = mono_object_new (domain, enumc);
3194 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3199 ICALL_EXPORT MonoBoolean
3200 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3202 int size = mono_class_value_size (a->vtable->klass, NULL);
3203 guint64 a_val = 0, b_val = 0;
3205 memcpy (&a_val, mono_object_unbox (a), size);
3206 memcpy (&b_val, mono_object_unbox (b), size);
3208 return (a_val & b_val) == b_val;
3211 ICALL_EXPORT MonoObject *
3212 ves_icall_System_Enum_get_value (MonoObject *eobj)
3223 g_assert (eobj->vtable->klass->enumtype);
3225 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3226 res = mono_object_new (mono_object_domain (eobj), enumc);
3227 dst = (char *)res + sizeof (MonoObject);
3228 src = (char *)eobj + sizeof (MonoObject);
3229 size = mono_class_value_size (enumc, NULL);
3231 memcpy (dst, src, size);
3236 ICALL_EXPORT MonoReflectionType *
3237 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3240 MonoReflectionType *ret;
3244 klass = mono_class_from_mono_type (type->type);
3245 mono_class_init_or_throw (klass);
3247 etype = mono_class_enum_basetype (klass);
3249 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3253 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3254 mono_error_raise_exception (&error);
3260 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3262 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3263 gpointer odata = (char *)other + sizeof (MonoObject);
3264 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3265 g_assert (basetype);
3270 if (eobj->vtable->klass != other->vtable->klass)
3273 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3274 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3275 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3278 return me > other ? 1 : -1; \
3281 switch (basetype->type) {
3283 COMPARE_ENUM_VALUES (guint8);
3285 COMPARE_ENUM_VALUES (gint8);
3286 case MONO_TYPE_CHAR:
3288 COMPARE_ENUM_VALUES (guint16);
3290 COMPARE_ENUM_VALUES (gint16);
3292 COMPARE_ENUM_VALUES (guint32);
3294 COMPARE_ENUM_VALUES (gint32);
3296 COMPARE_ENUM_VALUES (guint64);
3298 COMPARE_ENUM_VALUES (gint64);
3302 #undef COMPARE_ENUM_VALUES
3303 /* indicates that the enum was of an unsupported unerlying type */
3308 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3310 gpointer data = (char *)eobj + sizeof (MonoObject);
3311 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3312 g_assert (basetype);
3314 switch (basetype->type) {
3315 case MONO_TYPE_I1: {
3316 gint8 value = *((gint8*)data);
3317 return ((int)value ^ (int)value << 8);
3320 return *((guint8*)data);
3321 case MONO_TYPE_CHAR:
3323 return *((guint16*)data);
3325 case MONO_TYPE_I2: {
3326 gint16 value = *((gint16*)data);
3327 return ((int)(guint16)value | (((int)value) << 16));
3330 return *((guint32*)data);
3332 return *((gint32*)data);
3334 case MONO_TYPE_I8: {
3335 gint64 value = *((gint64*)data);
3336 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3339 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3344 ICALL_EXPORT MonoBoolean
3345 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3347 MonoDomain *domain = mono_object_domain (type);
3348 MonoClass *enumc = mono_class_from_mono_type (type->type);
3349 guint j = 0, nvalues;
3351 MonoClassField *field;
3353 guint64 field_value, previous_value = 0;
3354 gboolean sorted = TRUE;
3356 mono_class_init_or_throw (enumc);
3358 if (!enumc->enumtype) {
3359 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3363 base_type = mono_class_enum_basetype (enumc)->type;
3365 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3366 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3367 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3370 while ((field = mono_class_get_fields (enumc, &iter))) {
3372 MonoTypeEnum def_type;
3374 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3376 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3378 if (mono_field_is_deleted (field))
3380 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3382 p = mono_class_get_field_default_value (field, &def_type);
3383 /* len = */ mono_metadata_decode_blob_size (p, &p);
3385 field_value = read_enum_value (p, base_type);
3386 mono_array_set (*values, guint64, j, field_value);
3388 if (previous_value > field_value)
3391 previous_value = field_value;
3399 BFLAGS_IgnoreCase = 1,
3400 BFLAGS_DeclaredOnly = 2,
3401 BFLAGS_Instance = 4,
3403 BFLAGS_Public = 0x10,
3404 BFLAGS_NonPublic = 0x20,
3405 BFLAGS_FlattenHierarchy = 0x40,
3406 BFLAGS_InvokeMethod = 0x100,
3407 BFLAGS_CreateInstance = 0x200,
3408 BFLAGS_GetField = 0x400,
3409 BFLAGS_SetField = 0x800,
3410 BFLAGS_GetProperty = 0x1000,
3411 BFLAGS_SetProperty = 0x2000,
3412 BFLAGS_ExactBinding = 0x10000,
3413 BFLAGS_SuppressChangeType = 0x20000,
3414 BFLAGS_OptionalParamBinding = 0x40000
3417 ICALL_EXPORT MonoArray*
3418 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3422 MonoClass *startklass, *klass, *refklass;
3427 char *utf8_name = NULL;
3428 int (*compare_func) (const char *s1, const char *s2) = NULL;
3429 MonoClassField *field;
3430 MonoPtrArray tmp_array;
3432 domain = ((MonoObject *)type)->vtable->domain;
3433 if (type->type->byref)
3434 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3436 klass = startklass = mono_class_from_mono_type (type->type);
3437 refklass = mono_class_from_mono_type (reftype->type);
3439 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3442 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3443 mono_ptr_array_destroy (tmp_array);
3444 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3449 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3450 guint32 flags = mono_field_get_flags (field);
3452 if (mono_field_is_deleted_with_flags (field, flags))
3454 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3455 if (bflags & BFLAGS_Public)
3457 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3458 if (bflags & BFLAGS_NonPublic) {
3465 if (flags & FIELD_ATTRIBUTE_STATIC) {
3466 if (bflags & BFLAGS_Static)
3467 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3470 if (bflags & BFLAGS_Instance)
3478 if (utf8_name == NULL) {
3479 utf8_name = mono_string_to_utf8 (name);
3480 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3483 if (compare_func (mono_field_get_name (field), utf8_name))
3487 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3488 if (!mono_error_ok (&error))
3490 mono_ptr_array_append (tmp_array, member);
3492 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3495 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3497 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3498 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3500 mono_ptr_array_destroy (tmp_array);
3502 if (utf8_name != NULL)
3507 mono_ptr_array_destroy (tmp_array);
3508 mono_error_raise_exception (&error);
3509 g_assert_not_reached ();
3513 method_nonpublic (MonoMethod* method, gboolean start_klass)
3515 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3516 case METHOD_ATTRIBUTE_ASSEM:
3517 return (start_klass || mono_defaults.generic_ilist_class);
3518 case METHOD_ATTRIBUTE_PRIVATE:
3520 case METHOD_ATTRIBUTE_PUBLIC:
3528 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3531 MonoClass *startklass;
3535 /*FIXME, use MonoBitSet*/
3536 guint32 method_slots_default [8];
3537 guint32 *method_slots = NULL;
3538 int (*compare_func) (const char *s1, const char *s2) = NULL;
3540 array = g_ptr_array_new ();
3545 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3547 /* An optimization for calls made from Delegate:CreateDelegate () */
3548 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3549 method = mono_get_delegate_invoke (klass);
3550 if (mono_loader_get_last_error ())
3553 g_ptr_array_add (array, method);
3557 mono_class_setup_methods (klass);
3558 mono_class_setup_vtable (klass);
3559 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3562 if (is_generic_parameter (&klass->byval_arg))
3563 nslots = mono_class_get_vtable_size (klass->parent);
3565 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3566 if (nslots >= sizeof (method_slots_default) * 8) {
3567 method_slots = g_new0 (guint32, nslots / 32 + 1);
3569 method_slots = method_slots_default;
3570 memset (method_slots, 0, sizeof (method_slots_default));
3573 mono_class_setup_methods (klass);
3574 mono_class_setup_vtable (klass);
3575 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3579 while ((method = mono_class_get_methods (klass, &iter))) {
3581 if (method->slot != -1) {
3582 g_assert (method->slot < nslots);
3583 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3585 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3586 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3589 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3591 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3592 if (bflags & BFLAGS_Public)
3594 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3600 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3601 if (bflags & BFLAGS_Static)
3602 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3605 if (bflags & BFLAGS_Instance)
3613 if (compare_func (name, method->name))
3618 g_ptr_array_add (array, method);
3620 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3622 if (method_slots != method_slots_default)
3623 g_free (method_slots);
3628 if (method_slots != method_slots_default)
3629 g_free (method_slots);
3630 g_ptr_array_free (array, TRUE);
3632 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3633 *ex = mono_class_get_exception_for_failure (klass);
3635 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3636 mono_loader_clear_error ();
3641 ICALL_EXPORT MonoArray*
3642 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3644 static MonoClass *MethodInfo_array;
3648 MonoVTable *array_vtable;
3649 MonoException *ex = NULL;
3650 const char *mname = NULL;
3651 GPtrArray *method_array;
3652 MonoClass *klass, *refklass;
3655 if (!MethodInfo_array) {
3656 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3657 mono_memory_barrier ();
3658 MethodInfo_array = klass;
3661 klass = mono_class_from_mono_type (type->type);
3662 refklass = mono_class_from_mono_type (reftype->type);
3663 domain = ((MonoObject *)type)->vtable->domain;
3664 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3665 if (type->type->byref) {
3666 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3667 mono_error_set_pending_exception (&error);
3673 mname = mono_string_to_utf8 (name);
3675 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3676 g_free ((char*)mname);
3678 mono_set_pending_exception (ex);
3682 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3683 if (!mono_error_ok (&error)) {
3684 mono_error_set_pending_exception (&error);
3688 for (i = 0; i < method_array->len; ++i) {
3689 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3690 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3693 g_ptr_array_free (method_array, TRUE);
3697 ICALL_EXPORT MonoArray*
3698 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3701 static MonoClass *System_Reflection_ConstructorInfo;
3702 MonoClass *startklass, *klass, *refklass;
3707 gpointer iter = NULL;
3708 MonoPtrArray tmp_array;
3710 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3712 domain = ((MonoObject *)type)->vtable->domain;
3713 if (type->type->byref)
3714 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3715 klass = startklass = mono_class_from_mono_type (type->type);
3716 refklass = mono_class_from_mono_type (reftype->type);
3718 if (!System_Reflection_ConstructorInfo)
3719 System_Reflection_ConstructorInfo = mono_class_from_name (
3720 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3722 mono_class_setup_methods (klass);
3723 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3724 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3729 while ((method = mono_class_get_methods (klass, &iter))) {
3731 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3733 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3734 if (bflags & BFLAGS_Public)
3737 if (bflags & BFLAGS_NonPublic)
3743 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3744 if (bflags & BFLAGS_Static)
3745 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3748 if (bflags & BFLAGS_Instance)
3754 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3756 mono_ptr_array_append (tmp_array, member);
3759 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3761 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3762 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3764 mono_ptr_array_destroy (tmp_array);
3770 property_hash (gconstpointer data)
3772 MonoProperty *prop = (MonoProperty*)data;
3774 return g_str_hash (prop->name);
3778 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3780 if (method1->is_inflated)
3781 method1 = ((MonoMethodInflated*) method1)->declaring;
3782 if (method2->is_inflated)
3783 method2 = ((MonoMethodInflated*) method2)->declaring;
3785 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3789 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3791 // Properties are hide-by-name-and-signature
3792 if (!g_str_equal (prop1->name, prop2->name))
3795 /* If we see a property in a generic method, we want to
3796 compare the generic signatures, not the inflated signatures
3797 because we might conflate two properties that were
3801 public T this[T t] { getter { return t; } } // method 1
3802 public U this[U u] { getter { return u; } } // method 2
3805 If we see int Foo<int,int>::Item[int] we need to know if
3806 the indexer came from method 1 or from method 2, and we
3807 shouldn't conflate them. (Bugzilla 36283)
3809 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
3812 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
3819 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3824 return method_nonpublic (accessor, start_klass);
3827 ICALL_EXPORT MonoArray*
3828 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3832 static MonoClass *System_Reflection_PropertyInfo;
3833 MonoClass *startklass, *klass;
3839 gchar *propname = NULL;
3840 int (*compare_func) (const char *s1, const char *s2) = NULL;
3842 GHashTable *properties = NULL;
3843 MonoPtrArray tmp_array;
3845 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
3847 if (!System_Reflection_PropertyInfo)
3848 System_Reflection_PropertyInfo = mono_class_from_name (
3849 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3851 domain = ((MonoObject *)type)->vtable->domain;
3852 if (type->type->byref)
3853 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3854 klass = startklass = mono_class_from_mono_type (type->type);
3857 propname = mono_string_to_utf8 (name);
3858 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3861 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3863 mono_class_setup_methods (klass);
3864 mono_class_setup_vtable (klass);
3865 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3869 while ((prop = mono_class_get_properties (klass, &iter))) {
3875 flags = method->flags;
3878 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3879 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3880 if (bflags & BFLAGS_Public)
3882 } else if (bflags & BFLAGS_NonPublic) {
3883 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3884 property_accessor_nonpublic(prop->set, startklass == klass)) {
3891 if (flags & METHOD_ATTRIBUTE_STATIC) {
3892 if (bflags & BFLAGS_Static)
3893 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3896 if (bflags & BFLAGS_Instance)
3905 if (compare_func (propname, prop->name))
3909 if (g_hash_table_lookup (properties, prop))
3912 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3914 g_hash_table_insert (properties, prop, prop);
3916 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3919 g_hash_table_destroy (properties);
3922 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3923 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3924 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3926 mono_ptr_array_destroy (tmp_array);
3932 g_hash_table_destroy (properties);
3935 mono_ptr_array_destroy (tmp_array);
3937 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3938 ex = mono_class_get_exception_for_failure (klass);
3940 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3941 mono_loader_clear_error ();
3943 mono_set_pending_exception (ex);
3948 event_hash (gconstpointer data)
3950 MonoEvent *event = (MonoEvent*)data;
3952 return g_str_hash (event->name);
3956 event_equal (MonoEvent *event1, MonoEvent *event2)
3958 // Events are hide-by-name
3959 return g_str_equal (event1->name, event2->name);
3962 ICALL_EXPORT MonoArray*
3963 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3967 static MonoClass *System_Reflection_EventInfo;
3968 MonoClass *startklass, *klass;
3974 char *utf8_name = NULL;
3975 int (*compare_func) (const char *s1, const char *s2) = NULL;
3976 GHashTable *events = NULL;
3977 MonoPtrArray tmp_array;
3979 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
3981 if (!System_Reflection_EventInfo)
3982 System_Reflection_EventInfo = mono_class_from_name (
3983 mono_defaults.corlib, "System.Reflection", "EventInfo");
3985 domain = mono_object_domain (type);
3986 if (type->type->byref)
3987 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3988 klass = startklass = mono_class_from_mono_type (type->type);
3990 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
3992 mono_class_setup_methods (klass);
3993 mono_class_setup_vtable (klass);
3994 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3998 while ((event = mono_class_get_events (klass, &iter))) {
4000 method = event->add;
4002 method = event->remove;
4004 method = event->raise;
4006 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4007 if (bflags & BFLAGS_Public)
4009 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4010 if (bflags & BFLAGS_NonPublic)
4015 if (bflags & BFLAGS_NonPublic)
4021 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4022 if (bflags & BFLAGS_Static)
4023 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4026 if (bflags & BFLAGS_Instance)
4031 if (bflags & BFLAGS_Instance)
4037 if (utf8_name == NULL) {
4038 utf8_name = mono_string_to_utf8 (name);
4039 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4042 if (compare_func (event->name, utf8_name))
4046 if (g_hash_table_lookup (events, event))
4049 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
4051 g_hash_table_insert (events, event, event);
4053 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4056 g_hash_table_destroy (events);
4058 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
4060 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4061 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4063 mono_ptr_array_destroy (tmp_array);
4065 if (utf8_name != NULL)
4071 mono_ptr_array_destroy (tmp_array);
4072 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4073 ex = mono_class_get_exception_for_failure (klass);
4075 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4076 mono_loader_clear_error ();
4078 mono_set_pending_exception (ex);
4082 ICALL_EXPORT MonoArray*
4083 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4086 MonoReflectionType *rt;
4094 MonoPtrArray tmp_array;
4096 domain = ((MonoObject *)type)->vtable->domain;
4097 if (type->type->byref)
4098 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4099 klass = mono_class_from_mono_type (type->type);
4102 * If a nested type is generic, return its generic type definition.
4103 * Note that this means that the return value is essentially the set
4104 * of nested types of the generic type definition of @klass.
4106 * A note in MSDN claims that a generic type definition can have
4107 * nested types that aren't generic. In any case, the container of that
4108 * nested type would be the generic type definition.
4110 if (klass->generic_class)
4111 klass = klass->generic_class->container_class;
4113 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4115 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4117 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4118 if (bflags & BFLAGS_Public)
4121 if (bflags & BFLAGS_NonPublic)
4129 str = mono_string_to_utf8 (name);
4130 mono_identifier_unescape_type_name_chars (str);
4133 if (strcmp (nested->name, str))
4137 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4138 mono_error_raise_exception (&error);
4140 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4143 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4145 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4146 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4148 mono_ptr_array_destroy (tmp_array);
4156 ICALL_EXPORT MonoReflectionType*
4157 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4160 MonoReflectionType *ret;
4162 MonoType *type = NULL;
4163 MonoTypeNameParse info;
4164 gboolean type_resolve;
4166 /* On MS.NET, this does not fire a TypeResolve event */
4167 type_resolve = TRUE;
4168 str = mono_string_to_utf8 (name);
4169 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4170 if (!mono_reflection_parse_type (str, &info)) {
4172 mono_reflection_free_type_info (&info);
4174 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4177 /*g_print ("failed parse\n");*/
4181 if (info.assembly.name) {
4183 mono_reflection_free_type_info (&info);
4185 /* 1.0 and 2.0 throw different exceptions */
4186 if (mono_defaults.generic_ilist_class)
4187 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4189 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4195 if (module != NULL) {
4197 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4202 if (assembly_is_dynamic (assembly->assembly)) {
4203 /* Enumerate all modules */
4204 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4208 if (abuilder->modules) {
4209 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4210 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4211 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4217 if (!type && abuilder->loaded_modules) {
4218 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4219 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4220 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4227 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4229 mono_reflection_free_type_info (&info);
4231 MonoException *e = NULL;
4234 e = mono_get_exception_type_load (name, NULL);
4236 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4237 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4239 mono_loader_clear_error ();
4242 mono_set_pending_exception (e);
4244 } else if (mono_loader_get_last_error ()) {
4246 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4249 mono_loader_clear_error ();
4252 if (type->type == MONO_TYPE_CLASS) {
4253 MonoClass *klass = mono_type_get_class (type);
4255 /* need to report exceptions ? */
4256 if (throwOnError && klass->exception_type) {
4257 /* report SecurityException (or others) that occured when loading the assembly */
4258 MonoException *exc = mono_class_get_exception_for_failure (klass);
4259 mono_loader_clear_error ();
4260 mono_set_pending_exception (exc);
4265 /* g_print ("got it\n"); */
4266 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4267 mono_error_raise_exception (&error);
4273 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4276 gchar *shadow_ini_file;
4279 /* Check for shadow-copied assembly */
4280 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4281 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4283 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4284 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4290 g_free (shadow_ini_file);
4291 if (content != NULL) {
4294 *filename = content;
4301 ICALL_EXPORT MonoString *
4302 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4304 MonoDomain *domain = mono_object_domain (assembly);
4305 MonoAssembly *mass = assembly->assembly;
4306 MonoString *res = NULL;
4311 if (g_path_is_absolute (mass->image->name)) {
4312 absolute = g_strdup (mass->image->name);
4313 dirname = g_path_get_dirname (absolute);
4315 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4316 dirname = g_strdup (mass->basedir);
4319 replace_shadow_path (domain, dirname, &absolute);
4324 for (i = strlen (absolute) - 1; i >= 0; i--)
4325 if (absolute [i] == '\\')
4330 uri = g_filename_to_uri (absolute, NULL, NULL);
4332 const char *prepend = "file://";
4334 if (*absolute == '/' && *(absolute + 1) == '/') {
4337 prepend = "file:///";
4340 uri = g_strconcat (prepend, absolute, NULL);
4344 res = mono_string_new (domain, uri);
4351 ICALL_EXPORT MonoBoolean
4352 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4354 MonoAssembly *mass = assembly->assembly;
4356 return mass->in_gac;
4359 ICALL_EXPORT MonoReflectionAssembly*
4360 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4364 MonoImageOpenStatus status;
4366 name = mono_string_to_utf8 (mname);
4367 res = mono_assembly_load_with_partial_name (name, &status);
4373 return mono_assembly_get_object (mono_domain_get (), res);
4376 ICALL_EXPORT MonoString *
4377 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4379 MonoDomain *domain = mono_object_domain (assembly);
4382 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4387 ICALL_EXPORT MonoBoolean
4388 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4390 return assembly->assembly->ref_only;
4393 ICALL_EXPORT MonoString *
4394 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4396 MonoDomain *domain = mono_object_domain (assembly);
4398 return mono_string_new (domain, assembly->assembly->image->version);
4401 ICALL_EXPORT MonoReflectionMethod*
4402 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4406 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4410 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4411 if (!mono_error_ok (&error)) {
4412 mono_error_set_pending_exception (&error);
4416 return mono_method_get_object (mono_object_domain (assembly), method, NULL);
4419 ICALL_EXPORT MonoReflectionModule*
4420 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4422 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4425 ICALL_EXPORT MonoArray*
4426 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4428 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4429 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4433 for (i = 0; i < table->rows; ++i) {
4434 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4435 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4441 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4443 static MonoClass *System_Version = NULL;
4444 static MonoMethod *create_version = NULL;
4448 if (!System_Version) {
4449 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4450 g_assert (System_Version);
4453 if (!create_version) {
4454 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4455 create_version = mono_method_desc_search_in_class (desc, System_Version);
4456 g_assert (create_version);
4457 mono_method_desc_free (desc);
4463 args [3] = &revision;
4464 result = mono_object_new (domain, System_Version);
4465 mono_runtime_invoke (create_version, result, args, NULL);
4470 ICALL_EXPORT MonoArray*
4471 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4473 static MonoClass *System_Reflection_AssemblyName;
4475 MonoDomain *domain = mono_object_domain (assembly);
4477 static MonoMethod *create_culture = NULL;
4478 MonoImage *image = assembly->assembly->image;
4481 if (!System_Reflection_AssemblyName)
4482 System_Reflection_AssemblyName = mono_class_from_name (
4483 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4485 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4488 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4490 if (count > 0 && !create_culture) {
4491 MonoMethodDesc *desc = mono_method_desc_new (
4492 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4493 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4494 g_assert (create_culture);
4495 mono_method_desc_free (desc);
4498 for (i = 0; i < count; i++) {
4499 MonoReflectionAssemblyName *aname;
4500 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4502 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4504 aname = (MonoReflectionAssemblyName *) mono_object_new (
4505 domain, System_Reflection_AssemblyName);
4507 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4509 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4510 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4511 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4512 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4513 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4514 aname->versioncompat = 1; /* SameMachine (default) */
4515 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4516 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4518 if (create_culture) {
4520 MonoBoolean assembly_ref = 1;
4521 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4522 args [1] = &assembly_ref;
4523 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4526 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4527 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4528 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4530 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4531 /* public key token isn't copied - the class library will
4532 automatically generate it from the public key if required */
4533 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4534 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4536 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4537 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4540 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4543 /* note: this function doesn't return the codebase on purpose (i.e. it can
4544 be used under partial trust as path information isn't present). */
4546 mono_array_setref (result, i, aname);
4551 /* move this in some file in mono/util/ */
4553 g_concat_dir_and_file (const char *dir, const char *file)
4555 g_return_val_if_fail (dir != NULL, NULL);
4556 g_return_val_if_fail (file != NULL, NULL);
4559 * If the directory name doesn't have a / on the end, we need
4560 * to add one so we get a proper path to the file
4562 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4563 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4565 return g_strconcat (dir, file, NULL);
4569 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4571 char *n = mono_string_to_utf8 (name);
4572 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4574 guint32 cols [MONO_MANIFEST_SIZE];
4575 guint32 impl, file_idx;
4579 for (i = 0; i < table->rows; ++i) {
4580 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4581 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4582 if (strcmp (val, n) == 0)
4586 if (i == table->rows)
4589 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4592 * this code should only be called after obtaining the
4593 * ResourceInfo and handling the other cases.
4595 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4596 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4598 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4603 module = assembly->assembly->image;
4605 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4607 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4610 ICALL_EXPORT gboolean
4611 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4613 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4615 guint32 cols [MONO_MANIFEST_SIZE];
4616 guint32 file_cols [MONO_FILE_SIZE];
4620 n = mono_string_to_utf8 (name);
4621 for (i = 0; i < table->rows; ++i) {
4622 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4623 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4624 if (strcmp (val, n) == 0)
4628 if (i == table->rows)
4631 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4632 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4635 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4636 case MONO_IMPLEMENTATION_FILE:
4637 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4638 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4639 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4640 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4641 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4642 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4645 info->location = RESOURCE_LOCATION_EMBEDDED;
4648 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4649 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4650 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4651 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4652 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4653 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4655 mono_set_pending_exception (ex);
4658 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4660 /* Obtain info recursively */
4661 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4662 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4665 case MONO_IMPLEMENTATION_EXP_TYPE:
4666 g_assert_not_reached ();
4674 ICALL_EXPORT MonoObject*
4675 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4677 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4678 MonoArray *result = NULL;
4683 /* check hash if needed */
4685 n = mono_string_to_utf8 (name);
4686 for (i = 0; i < table->rows; ++i) {
4687 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4688 if (strcmp (val, n) == 0) {
4691 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4692 fn = mono_string_new (mono_object_domain (assembly), n);
4694 return (MonoObject*)fn;
4702 for (i = 0; i < table->rows; ++i) {
4703 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4707 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4710 for (i = 0; i < table->rows; ++i) {
4711 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4712 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4713 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4714 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4719 return (MonoObject*)result;
4722 ICALL_EXPORT MonoArray*
4723 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4725 MonoDomain *domain = mono_domain_get();
4728 int i, j, file_count = 0;
4729 MonoImage **modules;
4730 guint32 module_count, real_module_count;
4731 MonoTableInfo *table;
4732 guint32 cols [MONO_FILE_SIZE];
4733 MonoImage *image = assembly->assembly->image;
4735 g_assert (image != NULL);
4736 g_assert (!assembly_is_dynamic (assembly->assembly));
4738 table = &image->tables [MONO_TABLE_FILE];
4739 file_count = table->rows;
4741 modules = image->modules;
4742 module_count = image->module_count;
4744 real_module_count = 0;
4745 for (i = 0; i < module_count; ++i)
4747 real_module_count ++;
4749 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4750 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4752 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4754 for (i = 0; i < module_count; ++i)
4756 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4760 for (i = 0; i < file_count; ++i, ++j) {
4761 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4762 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4763 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4765 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4767 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4768 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
4771 mono_array_setref (res, j, mono_module_get_object (domain, m));
4778 ICALL_EXPORT MonoReflectionMethod*
4779 ves_icall_GetCurrentMethod (void)
4781 MonoMethod *m = mono_method_get_last_managed ();
4784 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
4788 while (m->is_inflated)
4789 m = ((MonoMethodInflated*)m)->declaring;
4791 return mono_method_get_object (mono_domain_get (), m, NULL);
4796 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4799 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4802 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4803 //method is inflated, we should inflate it on the other class
4804 MonoGenericContext ctx;
4805 ctx.method_inst = inflated->context.method_inst;
4806 ctx.class_inst = inflated->context.class_inst;
4807 if (klass->generic_class)
4808 ctx.class_inst = klass->generic_class->context.class_inst;
4809 else if (klass->generic_container)
4810 ctx.class_inst = klass->generic_container->context.class_inst;
4811 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
4812 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4816 mono_class_setup_methods (method->klass);
4817 if (method->klass->exception_type)
4819 for (i = 0; i < method->klass->method.count; ++i) {
4820 if (method->klass->methods [i] == method) {
4825 mono_class_setup_methods (klass);
4826 if (klass->exception_type)
4828 g_assert (offset >= 0 && offset < klass->method.count);
4829 return klass->methods [offset];
4832 ICALL_EXPORT MonoReflectionMethod*
4833 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4837 klass = mono_class_from_mono_type (type);
4838 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4840 if (method->klass != klass) {
4841 method = mono_method_get_equivalent_method (method, klass);
4846 klass = method->klass;
4847 return mono_method_get_object (mono_domain_get (), method, klass);
4850 ICALL_EXPORT MonoReflectionMethodBody*
4851 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4853 return mono_method_body_get_object (mono_domain_get (), method);
4856 ICALL_EXPORT MonoReflectionAssembly*
4857 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4859 MonoMethod *dest = NULL;
4861 mono_stack_walk_no_il (get_executing, &dest);
4863 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4867 ICALL_EXPORT MonoReflectionAssembly*
4868 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4870 MonoDomain* domain = mono_domain_get ();
4872 if (!domain->entry_assembly)
4875 return mono_assembly_get_object (domain, domain->entry_assembly);
4878 ICALL_EXPORT MonoReflectionAssembly*
4879 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4885 mono_stack_walk_no_il (get_executing, &dest);
4887 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
4891 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
4894 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4897 ICALL_EXPORT MonoString *
4898 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4899 gboolean assembly_qualified)
4901 MonoDomain *domain = mono_object_domain (object);
4902 MonoTypeNameFormat format;
4907 format = assembly_qualified ?
4908 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4909 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4911 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4913 name = mono_type_get_name_full (object->type, format);
4917 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4922 res = mono_string_new (domain, name);
4929 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
4931 MonoClass *klass = mono_class_from_mono_type (rfield->type);
4932 mono_class_init_or_throw (klass);
4933 return mono_security_core_clr_class_level (klass);
4937 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
4939 MonoClassField *field = rfield->field;
4940 return mono_security_core_clr_field_level (field, TRUE);
4944 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
4946 MonoMethod *method = rfield->method;
4947 return mono_security_core_clr_method_level (method, TRUE);
4951 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4953 static MonoMethod *create_culture = NULL;
4956 const char *pkey_ptr;
4958 MonoBoolean assembly_ref = 0;
4960 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4961 aname->major = name->major;
4962 aname->minor = name->minor;
4963 aname->build = name->build;
4964 aname->flags = name->flags;
4965 aname->revision = name->revision;
4966 aname->hashalg = name->hash_alg;
4967 aname->versioncompat = 1; /* SameMachine (default) */
4968 aname->processor_architecture = name->arch;
4970 if (by_default_version)
4971 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4974 if (absolute != NULL && *absolute != '\0') {
4975 const gchar *prepend = "file://";
4978 codebase = g_strdup (absolute);
4983 for (i = strlen (codebase) - 1; i >= 0; i--)
4984 if (codebase [i] == '\\')
4987 if (*codebase == '/' && *(codebase + 1) == '/') {
4990 prepend = "file:///";
4994 result = g_strconcat (prepend, codebase, NULL);
5000 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5004 if (!create_culture) {
5005 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5006 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5007 g_assert (create_culture);
5008 mono_method_desc_free (desc);
5011 if (name->culture) {
5012 args [0] = mono_string_new (domain, name->culture);
5013 args [1] = &assembly_ref;
5014 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5017 if (name->public_key) {
5018 pkey_ptr = (char*)name->public_key;
5019 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5021 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5022 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5023 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5024 } else if (default_publickey) {
5025 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5026 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5029 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5030 if (name->public_key_token [0]) {
5034 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5035 p = mono_array_addr (aname->keyToken, char, 0);
5037 for (i = 0, j = 0; i < 8; i++) {
5038 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5039 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5042 } else if (default_token) {
5043 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5047 ICALL_EXPORT MonoString *
5048 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5050 MonoDomain *domain = mono_object_domain (assembly);
5051 MonoAssembly *mass = assembly->assembly;
5055 name = mono_stringify_assembly_name (&mass->aname);
5056 res = mono_string_new (domain, name);
5063 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5066 MonoAssembly *mass = assembly->assembly;
5068 if (g_path_is_absolute (mass->image->name)) {
5069 fill_reflection_assembly_name (mono_object_domain (assembly),
5070 aname, &mass->aname, mass->image->name, TRUE,
5074 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5076 fill_reflection_assembly_name (mono_object_domain (assembly),
5077 aname, &mass->aname, absolute, TRUE, TRUE,
5084 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5087 MonoImageOpenStatus status = MONO_IMAGE_OK;
5090 MonoAssemblyName name;
5093 filename = mono_string_to_utf8 (fname);
5095 dirname = g_path_get_dirname (filename);
5096 replace_shadow_path (mono_domain_get (), dirname, &filename);
5099 image = mono_image_open (filename, &status);
5105 if (status == MONO_IMAGE_IMAGE_INVALID)
5106 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5108 exc = mono_get_exception_file_not_found2 (NULL, fname);
5109 mono_set_pending_exception (exc);
5113 res = mono_assembly_fill_assembly_name (image, &name);
5115 mono_image_close (image);
5117 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5121 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5125 mono_image_close (image);
5128 ICALL_EXPORT MonoBoolean
5129 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5130 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5132 MonoBoolean result = FALSE;
5133 MonoDeclSecurityEntry entry;
5135 /* SecurityAction.RequestMinimum */
5136 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5137 *minimum = entry.blob;
5138 *minLength = entry.size;
5141 /* SecurityAction.RequestOptional */
5142 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5143 *optional = entry.blob;
5144 *optLength = entry.size;
5147 /* SecurityAction.RequestRefuse */
5148 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5149 *refused = entry.blob;
5150 *refLength = entry.size;
5158 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5160 guint32 attrs, visibility;
5162 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5163 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5164 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5167 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5173 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5176 MonoReflectionType *rt;
5179 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5182 /* we start the count from 1 because we skip the special type <Module> */
5185 for (i = 1; i < tdef->rows; ++i) {
5186 if (mono_module_type_is_visible (tdef, image, i + 1))
5190 count = tdef->rows - 1;
5192 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5193 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5195 for (i = 1; i < tdef->rows; ++i) {
5196 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5197 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, &error);
5198 mono_loader_assert_no_error (); /* Plug any leaks */
5199 g_assert (mono_error_ok (&error));
5202 rt = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5203 mono_error_raise_exception (&error); /* FIXME don't raise here */
5205 mono_array_setref (res, count, rt);
5207 MonoException *ex = mono_error_convert_to_exception (&error);
5208 mono_array_setref (*exceptions, count, ex);
5217 ICALL_EXPORT MonoArray*
5218 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5220 MonoArray *res = NULL;
5221 MonoArray *exceptions = NULL;
5222 MonoImage *image = NULL;
5223 MonoTableInfo *table = NULL;
5226 int i, len, ex_count;
5228 domain = mono_object_domain (assembly);
5230 g_assert (!assembly_is_dynamic (assembly->assembly));
5231 image = assembly->assembly->image;
5232 table = &image->tables [MONO_TABLE_FILE];
5233 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5235 /* Append data from all modules in the assembly */
5236 for (i = 0; i < table->rows; ++i) {
5237 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5238 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5241 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5242 /* Append the new types to the end of the array */
5243 if (mono_array_length (res2) > 0) {
5245 MonoArray *res3, *ex3;
5247 len1 = mono_array_length (res);
5248 len2 = mono_array_length (res2);
5250 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5251 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5252 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5255 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5256 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5257 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5264 /* the ReflectionTypeLoadException must have all the types (Types property),
5265 * NULL replacing types which throws an exception. The LoaderException must
5266 * contain all exceptions for NULL items.
5269 len = mono_array_length (res);
5272 for (i = 0; i < len; i++) {
5273 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5277 klass = mono_type_get_class (t->type);
5278 if ((klass != NULL) && klass->exception_type) {
5279 /* keep the class in the list */
5280 list = g_list_append (list, klass);
5281 /* and replace Type with NULL */
5282 mono_array_setref (res, i, NULL);
5289 if (list || ex_count) {
5291 MonoException *exc = NULL;
5292 MonoArray *exl = NULL;
5293 int j, length = g_list_length (list) + ex_count;
5295 mono_loader_clear_error ();
5297 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5298 /* Types for which mono_class_get_checked () succeeded */
5299 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5300 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5301 mono_array_setref (exl, i, exc);
5303 /* Types for which it don't */
5304 for (j = 0; j < mono_array_length (exceptions); ++j) {
5305 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5307 g_assert (i < length);
5308 mono_array_setref (exl, i, exc);
5315 exc = mono_get_exception_reflection_type_load (res, exl);
5316 mono_loader_clear_error ();
5317 mono_set_pending_exception (exc);
5324 ICALL_EXPORT gboolean
5325 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5327 MonoAssemblyName aname;
5328 MonoDomain *domain = mono_object_domain (name);
5330 gboolean is_version_defined;
5331 gboolean is_token_defined;
5333 aname.public_key = NULL;
5334 val = mono_string_to_utf8 (assname);
5335 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5336 g_free ((guint8*) aname.public_key);
5341 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5342 FALSE, is_token_defined);
5344 mono_assembly_name_free (&aname);
5345 g_free ((guint8*) aname.public_key);
5351 ICALL_EXPORT MonoReflectionType*
5352 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5355 MonoReflectionType *ret;
5356 MonoDomain *domain = mono_object_domain (module);
5359 g_assert (module->image);
5361 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5362 /* These images do not have a global type */
5365 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5366 if (!mono_error_ok (&error)) {
5367 mono_error_set_pending_exception (&error);
5371 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5372 if (!mono_error_ok (&error)) {
5373 mono_error_set_pending_exception (&error);
5381 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5383 /*if (module->image)
5384 mono_image_close (module->image);*/
5387 ICALL_EXPORT MonoString*
5388 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5390 MonoDomain *domain = mono_object_domain (module);
5392 g_assert (module->image);
5393 return mono_string_new (domain, module->image->guid);
5396 ICALL_EXPORT gpointer
5397 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5400 if (module->image && module->image->is_module_handle)
5401 return module->image->raw_data;
5404 return (gpointer) (-1);
5408 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5410 if (image_is_dynamic (image)) {
5411 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5412 *pe_kind = dyn->pe_kind;
5413 *machine = dyn->machine;
5416 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5417 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5422 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5424 return (image->md_version_major << 16) | (image->md_version_minor);
5427 ICALL_EXPORT MonoArray*
5428 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5430 MonoArray *exceptions;
5434 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5436 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5437 for (i = 0; i < mono_array_length (exceptions); ++i) {
5438 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5440 mono_set_pending_exception (ex);
5449 mono_memberref_is_method (MonoImage *image, guint32 token)
5451 if (!image_is_dynamic (image)) {
5452 guint32 cols [MONO_MEMBERREF_SIZE];
5454 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5455 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5456 mono_metadata_decode_blob_size (sig, &sig);
5457 return (*sig != 0x6);
5459 MonoClass *handle_class;
5461 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5464 return mono_defaults.methodhandle_class == handle_class;
5469 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5472 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5473 mono_array_addr (type_args, MonoType*, 0));
5475 context->class_inst = NULL;
5477 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5478 mono_array_addr (method_args, MonoType*, 0));
5480 context->method_inst = NULL;
5483 ICALL_EXPORT MonoType*
5484 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5487 int table = mono_metadata_token_table (token);
5488 int index = mono_metadata_token_index (token);
5489 MonoGenericContext context;
5492 *resolve_error = ResolveTokenError_Other;
5494 /* Validate token */
5495 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5496 (table != MONO_TABLE_TYPESPEC)) {
5497 *resolve_error = ResolveTokenError_BadTable;
5501 if (image_is_dynamic (image)) {
5502 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5503 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5504 return klass ? &klass->byval_arg : NULL;
5507 init_generic_context_from_args (&context, type_args, method_args);
5508 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5509 return klass ? &klass->byval_arg : NULL;
5512 if ((index <= 0) || (index > image->tables [table].rows)) {
5513 *resolve_error = ResolveTokenError_OutOfRange;
5517 init_generic_context_from_args (&context, type_args, method_args);
5518 klass = mono_class_get_checked (image, token, &error);
5520 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5521 if (!mono_error_ok (&error)) {
5522 mono_error_set_pending_exception (&error);
5527 return &klass->byval_arg;
5532 ICALL_EXPORT MonoMethod*
5533 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5536 int table = mono_metadata_token_table (token);
5537 int index = mono_metadata_token_index (token);
5538 MonoGenericContext context;
5541 *resolve_error = ResolveTokenError_Other;
5543 /* Validate token */
5544 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5545 (table != MONO_TABLE_MEMBERREF)) {
5546 *resolve_error = ResolveTokenError_BadTable;
5550 if (image_is_dynamic (image)) {
5551 if (table == MONO_TABLE_METHOD)
5552 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5554 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5555 *resolve_error = ResolveTokenError_BadTable;
5559 init_generic_context_from_args (&context, type_args, method_args);
5560 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5563 if ((index <= 0) || (index > image->tables [table].rows)) {
5564 *resolve_error = ResolveTokenError_OutOfRange;
5567 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5568 *resolve_error = ResolveTokenError_BadTable;
5572 init_generic_context_from_args (&context, type_args, method_args);
5573 method = mono_get_method_checked (image, token, NULL, &context, &error);
5574 mono_error_set_pending_exception (&error);
5579 ICALL_EXPORT MonoString*
5580 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5582 int index = mono_metadata_token_index (token);
5584 *error = ResolveTokenError_Other;
5586 /* Validate token */
5587 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5588 *error = ResolveTokenError_BadTable;
5592 if (image_is_dynamic (image))
5593 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5595 if ((index <= 0) || (index >= image->heap_us.size)) {
5596 *error = ResolveTokenError_OutOfRange;
5600 /* FIXME: What to do if the index points into the middle of a string ? */
5602 return mono_ldstr (mono_domain_get (), image, index);
5605 ICALL_EXPORT MonoClassField*
5606 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5610 int table = mono_metadata_token_table (token);
5611 int index = mono_metadata_token_index (token);
5612 MonoGenericContext context;
5613 MonoClassField *field;
5615 *resolve_error = ResolveTokenError_Other;
5617 /* Validate token */
5618 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5619 *resolve_error = ResolveTokenError_BadTable;
5623 if (image_is_dynamic (image)) {
5624 if (table == MONO_TABLE_FIELD)
5625 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5627 if (mono_memberref_is_method (image, token)) {
5628 *resolve_error = ResolveTokenError_BadTable;
5632 init_generic_context_from_args (&context, type_args, method_args);
5633 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5636 if ((index <= 0) || (index > image->tables [table].rows)) {
5637 *resolve_error = ResolveTokenError_OutOfRange;
5640 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5641 *resolve_error = ResolveTokenError_BadTable;
5645 init_generic_context_from_args (&context, type_args, method_args);
5646 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5647 mono_error_set_pending_exception (&error);
5653 ICALL_EXPORT MonoObject*
5654 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5658 int table = mono_metadata_token_table (token);
5660 *error = ResolveTokenError_Other;
5663 case MONO_TABLE_TYPEDEF:
5664 case MONO_TABLE_TYPEREF:
5665 case MONO_TABLE_TYPESPEC: {
5666 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5668 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
5669 mono_error_raise_exception (&merror);
5676 case MONO_TABLE_METHOD:
5677 case MONO_TABLE_METHODSPEC: {
5678 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5680 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5684 case MONO_TABLE_FIELD: {
5685 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5687 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5688 mono_error_raise_exception (&merror);
5694 case MONO_TABLE_MEMBERREF:
5695 if (mono_memberref_is_method (image, token)) {
5696 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5698 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5703 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5705 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5706 mono_error_raise_exception (&merror);
5715 *error = ResolveTokenError_BadTable;
5721 ICALL_EXPORT MonoArray*
5722 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5724 int table = mono_metadata_token_table (token);
5725 int idx = mono_metadata_token_index (token);
5726 MonoTableInfo *tables = image->tables;
5731 *error = ResolveTokenError_OutOfRange;
5733 /* FIXME: Support other tables ? */
5734 if (table != MONO_TABLE_STANDALONESIG)
5737 if (image_is_dynamic (image))
5740 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5743 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5745 ptr = mono_metadata_blob_heap (image, sig);
5746 len = mono_metadata_decode_blob_size (ptr, &ptr);
5748 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5749 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5753 ICALL_EXPORT MonoReflectionType*
5754 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5757 MonoReflectionType *ret;
5759 int isbyref = 0, rank;
5760 char *str = mono_string_to_utf8 (smodifiers);
5763 klass = mono_class_from_mono_type (tb->type.type);
5765 /* logic taken from mono_reflection_parse_type(): keep in sync */
5769 if (isbyref) { /* only one level allowed by the spec */
5778 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
5779 mono_error_raise_exception (&error);
5783 klass = mono_ptr_class_get (&klass->byval_arg);
5784 mono_class_init (klass);
5795 else if (*p != '*') { /* '*' means unknown lower bound */
5806 klass = mono_array_class_get (klass, rank);
5807 mono_class_init (klass);
5816 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
5817 mono_error_raise_exception (&error);
5822 ICALL_EXPORT MonoBoolean
5823 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5829 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5835 check_for_invalid_type (MonoClass *klass)
5839 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5842 name = mono_type_get_full_name (klass);
5843 str = mono_string_new (mono_domain_get (), name);
5845 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5848 ICALL_EXPORT MonoReflectionType *
5849 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5852 MonoReflectionType *ret;
5853 MonoClass *klass, *aklass;
5855 klass = mono_class_from_mono_type (type->type);
5856 check_for_invalid_type (klass);
5858 if (rank == 0) //single dimentional array
5859 aklass = mono_array_class_get (klass, 1);
5861 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5863 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
5864 mono_error_raise_exception (&error);
5869 ICALL_EXPORT MonoReflectionType *
5870 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5873 MonoReflectionType *ret;
5876 klass = mono_class_from_mono_type (type->type);
5877 mono_class_init_or_throw (klass);
5878 check_for_invalid_type (klass);
5880 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
5881 mono_error_raise_exception (&error);
5886 ICALL_EXPORT MonoReflectionType *
5887 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5890 MonoReflectionType *ret;
5891 MonoClass *klass, *pklass;
5893 klass = mono_class_from_mono_type (type->type);
5894 mono_class_init_or_throw (klass);
5895 check_for_invalid_type (klass);
5897 pklass = mono_ptr_class_get (type->type);
5899 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
5900 mono_error_raise_exception (&error);
5905 ICALL_EXPORT MonoObject *
5906 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5907 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5909 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5910 MonoObject *delegate;
5912 MonoMethod *method = info->method;
5914 mono_class_init_or_throw (delegate_class);
5916 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5918 if (mono_security_core_clr_enabled ()) {
5919 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5923 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5925 if (method_is_dynamic (method)) {
5926 /* Creating a trampoline would leak memory */
5927 func = mono_compile_method (method);
5929 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5930 method = mono_object_get_virtual_method (target, method);
5931 func = mono_create_ftnptr (mono_domain_get (),
5932 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5935 mono_delegate_ctor_with_method (delegate, target, func, method);
5940 ICALL_EXPORT MonoMulticastDelegate *
5941 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
5943 MonoMulticastDelegate *ret;
5945 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
5947 ret = (MonoMulticastDelegate*) mono_object_new (mono_object_domain (delegate), mono_object_class (delegate));
5948 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
5953 ICALL_EXPORT MonoReflectionMethod*
5954 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
5956 return mono_method_get_object (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target));
5961 static inline gint32
5962 mono_array_get_byte_length (MonoArray *array)
5968 klass = array->obj.vtable->klass;
5970 if (array->bounds == NULL)
5971 length = array->max_length;
5974 for (i = 0; i < klass->rank; ++ i)
5975 length *= array->bounds [i].length;
5978 switch (klass->element_class->byval_arg.type) {
5981 case MONO_TYPE_BOOLEAN:
5985 case MONO_TYPE_CHAR:
5993 return length * sizeof (gpointer);
6004 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6006 return mono_array_get_byte_length (array);
6010 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6012 return mono_array_get (array, gint8, idx);
6016 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6018 mono_array_set (array, gint8, idx, value);
6021 ICALL_EXPORT MonoBoolean
6022 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6024 guint8 *src_buf, *dest_buf;
6027 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6031 g_assert (count >= 0);
6033 /* This is called directly from the class libraries without going through the managed wrapper */
6034 MONO_CHECK_ARG_NULL (src, FALSE);
6035 MONO_CHECK_ARG_NULL (dest, FALSE);
6037 /* watch out for integer overflow */
6038 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6041 src_buf = (guint8 *)src->vector + src_offset;
6042 dest_buf = (guint8 *)dest->vector + dest_offset;
6045 memcpy (dest_buf, src_buf, count);
6047 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6052 #ifndef DISABLE_REMOTING
6053 ICALL_EXPORT MonoObject *
6054 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6056 MonoDomain *domain = mono_object_domain (this_obj);
6058 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6059 MonoTransparentProxy *tp;
6063 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6064 tp = (MonoTransparentProxy*) res;
6066 MONO_OBJECT_SETREF (tp, rp, rp);
6067 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6068 klass = mono_class_from_mono_type (type);
6070 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6071 mono_class_setup_vtable (klass);
6072 if (klass->exception_type) {
6073 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6077 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
6078 tp->remote_class = mono_remote_class (domain, class_name, klass);
6080 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6084 ICALL_EXPORT MonoReflectionType *
6085 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6088 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6089 mono_error_raise_exception (&error);
6095 /* System.Environment */
6098 ves_icall_System_Environment_get_UserName (void)
6100 /* using glib is more portable */
6101 return mono_string_new (mono_domain_get (), g_get_user_name ());
6105 ICALL_EXPORT MonoString *
6106 ves_icall_System_Environment_get_MachineName (void)
6108 #if defined (HOST_WIN32)
6113 len = MAX_COMPUTERNAME_LENGTH + 1;
6114 buf = g_new (gunichar2, len);
6117 if (GetComputerName (buf, (PDWORD) &len))
6118 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6122 #elif !defined(DISABLE_SOCKETS)
6126 #if defined _SC_HOST_NAME_MAX
6127 n = sysconf (_SC_HOST_NAME_MAX);
6131 buf = g_malloc (n+1);
6133 if (gethostname (buf, n) == 0){
6135 result = mono_string_new (mono_domain_get (), buf);
6142 return mono_string_new (mono_domain_get (), "mono");
6147 ves_icall_System_Environment_get_Platform (void)
6149 #if defined (TARGET_WIN32)
6152 #elif defined(__MACH__)
6155 // Notice that the value is hidden from user code, and only exposed
6156 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6157 // define and making assumptions based on Unix/128/4 values before there
6158 // was a MacOS define. Lots of code would assume that not-Unix meant
6159 // Windows, but in this case, it would be OSX.
6168 ICALL_EXPORT MonoString *
6169 ves_icall_System_Environment_get_NewLine (void)
6171 #if defined (HOST_WIN32)
6172 return mono_string_new (mono_domain_get (), "\r\n");
6174 return mono_string_new (mono_domain_get (), "\n");
6178 ICALL_EXPORT MonoBoolean
6179 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6181 #if SIZEOF_VOID_P == 8
6185 gboolean isWow64Process = FALSE;
6186 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6187 return (MonoBoolean)isWow64Process;
6189 #elif defined(HAVE_SYS_UTSNAME_H)
6190 struct utsname name;
6192 if (uname (&name) >= 0) {
6193 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6200 ICALL_EXPORT MonoString *
6201 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6209 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6210 value = g_getenv (utf8_name);
6217 return mono_string_new (mono_domain_get (), value);
6221 * There is no standard way to get at environ.
6224 #ifndef __MINGW32_VERSION
6225 #if defined(__APPLE__)
6226 #if defined (TARGET_OSX)
6227 /* Apple defines this in crt_externs.h but doesn't provide that header for
6228 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6229 * in fact exist on all implementations (so far)
6231 gchar ***_NSGetEnviron(void);
6232 #define environ (*_NSGetEnviron())
6234 static char *mono_environ[1] = { NULL };
6235 #define environ mono_environ
6236 #endif /* defined (TARGET_OSX) */
6244 ICALL_EXPORT MonoArray *
6245 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6256 env_strings = GetEnvironmentStrings();
6259 env_string = env_strings;
6260 while (*env_string != '\0') {
6261 /* weird case that MS seems to skip */
6262 if (*env_string != '=')
6264 while (*env_string != '\0')
6270 domain = mono_domain_get ();
6271 names = mono_array_new (domain, mono_defaults.string_class, n);
6275 env_string = env_strings;
6276 while (*env_string != '\0') {
6277 /* weird case that MS seems to skip */
6278 if (*env_string != '=') {
6279 equal_str = wcschr(env_string, '=');
6280 g_assert(equal_str);
6281 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6282 mono_array_setref (names, n, str);
6285 while (*env_string != '\0')
6290 FreeEnvironmentStrings (env_strings);
6303 for (e = environ; *e != 0; ++ e)
6306 domain = mono_domain_get ();
6307 names = mono_array_new (domain, mono_defaults.string_class, n);
6310 for (e = environ; *e != 0; ++ e) {
6311 parts = g_strsplit (*e, "=", 2);
6313 str = mono_string_new (domain, *parts);
6314 mono_array_setref (names, n, str);
6327 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6329 #if !GLIB_CHECK_VERSION(2,4,0)
6330 #define g_setenv(a,b,c) setenv(a,b,c)
6331 #define g_unsetenv(a) unsetenv(a)
6335 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6338 gunichar2 *utf16_name, *utf16_value;
6340 gchar *utf8_name, *utf8_value;
6345 utf16_name = mono_string_to_utf16 (name);
6346 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6347 SetEnvironmentVariable (utf16_name, NULL);
6348 g_free (utf16_name);
6352 utf16_value = mono_string_to_utf16 (value);
6354 SetEnvironmentVariable (utf16_name, utf16_value);
6356 g_free (utf16_name);
6357 g_free (utf16_value);
6359 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6361 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6362 g_unsetenv (utf8_name);
6367 utf8_value = mono_string_to_utf8_checked (value, &error);
6368 if (!mono_error_ok (&error)) {
6370 mono_error_set_pending_exception (&error);
6373 g_setenv (utf8_name, utf8_value, TRUE);
6376 g_free (utf8_value);
6381 ves_icall_System_Environment_Exit (int result)
6383 mono_environment_exitcode_set (result);
6385 /* FIXME: There are some cleanup hangs that should be worked out, but
6386 * if the program is going to exit, everything will be cleaned up when
6387 * NaCl exits anyway.
6389 #ifndef __native_client__
6390 if (!mono_runtime_try_shutdown ())
6391 mono_thread_exit ();
6393 /* Suspend all managed threads since the runtime is going away */
6394 mono_thread_suspend_all_other_threads ();
6396 mono_runtime_quit ();
6399 /* we may need to do some cleanup here... */
6403 ICALL_EXPORT MonoString*
6404 ves_icall_System_Environment_GetGacPath (void)
6406 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6409 ICALL_EXPORT MonoString*
6410 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6412 #if defined (HOST_WIN32)
6413 #ifndef CSIDL_FLAG_CREATE
6414 #define CSIDL_FLAG_CREATE 0x8000
6417 WCHAR path [MAX_PATH];
6418 /* Create directory if no existing */
6419 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6423 return mono_string_new_utf16 (mono_domain_get (), path, len);
6426 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6428 return mono_string_new (mono_domain_get (), "");
6431 ICALL_EXPORT MonoArray *
6432 ves_icall_System_Environment_GetLogicalDrives (void)
6434 gunichar2 buf [256], *ptr, *dname;
6436 guint initial_size = 127, size = 128;
6439 MonoString *drivestr;
6440 MonoDomain *domain = mono_domain_get ();
6446 while (size > initial_size) {
6447 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6448 if (size > initial_size) {
6451 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6452 initial_size = size;
6466 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6471 while (*u16) { u16++; len ++; }
6472 drivestr = mono_string_new_utf16 (domain, dname, len);
6473 mono_array_setref (result, ndrives++, drivestr);
6483 ICALL_EXPORT MonoString *
6484 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6486 gunichar2 volume_name [MAX_PATH + 1];
6488 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6490 return mono_string_from_utf16 (volume_name);
6493 ICALL_EXPORT MonoString *
6494 ves_icall_System_Environment_InternalGetHome (void)
6496 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6499 static const char *encodings [] = {
6501 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6502 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6503 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6505 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6506 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6507 "x_unicode_2_0_utf_7",
6509 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6510 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6512 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6515 "unicodefffe", "utf_16be",
6522 * Returns the internal codepage, if the value of "int_code_page" is
6523 * 1 at entry, and we can not compute a suitable code page number,
6524 * returns the code page as a string
6526 ICALL_EXPORT MonoString*
6527 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6532 char *codepage = NULL;
6534 int want_name = *int_code_page;
6537 *int_code_page = -1;
6539 g_get_charset (&cset);
6540 c = codepage = strdup (cset);
6541 for (c = codepage; *c; c++){
6542 if (isascii (*c) && isalpha (*c))
6547 /* g_print ("charset: %s\n", cset); */
6549 /* handle some common aliases */
6552 for (i = 0; p != 0; ){
6555 p = encodings [++i];
6558 if (strcmp (p, codepage) == 0){
6559 *int_code_page = code;
6562 p = encodings [++i];
6565 if (strstr (codepage, "utf_8") != NULL)
6566 *int_code_page |= 0x10000000;
6569 if (want_name && *int_code_page == -1)
6570 return mono_string_new (mono_domain_get (), cset);
6575 ICALL_EXPORT MonoBoolean
6576 ves_icall_System_Environment_get_HasShutdownStarted (void)
6578 if (mono_runtime_is_shutting_down ())
6581 if (mono_domain_is_unloading (mono_domain_get ()))
6588 ves_icall_System_Environment_BroadcastSettingChange (void)
6591 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6596 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6602 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6603 MonoReflectionMethod *method,
6604 MonoArray *out_args)
6606 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6609 #ifndef DISABLE_REMOTING
6610 ICALL_EXPORT MonoBoolean
6611 ves_icall_IsTransparentProxy (MonoObject *proxy)
6616 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6622 ICALL_EXPORT MonoReflectionMethod *
6623 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6624 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6628 MonoMethod **vtable;
6629 MonoMethod *res = NULL;
6631 MONO_CHECK_ARG_NULL (rtype, NULL);
6632 MONO_CHECK_ARG_NULL (rmethod, NULL);
6634 method = rmethod->method;
6635 klass = mono_class_from_mono_type (rtype->type);
6636 mono_class_init_or_throw (klass);
6638 if (MONO_CLASS_IS_INTERFACE (klass))
6641 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6644 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6645 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6651 mono_class_setup_vtable (klass);
6652 vtable = klass->vtable;
6654 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6655 gboolean variance_used = FALSE;
6656 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6657 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6659 res = vtable [offs + method->slot];
6661 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6664 if (method->slot != -1)
6665 res = vtable [method->slot];
6671 return mono_method_get_object (mono_domain_get (), res, NULL);
6675 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6680 klass = mono_class_from_mono_type (type->type);
6681 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6683 mono_vtable_set_is_remote (vtable, enable);
6686 #else /* DISABLE_REMOTING */
6689 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6691 g_assert_not_reached ();
6696 ICALL_EXPORT MonoObject *
6697 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6704 domain = mono_object_domain (type);
6705 klass = mono_class_from_mono_type (type->type);
6706 mono_class_init_or_throw (klass);
6708 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
6709 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6713 if (klass->rank >= 1) {
6714 g_assert (klass->rank == 1);
6715 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6717 /* Bypass remoting object creation check */
6718 ret = mono_object_new_alloc_specific_checked (mono_class_vtable_full (domain, klass, TRUE), &error);
6719 mono_error_set_pending_exception (&error);
6725 ICALL_EXPORT MonoString *
6726 ves_icall_System_IO_get_temp_path (void)
6728 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6731 #ifndef PLATFORM_NO_DRIVEINFO
6732 ICALL_EXPORT MonoBoolean
6733 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6734 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6738 ULARGE_INTEGER wapi_free_bytes_avail;
6739 ULARGE_INTEGER wapi_total_number_of_bytes;
6740 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6742 *error = ERROR_SUCCESS;
6743 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6744 &wapi_total_number_of_free_bytes);
6747 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6748 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6749 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6751 *free_bytes_avail = 0;
6752 *total_number_of_bytes = 0;
6753 *total_number_of_free_bytes = 0;
6754 *error = GetLastError ();
6760 ICALL_EXPORT guint32
6761 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6763 return GetDriveType (mono_string_chars (root_path_name));
6767 ICALL_EXPORT gpointer
6768 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6770 return mono_compile_method (method);
6773 ICALL_EXPORT MonoString *
6774 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6779 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6781 #if defined (HOST_WIN32)
6782 /* Avoid mixing '/' and '\\' */
6785 for (i = strlen (path) - 1; i >= 0; i--)
6786 if (path [i] == '/')
6790 mcpath = mono_string_new (mono_domain_get (), path);
6797 get_bundled_app_config (void)
6799 const gchar *app_config;
6802 gchar *config_file_name, *config_file_path;
6803 gsize len, config_file_path_length, config_ext_length;
6806 domain = mono_domain_get ();
6807 file = domain->setup->configuration_file;
6808 if (!file || file->length == 0)
6811 // Retrieve config file and remove the extension
6812 config_file_name = mono_string_to_utf8 (file);
6813 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6814 if (!config_file_path)
6815 config_file_path = config_file_name;
6817 config_file_path_length = strlen (config_file_path);
6818 config_ext_length = strlen (".config");
6819 if (config_file_path_length <= config_ext_length)
6822 len = config_file_path_length - config_ext_length;
6823 module = (gchar *)g_malloc0 (len + 1);
6824 memcpy (module, config_file_path, len);
6825 // Get the config file from the module name
6826 app_config = mono_config_string_for_assembly_file (module);
6829 if (config_file_name != config_file_path)
6830 g_free (config_file_name);
6831 g_free (config_file_path);
6836 return mono_string_new (mono_domain_get (), app_config);
6840 get_bundled_machine_config (void)
6842 const gchar *machine_config;
6844 machine_config = mono_get_machine_config ();
6846 if (!machine_config)
6849 return mono_string_new (mono_domain_get (), machine_config);
6852 ICALL_EXPORT MonoString *
6853 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6858 path = g_path_get_dirname (mono_get_config_dir ());
6860 #if defined (HOST_WIN32)
6861 /* Avoid mixing '/' and '\\' */
6864 for (i = strlen (path) - 1; i >= 0; i--)
6865 if (path [i] == '/')
6869 ipath = mono_string_new (mono_domain_get (), path);
6875 ICALL_EXPORT gboolean
6876 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6878 MonoPEResourceDataEntry *entry;
6881 if (!assembly || !result || !size)
6886 image = assembly->assembly->image;
6887 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6891 *result = mono_image_rva_map (image, entry->rde_data_offset);
6896 *size = entry->rde_size;
6901 ICALL_EXPORT MonoBoolean
6902 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6904 return mono_is_debugger_attached ();
6907 ICALL_EXPORT MonoBoolean
6908 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
6910 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
6911 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
6917 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
6919 if (mono_get_runtime_callbacks ()->debug_log)
6920 mono_get_runtime_callbacks ()->debug_log (level, category, message);
6924 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6926 #if defined (HOST_WIN32)
6927 OutputDebugString (mono_string_chars (message));
6929 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6933 /* Only used for value types */
6934 ICALL_EXPORT MonoObject *
6935 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6940 domain = mono_object_domain (type);
6941 klass = mono_class_from_mono_type (type->type);
6942 mono_class_init_or_throw (klass);
6944 if (mono_class_is_nullable (klass))
6945 /* No arguments -> null */
6948 return mono_object_new (domain, klass);
6951 ICALL_EXPORT MonoReflectionMethod *
6952 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
6954 MonoClass *klass, *parent;
6955 MonoGenericContext *generic_inst = NULL;
6956 MonoMethod *method = m->method;
6957 MonoMethod *result = NULL;
6960 if (method->klass == NULL)
6963 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6964 MONO_CLASS_IS_INTERFACE (method->klass) ||
6965 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6968 slot = mono_method_get_vtable_slot (method);
6972 klass = method->klass;
6973 if (klass->generic_class) {
6974 generic_inst = mono_class_get_context (klass);
6975 klass = klass->generic_class->container_class;
6979 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6980 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6981 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
6982 or klass is the generic container class and generic_inst is the instantiation.
6984 when we go to the parent, if the parent is an open constructed type, we need to
6985 replace the type parameters by the definitions from the generic_inst, and then take it
6986 apart again into the klass and the generic_inst.
6988 For cases like this:
6989 class C<T> : B<T, int> {
6990 public override void Foo () { ... }
6992 class B<U,V> : A<HashMap<U,V>> {
6993 public override void Foo () { ... }
6996 public virtual void Foo () { ... }
6999 if at each iteration the parent isn't open, we can skip inflating it. if at some
7000 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7003 MonoGenericContext *parent_inst = NULL;
7004 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7006 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7007 if (!mono_error_ok (&error)) {
7008 mono_error_set_pending_exception (&error);
7012 if (parent->generic_class) {
7013 parent_inst = mono_class_get_context (parent);
7014 parent = parent->generic_class->container_class;
7017 mono_class_setup_vtable (parent);
7018 if (parent->vtable_size <= slot)
7021 generic_inst = parent_inst;
7024 klass = klass->parent;
7027 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7029 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7030 if (!mono_error_ok (&error)) {
7031 mono_error_set_pending_exception (&error);
7035 generic_inst = NULL;
7037 if (klass->generic_class) {
7038 generic_inst = mono_class_get_context (klass);
7039 klass = klass->generic_class->container_class;
7046 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7047 if (!mono_error_ok (&error)) {
7048 mono_error_set_pending_exception (&error);
7053 if (klass == method->klass)
7056 /*This is possible if definition == FALSE.
7057 * Do it here to be really sure we don't read invalid memory.
7059 if (slot >= klass->vtable_size)
7062 mono_class_setup_vtable (klass);
7064 result = klass->vtable [slot];
7065 if (result == NULL) {
7066 /* It is an abstract method */
7067 gpointer iter = NULL;
7068 while ((result = mono_class_get_methods (klass, &iter)))
7069 if (result->slot == slot)
7076 return mono_method_get_object (mono_domain_get (), result, NULL);
7079 ICALL_EXPORT MonoString*
7080 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7082 MonoMethod *method = m->method;
7084 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7089 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7091 iter->sig = *(MonoMethodSignature**)argsp;
7093 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7094 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7097 /* FIXME: it's not documented what start is exactly... */
7101 iter->args = argsp + sizeof (gpointer);
7103 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7105 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7108 ICALL_EXPORT MonoTypedRef
7109 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7111 guint32 i, arg_size;
7115 i = iter->sig->sentinelpos + iter->next_arg;
7117 g_assert (i < iter->sig->param_count);
7119 res.type = iter->sig->params [i];
7120 res.klass = mono_class_from_mono_type (res.type);
7121 arg_size = mono_type_stack_size (res.type, &align);
7122 #if defined(__arm__) || defined(__mips__)
7123 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7125 res.value = iter->args;
7126 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7127 /* Values are stored as 8 byte register sized objects, but 'value'
7128 * is dereferenced as a pointer in other routines.
7130 res.value = (char*)res.value + 4;
7132 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7133 if (arg_size <= sizeof (gpointer)) {
7135 int padding = arg_size - mono_type_size (res.type, &dummy);
7136 res.value = (guint8*)res.value + padding;
7139 iter->args = (char*)iter->args + arg_size;
7142 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7147 ICALL_EXPORT MonoTypedRef
7148 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7150 guint32 i, arg_size;
7154 i = iter->sig->sentinelpos + iter->next_arg;
7156 g_assert (i < iter->sig->param_count);
7158 while (i < iter->sig->param_count) {
7159 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7161 res.type = iter->sig->params [i];
7162 res.klass = mono_class_from_mono_type (res.type);
7163 /* FIXME: endianess issue... */
7164 arg_size = mono_type_stack_size (res.type, &align);
7165 #if defined(__arm__) || defined(__mips__)
7166 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7168 res.value = iter->args;
7169 iter->args = (char*)iter->args + arg_size;
7171 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7174 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7182 ICALL_EXPORT MonoType*
7183 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7187 i = iter->sig->sentinelpos + iter->next_arg;
7189 g_assert (i < iter->sig->param_count);
7191 return iter->sig->params [i];
7194 ICALL_EXPORT MonoObject*
7195 mono_TypedReference_ToObject (MonoTypedRef* tref)
7197 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7198 MonoObject** objp = (MonoObject **)tref->value;
7202 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
7205 ICALL_EXPORT MonoTypedRef
7206 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7209 MonoReflectionField *f;
7211 MonoType *ftype = NULL;
7215 memset (&res, 0, sizeof (res));
7218 g_assert (mono_array_length (fields) > 0);
7220 klass = target->vtable->klass;
7222 for (i = 0; i < mono_array_length (fields); ++i) {
7223 f = mono_array_get (fields, MonoReflectionField*, i);
7225 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7228 if (f->field->parent != klass) {
7229 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7233 p = (guint8*)target + f->field->offset;
7235 p += f->field->offset - sizeof (MonoObject);
7236 klass = mono_class_from_mono_type (f->field->type);
7237 ftype = f->field->type;
7241 res.klass = mono_class_from_mono_type (ftype);
7248 prelink_method (MonoMethod *method)
7250 const char *exc_class, *exc_arg;
7251 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7253 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7255 mono_raise_exception(
7256 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7258 /* create the wrapper, too? */
7262 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7264 prelink_method (method->method);
7268 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7270 MonoClass *klass = mono_class_from_mono_type (type->type);
7272 gpointer iter = NULL;
7274 mono_class_init_or_throw (klass);
7276 while ((m = mono_class_get_methods (klass, &iter)))
7280 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7282 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7283 gint32 const **exponents,
7284 gunichar2 const **digitLowerTable,
7285 gunichar2 const **digitUpperTable,
7286 gint64 const **tenPowersList,
7287 gint32 const **decHexDigits)
7289 *mantissas = Formatter_MantissaBitsTable;
7290 *exponents = Formatter_TensExponentTable;
7291 *digitLowerTable = Formatter_DigitLowerTable;
7292 *digitUpperTable = Formatter_DigitUpperTable;
7293 *tenPowersList = Formatter_TenPowersList;
7294 *decHexDigits = Formatter_DecHexDigits;
7298 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7299 * and avoid useless allocations.
7304 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7307 MonoReflectionType *rt;
7310 for (i = 0; i < type->num_mods; ++i) {
7311 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7316 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7318 for (i = 0; i < type->num_mods; ++i) {
7319 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7320 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
7321 mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */
7323 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, &error);
7324 mono_error_raise_exception (&error);
7326 mono_array_setref (res, count, rt);
7333 ICALL_EXPORT MonoArray*
7334 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7336 MonoType *type = param->ClassImpl->type;
7337 MonoClass *member_class = mono_object_class (param->MemberImpl);
7338 MonoMethod *method = NULL;
7341 MonoMethodSignature *sig;
7343 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7344 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7345 method = rmethod->method;
7346 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7347 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7348 if (!(method = prop->property->get))
7349 method = prop->property->set;
7352 char *type_name = mono_type_get_full_name (member_class);
7353 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7354 MonoException *ex = mono_get_exception_not_supported (msg);
7357 mono_set_pending_exception (ex);
7361 image = method->klass->image;
7362 pos = param->PositionImpl;
7363 sig = mono_method_signature (method);
7367 type = sig->params [pos];
7369 return type_array_from_modifiers (image, type, optional);
7373 get_property_type (MonoProperty *prop)
7375 MonoMethodSignature *sig;
7377 sig = mono_method_signature (prop->get);
7379 } else if (prop->set) {
7380 sig = mono_method_signature (prop->set);
7381 return sig->params [sig->param_count - 1];
7386 ICALL_EXPORT MonoArray*
7387 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7389 MonoType *type = get_property_type (property->property);
7390 MonoImage *image = property->klass->image;
7394 return type_array_from_modifiers (image, type, optional);
7398 *Construct a MonoType suited to be used to decode a constant blob object.
7400 * @type is the target type which will be constructed
7401 * @blob_type is the blob type, for example, that comes from the constant table
7402 * @real_type is the expected constructed type.
7405 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7407 type->type = blob_type;
7408 type->data.klass = NULL;
7409 if (blob_type == MONO_TYPE_CLASS)
7410 type->data.klass = mono_defaults.object_class;
7411 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7412 /* For enums, we need to use the base type */
7413 type->type = MONO_TYPE_VALUETYPE;
7414 type->data.klass = mono_class_from_mono_type (real_type);
7416 type->data.klass = mono_class_from_mono_type (real_type);
7419 ICALL_EXPORT MonoObject*
7420 property_info_get_default_value (MonoReflectionProperty *property)
7423 MonoProperty *prop = property->property;
7424 MonoType *type = get_property_type (prop);
7425 MonoDomain *domain = mono_object_domain (property);
7426 MonoTypeEnum def_type;
7427 const char *def_value;
7430 mono_class_init (prop->parent);
7432 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7433 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7437 def_value = mono_class_get_property_default_value (prop, &def_type);
7439 mono_type_from_blob_type (&blob_type, def_type, type);
7440 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7445 ICALL_EXPORT MonoBoolean
7446 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7448 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7449 MonoCustomAttrInfo *cinfo;
7452 mono_class_init_or_throw (attr_class);
7454 cinfo = mono_reflection_get_custom_attrs_info (obj);
7457 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7459 mono_custom_attrs_free (cinfo);
7463 ICALL_EXPORT MonoArray*
7464 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7466 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7471 mono_class_init_or_throw (attr_class);
7473 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7474 if (!mono_error_ok (&error)) {
7475 mono_error_set_pending_exception (&error);
7479 if (mono_loader_get_last_error ()) {
7480 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7487 ICALL_EXPORT MonoString*
7488 ves_icall_Mono_Runtime_GetDisplayName (void)
7491 MonoString *display_name;
7493 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7494 display_name = mono_string_new (mono_domain_get (), info);
7496 return display_name;
7499 ICALL_EXPORT MonoString*
7500 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7502 MonoString *message;
7506 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7507 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7510 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7512 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7519 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7522 char *path_str = mono_string_to_utf8 (path);
7524 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7532 #ifndef DISABLE_ICALL_TABLES
7534 #define ICALL_TYPE(id,name,first)
7535 #define ICALL(id,name,func) Icall_ ## id,
7538 #include "metadata/icall-def.h"
7544 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7545 #define ICALL(id,name,func)
7547 #include "metadata/icall-def.h"
7553 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7554 #define ICALL(id,name,func)
7556 guint16 first_icall;
7559 static const IcallTypeDesc
7560 icall_type_descs [] = {
7561 #include "metadata/icall-def.h"
7565 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7568 #define ICALL_TYPE(id,name,first)
7571 #ifdef HAVE_ARRAY_ELEM_INIT
7572 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7573 #define MSGSTRFIELD1(line) str##line
7575 static const struct msgstrtn_t {
7576 #define ICALL(id,name,func)
7578 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7579 #include "metadata/icall-def.h"
7581 } icall_type_names_str = {
7582 #define ICALL_TYPE(id,name,first) (name),
7583 #include "metadata/icall-def.h"
7586 static const guint16 icall_type_names_idx [] = {
7587 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7588 #include "metadata/icall-def.h"
7591 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7593 static const struct msgstr_t {
7595 #define ICALL_TYPE(id,name,first)
7596 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7597 #include "metadata/icall-def.h"
7599 } icall_names_str = {
7600 #define ICALL(id,name,func) (name),
7601 #include "metadata/icall-def.h"
7604 static const guint16 icall_names_idx [] = {
7605 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7606 #include "metadata/icall-def.h"
7609 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7615 #define ICALL_TYPE(id,name,first) name,
7616 #define ICALL(id,name,func)
7617 static const char* const
7618 icall_type_names [] = {
7619 #include "metadata/icall-def.h"
7623 #define icall_type_name_get(id) (icall_type_names [(id)])
7627 #define ICALL_TYPE(id,name,first)
7628 #define ICALL(id,name,func) name,
7629 static const char* const
7631 #include "metadata/icall-def.h"
7634 #define icall_name_get(id) icall_names [(id)]
7636 #endif /* !HAVE_ARRAY_ELEM_INIT */
7640 #define ICALL_TYPE(id,name,first)
7641 #define ICALL(id,name,func) func,
7642 static const gconstpointer
7643 icall_functions [] = {
7644 #include "metadata/icall-def.h"
7648 #ifdef ENABLE_ICALL_SYMBOL_MAP
7651 #define ICALL_TYPE(id,name,first)
7652 #define ICALL(id,name,func) #func,
7653 static const gconstpointer
7654 icall_symbols [] = {
7655 #include "metadata/icall-def.h"
7660 #endif /* DISABLE_ICALL_TABLES */
7662 static mono_mutex_t icall_mutex;
7663 static GHashTable *icall_hash = NULL;
7664 static GHashTable *jit_icall_hash_name = NULL;
7665 static GHashTable *jit_icall_hash_addr = NULL;
7668 mono_icall_init (void)
7670 #ifndef DISABLE_ICALL_TABLES
7673 /* check that tables are sorted: disable in release */
7676 const char *prev_class = NULL;
7677 const char *prev_method;
7679 for (i = 0; i < Icall_type_num; ++i) {
7680 const IcallTypeDesc *desc;
7683 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7684 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7685 prev_class = icall_type_name_get (i);
7686 desc = &icall_type_descs [i];
7687 num_icalls = icall_desc_num_icalls (desc);
7688 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7689 for (j = 0; j < num_icalls; ++j) {
7690 const char *methodn = icall_name_get (desc->first_icall + j);
7691 if (prev_method && strcmp (prev_method, methodn) >= 0)
7692 g_print ("method %s should come before method %s\n", methodn, prev_method);
7693 prev_method = methodn;
7699 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7700 mono_os_mutex_init (&icall_mutex);
7704 mono_icall_lock (void)
7706 mono_locks_os_acquire (&icall_mutex, IcallLock);
7710 mono_icall_unlock (void)
7712 mono_locks_os_release (&icall_mutex, IcallLock);
7716 mono_icall_cleanup (void)
7718 g_hash_table_destroy (icall_hash);
7719 g_hash_table_destroy (jit_icall_hash_name);
7720 g_hash_table_destroy (jit_icall_hash_addr);
7721 mono_os_mutex_destroy (&icall_mutex);
7725 mono_add_internal_call (const char *name, gconstpointer method)
7729 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7731 mono_icall_unlock ();
7734 #ifndef DISABLE_ICALL_TABLES
7736 #ifdef HAVE_ARRAY_ELEM_INIT
7738 compare_method_imap (const void *key, const void *elem)
7740 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7741 return strcmp (key, method_name);
7745 find_method_icall (const IcallTypeDesc *imap, const char *name)
7747 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);
7750 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7754 compare_class_imap (const void *key, const void *elem)
7756 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7757 return strcmp (key, class_name);
7760 static const IcallTypeDesc*
7761 find_class_icalls (const char *name)
7763 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);
7766 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7769 #else /* HAVE_ARRAY_ELEM_INIT */
7772 compare_method_imap (const void *key, const void *elem)
7774 const char** method_name = (const char**)elem;
7775 return strcmp (key, *method_name);
7779 find_method_icall (const IcallTypeDesc *imap, const char *name)
7781 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7784 return (gpointer)icall_functions [(nameslot - icall_names)];
7788 compare_class_imap (const void *key, const void *elem)
7790 const char** class_name = (const char**)elem;
7791 return strcmp (key, *class_name);
7794 static const IcallTypeDesc*
7795 find_class_icalls (const char *name)
7797 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7800 return &icall_type_descs [nameslot - icall_type_names];
7803 #endif /* HAVE_ARRAY_ELEM_INIT */
7805 #endif /* DISABLE_ICALL_TABLES */
7808 * we should probably export this as an helper (handle nested types).
7809 * Returns the number of chars written in buf.
7812 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7814 int nspacelen, cnamelen;
7815 nspacelen = strlen (klass->name_space);
7816 cnamelen = strlen (klass->name);
7817 if (nspacelen + cnamelen + 2 > bufsize)
7820 memcpy (buf, klass->name_space, nspacelen);
7821 buf [nspacelen ++] = '.';
7823 memcpy (buf + nspacelen, klass->name, cnamelen);
7824 buf [nspacelen + cnamelen] = 0;
7825 return nspacelen + cnamelen;
7828 #ifdef DISABLE_ICALL_TABLES
7830 no_icall_table (void)
7832 g_assert_not_reached ();
7837 mono_lookup_internal_call (MonoMethod *method)
7842 int typelen = 0, mlen, siglen;
7844 #ifndef DISABLE_ICALL_TABLES
7845 const IcallTypeDesc *imap = NULL;
7848 g_assert (method != NULL);
7850 if (method->is_inflated)
7851 method = ((MonoMethodInflated *) method)->declaring;
7853 if (method->klass->nested_in) {
7854 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7858 mname [pos++] = '/';
7861 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7867 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7872 #ifndef DISABLE_ICALL_TABLES
7873 imap = find_class_icalls (mname);
7876 mname [typelen] = ':';
7877 mname [typelen + 1] = ':';
7879 mlen = strlen (method->name);
7880 memcpy (mname + typelen + 2, method->name, mlen);
7881 sigstart = mname + typelen + 2 + mlen;
7884 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7885 siglen = strlen (tmpsig);
7886 if (typelen + mlen + siglen + 6 > sizeof (mname))
7889 memcpy (sigstart + 1, tmpsig, siglen);
7890 sigstart [siglen + 1] = ')';
7891 sigstart [siglen + 2] = 0;
7896 res = g_hash_table_lookup (icall_hash, mname);
7898 mono_icall_unlock ();;
7901 /* try without signature */
7903 res = g_hash_table_lookup (icall_hash, mname);
7905 mono_icall_unlock ();
7909 #ifdef DISABLE_ICALL_TABLES
7910 mono_icall_unlock ();
7911 /* Fail only when the result is actually used */
7912 /* mono_marshal_get_native_wrapper () depends on this */
7913 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
7914 return ves_icall_System_String_ctor_RedirectToCreateString;
7916 return no_icall_table;
7918 /* it wasn't found in the static call tables */
7920 mono_icall_unlock ();
7923 res = find_method_icall (imap, sigstart - mlen);
7925 mono_icall_unlock ();
7928 /* try _with_ signature */
7930 res = find_method_icall (imap, sigstart - mlen);
7932 mono_icall_unlock ();
7936 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7937 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7938 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7939 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
7940 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");
7941 g_print ("If you see other errors or faults after this message they are probably related\n");
7942 g_print ("and you need to fix your mono install first.\n");
7944 mono_icall_unlock ();
7950 #ifdef ENABLE_ICALL_SYMBOL_MAP
7952 func_cmp (gconstpointer key, gconstpointer p)
7954 return (gsize)key - (gsize)*(gsize*)p;
7959 * mono_lookup_icall_symbol:
7961 * Given the icall METHOD, returns its C symbol.
7964 mono_lookup_icall_symbol (MonoMethod *m)
7966 #ifdef DISABLE_ICALL_TABLES
7967 g_assert_not_reached ();
7970 #ifdef ENABLE_ICALL_SYMBOL_MAP
7974 static gconstpointer *functions_sorted;
7975 static const char**symbols_sorted;
7976 static gboolean inited;
7981 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7982 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7983 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7984 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7985 /* Bubble sort the two arrays */
7989 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
7990 if (functions_sorted [i] > functions_sorted [i + 1]) {
7993 tmp = functions_sorted [i];
7994 functions_sorted [i] = functions_sorted [i + 1];
7995 functions_sorted [i + 1] = tmp;
7996 tmp = symbols_sorted [i];
7997 symbols_sorted [i] = symbols_sorted [i + 1];
7998 symbols_sorted [i + 1] = tmp;
8005 func = mono_lookup_internal_call (m);
8008 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8012 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8014 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8015 g_assert_not_reached ();
8022 type_from_typename (char *type_name)
8024 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8026 if (!strcmp (type_name, "int"))
8027 klass = mono_defaults.int_class;
8028 else if (!strcmp (type_name, "ptr"))
8029 klass = mono_defaults.int_class;
8030 else if (!strcmp (type_name, "void"))
8031 klass = mono_defaults.void_class;
8032 else if (!strcmp (type_name, "int32"))
8033 klass = mono_defaults.int32_class;
8034 else if (!strcmp (type_name, "uint32"))
8035 klass = mono_defaults.uint32_class;
8036 else if (!strcmp (type_name, "int8"))
8037 klass = mono_defaults.sbyte_class;
8038 else if (!strcmp (type_name, "uint8"))
8039 klass = mono_defaults.byte_class;
8040 else if (!strcmp (type_name, "int16"))
8041 klass = mono_defaults.int16_class;
8042 else if (!strcmp (type_name, "uint16"))
8043 klass = mono_defaults.uint16_class;
8044 else if (!strcmp (type_name, "long"))
8045 klass = mono_defaults.int64_class;
8046 else if (!strcmp (type_name, "ulong"))
8047 klass = mono_defaults.uint64_class;
8048 else if (!strcmp (type_name, "float"))
8049 klass = mono_defaults.single_class;
8050 else if (!strcmp (type_name, "double"))
8051 klass = mono_defaults.double_class;
8052 else if (!strcmp (type_name, "object"))
8053 klass = mono_defaults.object_class;
8054 else if (!strcmp (type_name, "obj"))
8055 klass = mono_defaults.object_class;
8056 else if (!strcmp (type_name, "string"))
8057 klass = mono_defaults.string_class;
8058 else if (!strcmp (type_name, "bool"))
8059 klass = mono_defaults.boolean_class;
8060 else if (!strcmp (type_name, "boolean"))
8061 klass = mono_defaults.boolean_class;
8063 g_error ("%s", type_name);
8064 g_assert_not_reached ();
8066 return &klass->byval_arg;
8070 * LOCKING: Take the corlib image lock.
8072 MonoMethodSignature*
8073 mono_create_icall_signature (const char *sigstr)
8078 MonoMethodSignature *res, *res2;
8079 MonoImage *corlib = mono_defaults.corlib;
8081 mono_image_lock (corlib);
8082 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8083 mono_image_unlock (corlib);
8088 parts = g_strsplit (sigstr, " ", 256);
8097 res = mono_metadata_signature_alloc (corlib, len - 1);
8102 * Under windows, the default pinvoke calling convention is STDCALL but
8105 res->call_convention = MONO_CALL_C;
8108 res->ret = type_from_typename (parts [0]);
8109 for (i = 1; i < len; ++i) {
8110 res->params [i - 1] = type_from_typename (parts [i]);
8115 mono_image_lock (corlib);
8116 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8118 res = res2; /*Value is allocated in the image pool*/
8120 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8121 mono_image_unlock (corlib);
8127 mono_find_jit_icall_by_name (const char *name)
8129 MonoJitICallInfo *info;
8130 g_assert (jit_icall_hash_name);
8133 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8134 mono_icall_unlock ();
8139 mono_find_jit_icall_by_addr (gconstpointer addr)
8141 MonoJitICallInfo *info;
8142 g_assert (jit_icall_hash_addr);
8145 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8146 mono_icall_unlock ();
8152 * mono_get_jit_icall_info:
8154 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8155 * caller should access it while holding the icall lock.
8158 mono_get_jit_icall_info (void)
8160 return jit_icall_hash_name;
8164 * mono_lookup_jit_icall_symbol:
8166 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8169 mono_lookup_jit_icall_symbol (const char *name)
8171 MonoJitICallInfo *info;
8172 const char *res = NULL;
8175 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8177 res = info->c_symbol;
8178 mono_icall_unlock ();
8183 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8186 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8187 mono_icall_unlock ();
8191 * 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
8192 * icalls without wrappers in some cases.
8195 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8197 MonoJitICallInfo *info;
8204 if (!jit_icall_hash_name) {
8205 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8206 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8209 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8210 g_warning ("jit icall already defined \"%s\"\n", name);
8211 g_assert_not_reached ();
8214 info = g_new0 (MonoJitICallInfo, 1);
8219 info->c_symbol = c_symbol;
8220 info->no_raise = no_raise;
8223 info->wrapper = func;
8225 info->wrapper = NULL;
8228 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8229 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8231 mono_icall_unlock ();
8236 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8238 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);