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)
1619 gboolean found = FALSE;
1626 klass = handle->parent;
1628 klass = mono_class_from_mono_type (type);
1630 /* Check that the field belongs to the class */
1631 for (k = klass; k; k = k->parent) {
1632 if (k == handle->parent) {
1639 /* The managed code will throw the exception */
1643 return mono_field_get_object (mono_domain_get (), klass, handle);
1646 ICALL_EXPORT MonoArray*
1647 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1650 MonoType *type = mono_field_get_type_checked (field->field, &error);
1651 if (!mono_error_ok (&error)) {
1652 mono_error_set_pending_exception (&error);
1656 return type_array_from_modifiers (field->field->parent->image, type, optional);
1660 vell_icall_get_method_attributes (MonoMethod *method)
1662 return method->flags;
1666 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1669 MonoReflectionType *rt;
1670 MonoDomain *domain = mono_domain_get ();
1671 MonoMethodSignature* sig;
1673 sig = mono_method_signature_checked (method, &error);
1674 if (!mono_error_ok (&error)) {
1675 mono_error_set_pending_exception (&error);
1679 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1680 if (!mono_error_ok (&error)) {
1681 mono_error_set_pending_exception (&error);
1685 MONO_STRUCT_SETREF (info, parent, rt);
1687 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1688 if (!mono_error_ok (&error)) {
1689 mono_error_set_pending_exception (&error);
1693 MONO_STRUCT_SETREF (info, ret, rt);
1695 info->attrs = method->flags;
1696 info->implattrs = method->iflags;
1697 if (sig->call_convention == MONO_CALL_DEFAULT)
1698 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1700 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1705 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1708 ICALL_EXPORT MonoArray*
1709 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1711 MonoDomain *domain = mono_domain_get ();
1713 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1716 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1717 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1719 MonoDomain *domain = mono_domain_get ();
1720 MonoReflectionMarshalAsAttribute* res = NULL;
1721 MonoMarshalSpec **mspecs;
1724 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1725 mono_method_get_marshal_info (method, mspecs);
1728 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1730 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1732 mono_metadata_free_marshal_spec (mspecs [i]);
1739 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1741 MonoClass *parent = field->field->parent;
1742 if (!parent->size_inited)
1743 mono_class_init (parent);
1744 mono_class_setup_fields_locking (parent);
1746 return field->field->offset - sizeof (MonoObject);
1749 ICALL_EXPORT MonoReflectionType*
1750 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1753 MonoReflectionType *ret;
1756 parent = declaring? field->field->parent: field->klass;
1758 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1759 mono_error_raise_exception (&error);
1765 ICALL_EXPORT MonoObject *
1766 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1768 MonoClass *fklass = field->klass;
1769 MonoClassField *cf = field->field;
1770 MonoDomain *domain = mono_object_domain (field);
1772 if (fklass->image->assembly->ref_only) {
1773 mono_set_pending_exception (mono_get_exception_invalid_operation (
1774 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1778 if (mono_security_core_clr_enabled ())
1779 mono_security_core_clr_ensure_reflection_access_field (cf);
1781 return mono_field_get_value_object (domain, cf, obj);
1785 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1788 MonoClassField *cf = field->field;
1792 if (field->klass->image->assembly->ref_only) {
1793 mono_set_pending_exception (mono_get_exception_invalid_operation (
1794 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1798 if (mono_security_core_clr_enabled ())
1799 mono_security_core_clr_ensure_reflection_access_field (cf);
1801 type = mono_field_get_type_checked (cf, &error);
1802 if (!mono_error_ok (&error)) {
1803 mono_error_set_pending_exception (&error);
1807 v = (gchar *) value;
1809 switch (type->type) {
1812 case MONO_TYPE_BOOLEAN:
1815 case MONO_TYPE_CHAR:
1824 case MONO_TYPE_VALUETYPE:
1827 v += sizeof (MonoObject);
1829 case MONO_TYPE_STRING:
1830 case MONO_TYPE_OBJECT:
1831 case MONO_TYPE_CLASS:
1832 case MONO_TYPE_ARRAY:
1833 case MONO_TYPE_SZARRAY:
1836 case MONO_TYPE_GENERICINST: {
1837 MonoGenericClass *gclass = type->data.generic_class;
1838 g_assert (!gclass->context.class_inst->is_open);
1840 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1841 MonoClass *nklass = mono_class_from_mono_type (type);
1842 MonoObject *nullable;
1845 * Convert the boxed vtype into a Nullable structure.
1846 * This is complicated by the fact that Nullables have
1847 * a variable structure.
1849 nullable = mono_object_new (mono_domain_get (), nklass);
1851 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1853 v = (gchar *)mono_object_unbox (nullable);
1856 if (gclass->container_class->valuetype && (v != NULL))
1857 v += sizeof (MonoObject);
1861 g_error ("type 0x%x not handled in "
1862 "ves_icall_FieldInfo_SetValueInternal", type->type);
1867 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1868 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1869 if (!vtable->initialized)
1870 mono_runtime_class_init (vtable);
1871 mono_field_static_set_value (vtable, cf, v);
1873 mono_field_set_value (obj, cf, v);
1878 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1887 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1888 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1892 if (MONO_TYPE_IS_REFERENCE (f->type))
1893 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1895 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1898 ICALL_EXPORT MonoObject *
1899 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1901 MonoObject *o = NULL;
1902 MonoClassField *field = rfield->field;
1904 MonoDomain *domain = mono_object_domain (rfield);
1906 MonoTypeEnum def_type;
1907 const char *def_value;
1911 mono_class_init (field->parent);
1913 t = mono_field_get_type_checked (field, &error);
1914 if (!mono_error_ok (&error)) {
1915 mono_error_set_pending_exception (&error);
1919 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
1920 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1924 if (image_is_dynamic (field->parent->image)) {
1925 MonoClass *klass = field->parent;
1926 int fidx = field - klass->fields;
1928 g_assert (fidx >= 0 && fidx < klass->field.count);
1929 g_assert (klass->ext);
1930 g_assert (klass->ext->field_def_values);
1931 def_type = klass->ext->field_def_values [fidx].def_type;
1932 def_value = klass->ext->field_def_values [fidx].data;
1933 if (def_type == MONO_TYPE_END) {
1934 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1938 def_value = mono_class_get_field_default_value (field, &def_type);
1939 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
1941 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1946 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1950 case MONO_TYPE_BOOLEAN:
1953 case MONO_TYPE_CHAR:
1961 case MONO_TYPE_R8: {
1964 /* boxed value type */
1965 t = g_new0 (MonoType, 1);
1967 klass = mono_class_from_mono_type (t);
1969 o = mono_object_new (domain, klass);
1970 v = ((gchar *) o) + sizeof (MonoObject);
1971 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1974 case MONO_TYPE_STRING:
1975 case MONO_TYPE_CLASS:
1976 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1979 g_assert_not_reached ();
1985 ICALL_EXPORT MonoReflectionType*
1986 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1989 MonoReflectionType *ret;
1992 type = mono_field_get_type_checked (ref_field->field, &error);
1993 if (!mono_error_ok (&error)) {
1994 mono_error_set_pending_exception (&error);
1998 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
1999 if (!mono_error_ok (&error)) {
2000 mono_error_set_pending_exception (&error);
2007 /* From MonoProperty.cs */
2009 PInfo_Attributes = 1,
2010 PInfo_GetMethod = 1 << 1,
2011 PInfo_SetMethod = 1 << 2,
2012 PInfo_ReflectedType = 1 << 3,
2013 PInfo_DeclaringType = 1 << 4,
2018 ves_icall_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2021 MonoReflectionType *rt;
2022 MonoDomain *domain = mono_object_domain (property);
2023 const MonoProperty *pproperty = property->property;
2025 if ((req_info & PInfo_ReflectedType) != 0) {
2026 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2027 mono_error_raise_exception (&error);
2029 MONO_STRUCT_SETREF (info, parent, rt);
2031 if ((req_info & PInfo_DeclaringType) != 0) {
2032 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2033 mono_error_raise_exception (&error);
2035 MONO_STRUCT_SETREF (info, declaring_type, rt);
2038 if ((req_info & PInfo_Name) != 0)
2039 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2041 if ((req_info & PInfo_Attributes) != 0)
2042 info->attrs = pproperty->attrs;
2044 if ((req_info & PInfo_GetMethod) != 0)
2045 MONO_STRUCT_SETREF (info, get, pproperty->get &&
2046 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) || pproperty->get->klass == property->klass) ?
2047 mono_method_get_object (domain, pproperty->get, property->klass): NULL);
2048 if ((req_info & PInfo_SetMethod) != 0)
2049 MONO_STRUCT_SETREF (info, set, pproperty->set &&
2050 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) || pproperty->set->klass == property->klass) ?
2051 mono_method_get_object (domain, pproperty->set, property->klass): NULL);
2053 * There may be other methods defined for properties, though, it seems they are not exposed
2054 * in the reflection API
2059 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2062 MonoReflectionType *rt;
2063 MonoDomain *domain = mono_object_domain (event);
2065 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2066 mono_error_raise_exception (&error);
2068 MONO_STRUCT_SETREF (info, reflected_type, rt);
2070 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2071 mono_error_raise_exception (&error);
2073 MONO_STRUCT_SETREF (info, declaring_type, rt);
2075 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2076 info->attrs = event->event->attrs;
2077 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2078 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2079 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2081 #ifndef MONO_SMALL_CONFIG
2082 if (event->event->other) {
2084 while (event->event->other [n])
2086 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2088 for (i = 0; i < n; i++)
2089 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2095 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2100 mono_class_setup_interfaces (klass, error);
2101 if (!mono_error_ok (error))
2104 for (i = 0; i < klass->interface_count; i++) {
2105 ic = klass->interfaces [i];
2106 g_hash_table_insert (ifaces, ic, ic);
2108 collect_interfaces (ic, ifaces, error);
2109 if (!mono_error_ok (error))
2115 MonoArray *iface_array;
2116 MonoGenericContext *context;
2120 } FillIfaceArrayData;
2123 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2125 MonoReflectionType *rt;
2126 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2127 MonoClass *ic = (MonoClass *)key;
2128 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2130 if (!mono_error_ok (data->error))
2133 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2134 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2135 if (!mono_error_ok (data->error))
2139 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2140 if (!mono_error_ok (data->error))
2143 mono_array_setref (data->iface_array, data->next_idx++, rt);
2146 mono_metadata_free_type (inflated);
2150 get_interfaces_hash (gconstpointer v1)
2152 MonoClass *k = (MonoClass*)v1;
2154 return k->type_token;
2157 ICALL_EXPORT MonoArray*
2158 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2161 MonoClass *klass = mono_class_from_mono_type (type->type);
2163 FillIfaceArrayData data = { 0 };
2166 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2168 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2169 data.context = mono_class_get_context (klass);
2170 klass = klass->generic_class->container_class;
2173 for (parent = klass; parent; parent = parent->parent) {
2174 mono_class_setup_interfaces (parent, &error);
2175 if (!mono_error_ok (&error))
2177 collect_interfaces (parent, iface_hash, &error);
2178 if (!mono_error_ok (&error))
2182 data.error = &error;
2183 data.domain = mono_object_domain (type);
2185 len = g_hash_table_size (iface_hash);
2187 g_hash_table_destroy (iface_hash);
2188 if (!data.domain->empty_types)
2189 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2190 return data.domain->empty_types;
2193 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2194 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2195 if (!mono_error_ok (&error))
2198 g_hash_table_destroy (iface_hash);
2199 return data.iface_array;
2202 g_hash_table_destroy (iface_hash);
2203 mono_error_set_pending_exception (&error);
2208 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2210 gboolean variance_used;
2211 MonoClass *klass = mono_class_from_mono_type (type->type);
2212 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2213 MonoReflectionMethod *member;
2216 int i = 0, len, ioffset;
2219 mono_class_init_or_throw (klass);
2220 mono_class_init_or_throw (iclass);
2222 mono_class_setup_vtable (klass);
2224 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2228 len = mono_class_num_methods (iclass);
2229 domain = mono_object_domain (type);
2230 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2231 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2233 while ((method = mono_class_get_methods (iclass, &iter))) {
2234 member = mono_method_get_object (domain, method, iclass);
2235 mono_array_setref (*methods, i, member);
2236 member = mono_method_get_object (domain, klass->vtable [i + ioffset], klass);
2237 mono_array_setref (*targets, i, member);
2244 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2246 MonoClass *klass = mono_class_from_mono_type (type->type);
2247 mono_class_init_or_throw (klass);
2249 if (image_is_dynamic (klass->image)) {
2250 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2251 *packing = tb->packing_size;
2252 *size = tb->class_size;
2254 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2258 ICALL_EXPORT MonoReflectionType*
2259 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2262 MonoReflectionType *ret;
2265 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2266 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2267 mono_error_raise_exception (&error);
2272 klass = mono_class_from_mono_type (type->type);
2273 mono_class_init_or_throw (klass);
2275 // GetElementType should only return a type for:
2276 // Array Pointer PassedByRef
2277 if (type->type->byref)
2278 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2279 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2280 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2281 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2282 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2286 mono_error_raise_exception (&error);
2291 ICALL_EXPORT MonoReflectionType*
2292 ves_icall_get_type_parent (MonoReflectionType *type)
2295 MonoReflectionType *ret;
2297 if (type->type->byref)
2300 MonoClass *klass = mono_class_from_mono_type (type->type);
2304 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2305 mono_error_raise_exception (&error);
2310 ICALL_EXPORT MonoBoolean
2311 ves_icall_type_ispointer (MonoReflectionType *type)
2313 return type->type->type == MONO_TYPE_PTR;
2316 ICALL_EXPORT MonoBoolean
2317 ves_icall_type_isprimitive (MonoReflectionType *type)
2319 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)));
2322 ICALL_EXPORT MonoBoolean
2323 ves_icall_type_isbyref (MonoReflectionType *type)
2325 return type->type->byref;
2328 ICALL_EXPORT MonoBoolean
2329 ves_icall_type_iscomobject (MonoReflectionType *type)
2331 MonoClass *klass = mono_class_from_mono_type (type->type);
2332 mono_class_init_or_throw (klass);
2334 return mono_class_is_com_object (klass);
2337 ICALL_EXPORT MonoReflectionModule*
2338 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2340 MonoClass *klass = mono_class_from_mono_type (type->type);
2341 return mono_module_get_object (mono_object_domain (type), klass->image);
2344 ICALL_EXPORT MonoReflectionAssembly*
2345 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2347 MonoDomain *domain = mono_domain_get ();
2348 MonoClass *klass = mono_class_from_mono_type (type->type);
2349 return mono_assembly_get_object (domain, klass->image->assembly);
2352 ICALL_EXPORT MonoReflectionType*
2353 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2356 MonoReflectionType *ret;
2357 MonoDomain *domain = mono_domain_get ();
2360 if (type->type->byref)
2362 if (type->type->type == MONO_TYPE_VAR) {
2363 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2364 klass = param ? param->owner.klass : NULL;
2365 } else if (type->type->type == MONO_TYPE_MVAR) {
2366 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2367 klass = param ? param->owner.method->klass : NULL;
2369 klass = mono_class_from_mono_type (type->type)->nested_in;
2375 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2376 mono_error_raise_exception (&error);
2381 ICALL_EXPORT MonoString*
2382 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2384 MonoDomain *domain = mono_domain_get ();
2385 MonoClass *klass = mono_class_from_mono_type (type->type);
2387 if (type->type->byref) {
2388 char *n = g_strdup_printf ("%s&", klass->name);
2389 MonoString *res = mono_string_new (domain, n);
2395 return mono_string_new (domain, klass->name);
2399 ICALL_EXPORT MonoString*
2400 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2402 MonoDomain *domain = mono_domain_get ();
2403 MonoClass *klass = mono_class_from_mono_type (type->type);
2405 while (klass->nested_in)
2406 klass = klass->nested_in;
2408 if (klass->name_space [0] == '\0')
2411 return mono_string_new (domain, klass->name_space);
2415 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2419 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2420 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2424 klass = mono_class_from_mono_type (type->type);
2430 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2433 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2437 ICALL_EXPORT MonoArray*
2438 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2441 MonoReflectionType *rt;
2443 MonoClass *klass, *pklass;
2444 MonoDomain *domain = mono_object_domain (type);
2447 klass = mono_class_from_mono_type (type->type);
2449 if (klass->generic_container) {
2450 MonoGenericContainer *container = klass->generic_container;
2451 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2452 for (i = 0; i < container->type_argc; ++i) {
2453 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2455 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2456 mono_error_raise_exception (&error);
2458 mono_array_setref (res, i, rt);
2460 } else if (klass->generic_class) {
2461 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2462 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2463 for (i = 0; i < inst->type_argc; ++i) {
2464 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2465 mono_error_raise_exception (&error);
2467 mono_array_setref (res, i, rt);
2475 ICALL_EXPORT gboolean
2476 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2480 if (!IS_MONOTYPE (type))
2483 if (type->type->byref)
2486 klass = mono_class_from_mono_type (type->type);
2487 return klass->generic_container != NULL;
2490 ICALL_EXPORT MonoReflectionType*
2491 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2494 MonoReflectionType *ret;
2497 if (type->type->byref)
2500 klass = mono_class_from_mono_type (type->type);
2502 if (klass->generic_container) {
2503 return type; /* check this one */
2505 if (klass->generic_class) {
2506 MonoClass *generic_class = klass->generic_class->container_class;
2509 tb = mono_class_get_ref_info (generic_class);
2511 if (generic_class->wastypebuilder && tb)
2512 return (MonoReflectionType *)tb;
2514 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2515 mono_error_raise_exception (&error);
2523 ICALL_EXPORT MonoReflectionType*
2524 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2527 MonoReflectionType *ret;
2529 MonoType *geninst, **types;
2532 g_assert (IS_MONOTYPE (type));
2533 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2535 count = mono_array_length (type_array);
2536 types = g_new0 (MonoType *, count);
2538 for (i = 0; i < count; i++) {
2539 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2540 types [i] = t->type;
2543 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2548 klass = mono_class_from_mono_type (geninst);
2550 /*we might inflate to the GTD*/
2551 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2552 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2556 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2557 mono_error_raise_exception (&error);
2562 ICALL_EXPORT gboolean
2563 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2567 if (!IS_MONOTYPE (type))
2570 if (type->type->byref)
2573 klass = mono_class_from_mono_type (type->type);
2574 return klass->generic_class != NULL || klass->generic_container != NULL;
2578 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2580 if (!IS_MONOTYPE (type))
2583 if (is_generic_parameter (type->type))
2584 return mono_type_get_generic_param_num (type->type);
2588 ICALL_EXPORT GenericParameterAttributes
2589 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2591 g_assert (IS_MONOTYPE (type));
2592 g_assert (is_generic_parameter (type->type));
2593 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2596 ICALL_EXPORT MonoArray *
2597 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2600 MonoReflectionType *rt;
2601 MonoGenericParamInfo *param_info;
2607 g_assert (IS_MONOTYPE (type));
2609 domain = mono_object_domain (type);
2610 param_info = mono_generic_param_info (type->type->data.generic_param);
2611 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2614 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2615 for (i = 0; i < count; i++) {
2616 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2617 mono_error_raise_exception (&error);
2619 mono_array_setref (res, i, rt);
2626 ICALL_EXPORT MonoBoolean
2627 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2629 return is_generic_parameter (type->type);
2632 ICALL_EXPORT MonoBoolean
2633 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2635 return is_generic_parameter (tb->type.type);
2639 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2640 MonoReflectionType *t)
2642 enumtype->type = t->type;
2645 ICALL_EXPORT MonoReflectionMethod*
2646 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2647 MonoReflectionMethod* generic)
2654 domain = ((MonoObject *)type)->vtable->domain;
2656 klass = mono_class_from_mono_type (type->type);
2657 mono_class_init_or_throw (klass);
2660 while ((method = mono_class_get_methods (klass, &iter))) {
2661 if (method->token == generic->method->token)
2662 return mono_method_get_object (domain, method, klass);
2668 ICALL_EXPORT MonoReflectionMethod *
2669 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2672 MonoType *type = ref_type->type;
2674 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2675 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2678 if (type->type == MONO_TYPE_VAR)
2681 method = mono_type_get_generic_param_owner (type)->owner.method;
2683 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2686 ICALL_EXPORT MonoBoolean
2687 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2689 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2693 ICALL_EXPORT MonoBoolean
2694 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2696 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2701 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2703 MonoDomain *domain = mono_domain_get ();
2704 MonoImage *image = method->method->klass->image;
2705 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2706 MonoTableInfo *tables = image->tables;
2707 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2708 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2709 guint32 im_cols [MONO_IMPLMAP_SIZE];
2710 guint32 scope_token;
2711 const char *import = NULL;
2712 const char *scope = NULL;
2714 if (image_is_dynamic (image)) {
2715 MonoReflectionMethodAux *method_aux =
2716 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2718 import = method_aux->dllentry;
2719 scope = method_aux->dll;
2722 if (!import || !scope) {
2723 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2728 if (piinfo->implmap_idx) {
2729 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2731 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2732 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2733 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2734 scope = mono_metadata_string_heap (image, scope_token);
2738 *flags = piinfo->piflags;
2739 *entry_point = mono_string_new (domain, import);
2740 *dll_name = mono_string_new (domain, scope);
2743 ICALL_EXPORT MonoReflectionMethod *
2744 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2746 MonoMethodInflated *imethod;
2749 if (method->method->is_generic)
2752 if (!method->method->is_inflated)
2755 imethod = (MonoMethodInflated *) method->method;
2757 result = imethod->declaring;
2758 /* Not a generic method. */
2759 if (!result->is_generic)
2762 if (image_is_dynamic (method->method->klass->image)) {
2763 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2764 MonoReflectionMethod *res;
2767 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2768 * the dynamic case as well ?
2770 mono_image_lock ((MonoImage*)image);
2771 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2772 mono_image_unlock ((MonoImage*)image);
2778 if (imethod->context.class_inst) {
2779 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2780 /*Generic methods gets the context of the GTD.*/
2781 if (mono_class_get_context (klass)) {
2783 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2784 if (!mono_error_ok (&error)) {
2785 mono_error_set_pending_exception (&error);
2791 return mono_method_get_object (mono_object_domain (method), result, NULL);
2794 ICALL_EXPORT gboolean
2795 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2797 return mono_method_signature (method->method)->generic_param_count != 0;
2800 ICALL_EXPORT gboolean
2801 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2803 return method->method->is_generic;
2806 ICALL_EXPORT MonoArray*
2807 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2810 MonoReflectionType *rt;
2815 domain = mono_object_domain (method);
2817 if (method->method->is_inflated) {
2818 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2821 count = inst->type_argc;
2822 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2824 for (i = 0; i < count; i++) {
2825 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2826 mono_error_raise_exception (&error);
2828 mono_array_setref (res, i, rt);
2835 count = mono_method_signature (method->method)->generic_param_count;
2836 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2838 for (i = 0; i < count; i++) {
2839 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2840 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2841 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
2843 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2844 mono_error_raise_exception (&error);
2846 mono_array_setref (res, i, rt);
2852 ICALL_EXPORT MonoObject *
2853 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
2857 * Invoke from reflection is supposed to always be a virtual call (the API
2858 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2859 * greater flexibility.
2861 MonoMethod *m = method->method;
2862 MonoMethodSignature *sig = mono_method_signature (m);
2865 void *obj = this_arg;
2869 if (mono_security_core_clr_enabled ())
2870 mono_security_core_clr_ensure_reflection_access_method (m);
2872 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2873 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2874 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2879 if (!mono_object_isinst (this_arg, m->klass)) {
2880 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
2881 char *target_name = mono_type_get_full_name (m->klass);
2882 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2883 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2885 g_free (target_name);
2889 m = mono_object_get_virtual_method (this_arg, m);
2890 /* must pass the pointer to the value for valuetype methods */
2891 if (m->klass->valuetype)
2892 obj = mono_object_unbox (this_arg);
2893 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2894 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2899 if (sig->ret->byref) {
2900 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"));
2904 pcount = params? mono_array_length (params): 0;
2905 if (pcount != sig->param_count) {
2906 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2910 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
2911 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."));
2915 image = m->klass->image;
2916 if (image->assembly->ref_only) {
2917 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."));
2921 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
2922 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2926 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2930 intptr_t *lower_bounds;
2931 pcount = mono_array_length (params);
2932 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
2933 /* Note: the synthetized array .ctors have int32 as argument type */
2934 for (i = 0; i < pcount; ++i)
2935 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2937 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
2938 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
2939 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
2940 if (!mono_error_ok (&error)) {
2941 mono_error_set_pending_exception (&error);
2945 for (i = 0; i < mono_array_length (arr); ++i) {
2946 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
2947 if (!mono_error_ok (&error)) {
2948 mono_error_set_pending_exception (&error);
2951 mono_array_setref_fast (arr, i, subarray);
2953 return (MonoObject*)arr;
2956 if (m->klass->rank == pcount) {
2957 /* Only lengths provided. */
2958 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
2959 if (!mono_error_ok (&error)) {
2960 mono_error_set_pending_exception (&error);
2964 return (MonoObject*)arr;
2966 g_assert (pcount == (m->klass->rank * 2));
2967 /* The arguments are lower-bound-length pairs */
2968 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
2970 for (i = 0; i < pcount / 2; ++i) {
2971 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
2972 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
2975 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
2976 if (!mono_error_ok (&error)) {
2977 mono_error_set_pending_exception (&error);
2981 return (MonoObject*)arr;
2984 return mono_runtime_invoke_array (m, obj, params, NULL);
2987 #ifndef DISABLE_REMOTING
2988 ICALL_EXPORT MonoObject *
2989 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
2991 MonoDomain *domain = mono_object_domain (method);
2992 MonoMethod *m = method->method;
2993 MonoMethodSignature *sig = mono_method_signature (m);
2994 MonoArray *out_args;
2996 int i, j, outarg_count = 0;
2998 if (m->klass == mono_defaults.object_class) {
2999 if (!strcmp (m->name, "FieldGetter")) {
3000 MonoClass *k = this_arg->vtable->klass;
3004 /* If this is a proxy, then it must be a CBO */
3005 if (k == mono_defaults.transparent_proxy_class) {
3006 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3007 this_arg = tp->rp->unwrapped_server;
3008 g_assert (this_arg);
3009 k = this_arg->vtable->klass;
3012 name = mono_array_get (params, MonoString *, 1);
3013 str = mono_string_to_utf8 (name);
3016 MonoClassField* field = mono_class_get_field_from_name (k, str);
3018 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3019 if (field_klass->valuetype)
3020 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
3022 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3024 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3025 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3026 mono_array_setref (out_args, 0, result);
3034 g_assert_not_reached ();
3036 } else if (!strcmp (m->name, "FieldSetter")) {
3037 MonoClass *k = this_arg->vtable->klass;
3043 /* If this is a proxy, then it must be a CBO */
3044 if (k == mono_defaults.transparent_proxy_class) {
3045 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3046 this_arg = tp->rp->unwrapped_server;
3047 g_assert (this_arg);
3048 k = this_arg->vtable->klass;
3051 name = mono_array_get (params, MonoString *, 1);
3052 str = mono_string_to_utf8 (name);
3055 MonoClassField* field = mono_class_get_field_from_name (k, str);
3057 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3058 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3060 if (field_klass->valuetype) {
3061 size = mono_type_size (field->type, &align);
3062 g_assert (size == mono_class_value_size (field_klass, NULL));
3063 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3065 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3068 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3069 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3079 g_assert_not_reached ();
3084 for (i = 0; i < mono_array_length (params); i++) {
3085 if (sig->params [i]->byref)
3089 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3091 /* handle constructors only for objects already allocated */
3092 if (!strcmp (method->method->name, ".ctor"))
3093 g_assert (this_arg);
3095 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3096 g_assert (!method->method->klass->valuetype);
3097 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3099 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3100 if (sig->params [i]->byref) {
3102 arg = mono_array_get (params, gpointer, i);
3103 mono_array_setref (out_args, j, arg);
3108 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3115 read_enum_value (const char *mem, int type)
3118 case MONO_TYPE_BOOLEAN:
3120 return *(guint8*)mem;
3122 return *(gint8*)mem;
3123 case MONO_TYPE_CHAR:
3125 return read16 (mem);
3127 return (gint16) read16 (mem);
3129 return read32 (mem);
3131 return (gint32) read32 (mem);
3134 return read64 (mem);
3136 g_assert_not_reached ();
3142 write_enum_value (char *mem, int type, guint64 value)
3146 case MONO_TYPE_I1: {
3147 guint8 *p = (guint8*)mem;
3152 case MONO_TYPE_I2: {
3153 guint16 *p = (guint16 *)mem;
3158 case MONO_TYPE_I4: {
3159 guint32 *p = (guint32 *)mem;
3164 case MONO_TYPE_I8: {
3165 guint64 *p = (guint64 *)mem;
3170 g_assert_not_reached ();
3175 ICALL_EXPORT MonoObject *
3176 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3183 domain = mono_object_domain (enumType);
3184 enumc = mono_class_from_mono_type (enumType->type);
3186 mono_class_init_or_throw (enumc);
3188 etype = mono_class_enum_basetype (enumc);
3190 res = mono_object_new (domain, enumc);
3191 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3196 ICALL_EXPORT MonoBoolean
3197 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3199 int size = mono_class_value_size (a->vtable->klass, NULL);
3200 guint64 a_val = 0, b_val = 0;
3202 memcpy (&a_val, mono_object_unbox (a), size);
3203 memcpy (&b_val, mono_object_unbox (b), size);
3205 return (a_val & b_val) == b_val;
3208 ICALL_EXPORT MonoObject *
3209 ves_icall_System_Enum_get_value (MonoObject *eobj)
3220 g_assert (eobj->vtable->klass->enumtype);
3222 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3223 res = mono_object_new (mono_object_domain (eobj), enumc);
3224 dst = (char *)res + sizeof (MonoObject);
3225 src = (char *)eobj + sizeof (MonoObject);
3226 size = mono_class_value_size (enumc, NULL);
3228 memcpy (dst, src, size);
3233 ICALL_EXPORT MonoReflectionType *
3234 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3237 MonoReflectionType *ret;
3241 klass = mono_class_from_mono_type (type->type);
3242 mono_class_init_or_throw (klass);
3244 etype = mono_class_enum_basetype (klass);
3246 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3250 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3251 mono_error_raise_exception (&error);
3257 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3259 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3260 gpointer odata = (char *)other + sizeof (MonoObject);
3261 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3262 g_assert (basetype);
3267 if (eobj->vtable->klass != other->vtable->klass)
3270 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3271 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3272 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3275 return me > other ? 1 : -1; \
3278 switch (basetype->type) {
3280 COMPARE_ENUM_VALUES (guint8);
3282 COMPARE_ENUM_VALUES (gint8);
3283 case MONO_TYPE_CHAR:
3285 COMPARE_ENUM_VALUES (guint16);
3287 COMPARE_ENUM_VALUES (gint16);
3289 COMPARE_ENUM_VALUES (guint32);
3291 COMPARE_ENUM_VALUES (gint32);
3293 COMPARE_ENUM_VALUES (guint64);
3295 COMPARE_ENUM_VALUES (gint64);
3299 #undef COMPARE_ENUM_VALUES
3300 /* indicates that the enum was of an unsupported unerlying type */
3305 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3307 gpointer data = (char *)eobj + sizeof (MonoObject);
3308 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3309 g_assert (basetype);
3311 switch (basetype->type) {
3312 case MONO_TYPE_I1: {
3313 gint8 value = *((gint8*)data);
3314 return ((int)value ^ (int)value << 8);
3317 return *((guint8*)data);
3318 case MONO_TYPE_CHAR:
3320 return *((guint16*)data);
3322 case MONO_TYPE_I2: {
3323 gint16 value = *((gint16*)data);
3324 return ((int)(guint16)value | (((int)value) << 16));
3327 return *((guint32*)data);
3329 return *((gint32*)data);
3331 case MONO_TYPE_I8: {
3332 gint64 value = *((gint64*)data);
3333 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3336 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3341 ICALL_EXPORT MonoBoolean
3342 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3344 MonoDomain *domain = mono_object_domain (type);
3345 MonoClass *enumc = mono_class_from_mono_type (type->type);
3346 guint j = 0, nvalues;
3348 MonoClassField *field;
3350 guint64 field_value, previous_value = 0;
3351 gboolean sorted = TRUE;
3353 mono_class_init_or_throw (enumc);
3355 if (!enumc->enumtype) {
3356 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3360 base_type = mono_class_enum_basetype (enumc)->type;
3362 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3363 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3364 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3367 while ((field = mono_class_get_fields (enumc, &iter))) {
3369 MonoTypeEnum def_type;
3371 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3373 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3375 if (mono_field_is_deleted (field))
3377 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3379 p = mono_class_get_field_default_value (field, &def_type);
3380 /* len = */ mono_metadata_decode_blob_size (p, &p);
3382 field_value = read_enum_value (p, base_type);
3383 mono_array_set (*values, guint64, j, field_value);
3385 if (previous_value > field_value)
3388 previous_value = field_value;
3396 BFLAGS_IgnoreCase = 1,
3397 BFLAGS_DeclaredOnly = 2,
3398 BFLAGS_Instance = 4,
3400 BFLAGS_Public = 0x10,
3401 BFLAGS_NonPublic = 0x20,
3402 BFLAGS_FlattenHierarchy = 0x40,
3403 BFLAGS_InvokeMethod = 0x100,
3404 BFLAGS_CreateInstance = 0x200,
3405 BFLAGS_GetField = 0x400,
3406 BFLAGS_SetField = 0x800,
3407 BFLAGS_GetProperty = 0x1000,
3408 BFLAGS_SetProperty = 0x2000,
3409 BFLAGS_ExactBinding = 0x10000,
3410 BFLAGS_SuppressChangeType = 0x20000,
3411 BFLAGS_OptionalParamBinding = 0x40000
3414 ICALL_EXPORT MonoArray*
3415 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3418 MonoClass *startklass, *klass, *refklass;
3423 char *utf8_name = NULL;
3424 int (*compare_func) (const char *s1, const char *s2) = NULL;
3425 MonoClassField *field;
3426 MonoPtrArray tmp_array;
3428 domain = ((MonoObject *)type)->vtable->domain;
3429 if (type->type->byref)
3430 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3432 klass = startklass = mono_class_from_mono_type (type->type);
3433 refklass = mono_class_from_mono_type (reftype->type);
3435 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3438 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3439 mono_ptr_array_destroy (tmp_array);
3440 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3445 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3446 guint32 flags = mono_field_get_flags (field);
3448 if (mono_field_is_deleted_with_flags (field, flags))
3450 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3451 if (bflags & BFLAGS_Public)
3453 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3454 if (bflags & BFLAGS_NonPublic) {
3461 if (flags & FIELD_ATTRIBUTE_STATIC) {
3462 if (bflags & BFLAGS_Static)
3463 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3466 if (bflags & BFLAGS_Instance)
3474 if (utf8_name == NULL) {
3475 utf8_name = mono_string_to_utf8 (name);
3476 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3479 if (compare_func (mono_field_get_name (field), utf8_name))
3483 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3484 mono_ptr_array_append (tmp_array, member);
3486 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3489 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3491 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3492 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3494 mono_ptr_array_destroy (tmp_array);
3496 if (utf8_name != NULL)
3503 method_nonpublic (MonoMethod* method, gboolean start_klass)
3505 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3506 case METHOD_ATTRIBUTE_ASSEM:
3507 return (start_klass || mono_defaults.generic_ilist_class);
3508 case METHOD_ATTRIBUTE_PRIVATE:
3510 case METHOD_ATTRIBUTE_PUBLIC:
3518 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3521 MonoClass *startklass;
3525 /*FIXME, use MonoBitSet*/
3526 guint32 method_slots_default [8];
3527 guint32 *method_slots = NULL;
3528 int (*compare_func) (const char *s1, const char *s2) = NULL;
3530 array = g_ptr_array_new ();
3535 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3537 /* An optimization for calls made from Delegate:CreateDelegate () */
3538 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3539 method = mono_get_delegate_invoke (klass);
3540 if (mono_loader_get_last_error ())
3543 g_ptr_array_add (array, method);
3547 mono_class_setup_methods (klass);
3548 mono_class_setup_vtable (klass);
3549 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3552 if (is_generic_parameter (&klass->byval_arg))
3553 nslots = mono_class_get_vtable_size (klass->parent);
3555 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3556 if (nslots >= sizeof (method_slots_default) * 8) {
3557 method_slots = g_new0 (guint32, nslots / 32 + 1);
3559 method_slots = method_slots_default;
3560 memset (method_slots, 0, sizeof (method_slots_default));
3563 mono_class_setup_methods (klass);
3564 mono_class_setup_vtable (klass);
3565 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3569 while ((method = mono_class_get_methods (klass, &iter))) {
3571 if (method->slot != -1) {
3572 g_assert (method->slot < nslots);
3573 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3575 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3576 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3579 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3581 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3582 if (bflags & BFLAGS_Public)
3584 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3590 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3591 if (bflags & BFLAGS_Static)
3592 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3595 if (bflags & BFLAGS_Instance)
3603 if (compare_func (name, method->name))
3608 g_ptr_array_add (array, method);
3610 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3612 if (method_slots != method_slots_default)
3613 g_free (method_slots);
3618 if (method_slots != method_slots_default)
3619 g_free (method_slots);
3620 g_ptr_array_free (array, TRUE);
3622 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3623 *ex = mono_class_get_exception_for_failure (klass);
3625 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3626 mono_loader_clear_error ();
3631 ICALL_EXPORT MonoArray*
3632 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3634 static MonoClass *MethodInfo_array;
3638 MonoVTable *array_vtable;
3639 MonoException *ex = NULL;
3640 const char *mname = NULL;
3641 GPtrArray *method_array;
3642 MonoClass *klass, *refklass;
3645 if (!MethodInfo_array) {
3646 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3647 mono_memory_barrier ();
3648 MethodInfo_array = klass;
3651 klass = mono_class_from_mono_type (type->type);
3652 refklass = mono_class_from_mono_type (reftype->type);
3653 domain = ((MonoObject *)type)->vtable->domain;
3654 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3655 if (type->type->byref) {
3656 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3657 mono_error_set_pending_exception (&error);
3663 mname = mono_string_to_utf8 (name);
3665 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3666 g_free ((char*)mname);
3668 mono_set_pending_exception (ex);
3672 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3673 if (!mono_error_ok (&error)) {
3674 mono_error_set_pending_exception (&error);
3678 for (i = 0; i < method_array->len; ++i) {
3679 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3680 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3683 g_ptr_array_free (method_array, TRUE);
3687 ICALL_EXPORT MonoArray*
3688 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3691 static MonoClass *System_Reflection_ConstructorInfo;
3692 MonoClass *startklass, *klass, *refklass;
3697 gpointer iter = NULL;
3698 MonoPtrArray tmp_array;
3700 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3702 domain = ((MonoObject *)type)->vtable->domain;
3703 if (type->type->byref)
3704 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3705 klass = startklass = mono_class_from_mono_type (type->type);
3706 refklass = mono_class_from_mono_type (reftype->type);
3708 if (!System_Reflection_ConstructorInfo)
3709 System_Reflection_ConstructorInfo = mono_class_from_name (
3710 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3712 mono_class_setup_methods (klass);
3713 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3714 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3719 while ((method = mono_class_get_methods (klass, &iter))) {
3721 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3723 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3724 if (bflags & BFLAGS_Public)
3727 if (bflags & BFLAGS_NonPublic)
3733 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3734 if (bflags & BFLAGS_Static)
3735 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3738 if (bflags & BFLAGS_Instance)
3744 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3746 mono_ptr_array_append (tmp_array, member);
3749 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3751 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3752 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3754 mono_ptr_array_destroy (tmp_array);
3760 property_hash (gconstpointer data)
3762 MonoProperty *prop = (MonoProperty*)data;
3764 return g_str_hash (prop->name);
3768 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3770 if (method1->is_inflated)
3771 method1 = ((MonoMethodInflated*) method1)->declaring;
3772 if (method2->is_inflated)
3773 method2 = ((MonoMethodInflated*) method2)->declaring;
3775 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3779 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3781 // Properties are hide-by-name-and-signature
3782 if (!g_str_equal (prop1->name, prop2->name))
3785 /* If we see a property in a generic method, we want to
3786 compare the generic signatures, not the inflated signatures
3787 because we might conflate two properties that were
3791 public T this[T t] { getter { return t; } } // method 1
3792 public U this[U u] { getter { return u; } } // method 2
3795 If we see int Foo<int,int>::Item[int] we need to know if
3796 the indexer came from method 1 or from method 2, and we
3797 shouldn't conflate them. (Bugzilla 36283)
3799 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
3802 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
3809 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3814 return method_nonpublic (accessor, start_klass);
3817 ICALL_EXPORT MonoArray*
3818 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3822 static MonoClass *System_Reflection_PropertyInfo;
3823 MonoClass *startklass, *klass;
3829 gchar *propname = NULL;
3830 int (*compare_func) (const char *s1, const char *s2) = NULL;
3832 GHashTable *properties = NULL;
3833 MonoPtrArray tmp_array;
3835 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
3837 if (!System_Reflection_PropertyInfo)
3838 System_Reflection_PropertyInfo = mono_class_from_name (
3839 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3841 domain = ((MonoObject *)type)->vtable->domain;
3842 if (type->type->byref)
3843 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3844 klass = startklass = mono_class_from_mono_type (type->type);
3847 propname = mono_string_to_utf8 (name);
3848 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3851 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3853 mono_class_setup_methods (klass);
3854 mono_class_setup_vtable (klass);
3855 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3859 while ((prop = mono_class_get_properties (klass, &iter))) {
3865 flags = method->flags;
3868 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3869 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3870 if (bflags & BFLAGS_Public)
3872 } else if (bflags & BFLAGS_NonPublic) {
3873 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3874 property_accessor_nonpublic(prop->set, startklass == klass)) {
3881 if (flags & METHOD_ATTRIBUTE_STATIC) {
3882 if (bflags & BFLAGS_Static)
3883 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3886 if (bflags & BFLAGS_Instance)
3895 if (compare_func (propname, prop->name))
3899 if (g_hash_table_lookup (properties, prop))
3902 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3904 g_hash_table_insert (properties, prop, prop);
3906 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3909 g_hash_table_destroy (properties);
3912 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3913 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3914 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3916 mono_ptr_array_destroy (tmp_array);
3922 g_hash_table_destroy (properties);
3925 mono_ptr_array_destroy (tmp_array);
3927 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3928 ex = mono_class_get_exception_for_failure (klass);
3930 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3931 mono_loader_clear_error ();
3933 mono_set_pending_exception (ex);
3938 event_hash (gconstpointer data)
3940 MonoEvent *event = (MonoEvent*)data;
3942 return g_str_hash (event->name);
3946 event_equal (MonoEvent *event1, MonoEvent *event2)
3948 // Events are hide-by-name
3949 return g_str_equal (event1->name, event2->name);
3952 ICALL_EXPORT MonoArray*
3953 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3957 static MonoClass *System_Reflection_EventInfo;
3958 MonoClass *startklass, *klass;
3964 char *utf8_name = NULL;
3965 int (*compare_func) (const char *s1, const char *s2) = NULL;
3966 GHashTable *events = NULL;
3967 MonoPtrArray tmp_array;
3969 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
3971 if (!System_Reflection_EventInfo)
3972 System_Reflection_EventInfo = mono_class_from_name (
3973 mono_defaults.corlib, "System.Reflection", "EventInfo");
3975 domain = mono_object_domain (type);
3976 if (type->type->byref)
3977 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3978 klass = startklass = mono_class_from_mono_type (type->type);
3980 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
3982 mono_class_setup_methods (klass);
3983 mono_class_setup_vtable (klass);
3984 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3988 while ((event = mono_class_get_events (klass, &iter))) {
3990 method = event->add;
3992 method = event->remove;
3994 method = event->raise;
3996 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3997 if (bflags & BFLAGS_Public)
3999 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4000 if (bflags & BFLAGS_NonPublic)
4005 if (bflags & BFLAGS_NonPublic)
4011 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4012 if (bflags & BFLAGS_Static)
4013 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4016 if (bflags & BFLAGS_Instance)
4021 if (bflags & BFLAGS_Instance)
4027 if (utf8_name == NULL) {
4028 utf8_name = mono_string_to_utf8 (name);
4029 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4032 if (compare_func (event->name, utf8_name))
4036 if (g_hash_table_lookup (events, event))
4039 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
4041 g_hash_table_insert (events, event, event);
4043 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4046 g_hash_table_destroy (events);
4048 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
4050 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4051 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4053 mono_ptr_array_destroy (tmp_array);
4055 if (utf8_name != NULL)
4061 mono_ptr_array_destroy (tmp_array);
4062 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4063 ex = mono_class_get_exception_for_failure (klass);
4065 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4066 mono_loader_clear_error ();
4068 mono_set_pending_exception (ex);
4072 ICALL_EXPORT MonoArray*
4073 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4076 MonoReflectionType *rt;
4084 MonoPtrArray tmp_array;
4086 domain = ((MonoObject *)type)->vtable->domain;
4087 if (type->type->byref)
4088 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4089 klass = mono_class_from_mono_type (type->type);
4092 * If a nested type is generic, return its generic type definition.
4093 * Note that this means that the return value is essentially the set
4094 * of nested types of the generic type definition of @klass.
4096 * A note in MSDN claims that a generic type definition can have
4097 * nested types that aren't generic. In any case, the container of that
4098 * nested type would be the generic type definition.
4100 if (klass->generic_class)
4101 klass = klass->generic_class->container_class;
4103 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4105 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4107 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4108 if (bflags & BFLAGS_Public)
4111 if (bflags & BFLAGS_NonPublic)
4119 str = mono_string_to_utf8 (name);
4120 mono_identifier_unescape_type_name_chars (str);
4123 if (strcmp (nested->name, str))
4127 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4128 mono_error_raise_exception (&error);
4130 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4133 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4135 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4136 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4138 mono_ptr_array_destroy (tmp_array);
4146 ICALL_EXPORT MonoReflectionType*
4147 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4150 MonoReflectionType *ret;
4152 MonoType *type = NULL;
4153 MonoTypeNameParse info;
4154 gboolean type_resolve;
4156 /* On MS.NET, this does not fire a TypeResolve event */
4157 type_resolve = TRUE;
4158 str = mono_string_to_utf8 (name);
4159 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4160 if (!mono_reflection_parse_type (str, &info)) {
4162 mono_reflection_free_type_info (&info);
4164 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4167 /*g_print ("failed parse\n");*/
4171 if (info.assembly.name) {
4173 mono_reflection_free_type_info (&info);
4175 /* 1.0 and 2.0 throw different exceptions */
4176 if (mono_defaults.generic_ilist_class)
4177 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4179 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4185 if (module != NULL) {
4187 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4192 if (assembly_is_dynamic (assembly->assembly)) {
4193 /* Enumerate all modules */
4194 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4198 if (abuilder->modules) {
4199 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4200 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4201 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4207 if (!type && abuilder->loaded_modules) {
4208 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4209 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4210 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4217 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4219 mono_reflection_free_type_info (&info);
4221 MonoException *e = NULL;
4224 e = mono_get_exception_type_load (name, NULL);
4226 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4227 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4229 mono_loader_clear_error ();
4232 mono_set_pending_exception (e);
4234 } else if (mono_loader_get_last_error ()) {
4236 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4239 mono_loader_clear_error ();
4242 if (type->type == MONO_TYPE_CLASS) {
4243 MonoClass *klass = mono_type_get_class (type);
4245 /* need to report exceptions ? */
4246 if (throwOnError && klass->exception_type) {
4247 /* report SecurityException (or others) that occured when loading the assembly */
4248 MonoException *exc = mono_class_get_exception_for_failure (klass);
4249 mono_loader_clear_error ();
4250 mono_set_pending_exception (exc);
4255 /* g_print ("got it\n"); */
4256 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4257 mono_error_raise_exception (&error);
4263 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4266 gchar *shadow_ini_file;
4269 /* Check for shadow-copied assembly */
4270 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4271 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4273 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4274 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4280 g_free (shadow_ini_file);
4281 if (content != NULL) {
4284 *filename = content;
4291 ICALL_EXPORT MonoString *
4292 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4294 MonoDomain *domain = mono_object_domain (assembly);
4295 MonoAssembly *mass = assembly->assembly;
4296 MonoString *res = NULL;
4301 if (g_path_is_absolute (mass->image->name)) {
4302 absolute = g_strdup (mass->image->name);
4303 dirname = g_path_get_dirname (absolute);
4305 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4306 dirname = g_strdup (mass->basedir);
4309 replace_shadow_path (domain, dirname, &absolute);
4314 for (i = strlen (absolute) - 1; i >= 0; i--)
4315 if (absolute [i] == '\\')
4320 uri = g_filename_to_uri (absolute, NULL, NULL);
4322 const char *prepend = "file://";
4324 if (*absolute == '/' && *(absolute + 1) == '/') {
4327 prepend = "file:///";
4330 uri = g_strconcat (prepend, absolute, NULL);
4334 res = mono_string_new (domain, uri);
4341 ICALL_EXPORT MonoBoolean
4342 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4344 MonoAssembly *mass = assembly->assembly;
4346 return mass->in_gac;
4349 ICALL_EXPORT MonoReflectionAssembly*
4350 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4354 MonoImageOpenStatus status;
4356 name = mono_string_to_utf8 (mname);
4357 res = mono_assembly_load_with_partial_name (name, &status);
4363 return mono_assembly_get_object (mono_domain_get (), res);
4366 ICALL_EXPORT MonoString *
4367 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4369 MonoDomain *domain = mono_object_domain (assembly);
4372 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4377 ICALL_EXPORT MonoBoolean
4378 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4380 return assembly->assembly->ref_only;
4383 ICALL_EXPORT MonoString *
4384 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4386 MonoDomain *domain = mono_object_domain (assembly);
4388 return mono_string_new (domain, assembly->assembly->image->version);
4391 ICALL_EXPORT MonoReflectionMethod*
4392 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4396 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4400 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4401 if (!mono_error_ok (&error)) {
4402 mono_error_set_pending_exception (&error);
4406 return mono_method_get_object (mono_object_domain (assembly), method, NULL);
4409 ICALL_EXPORT MonoReflectionModule*
4410 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4412 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4415 ICALL_EXPORT MonoArray*
4416 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4418 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4419 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4423 for (i = 0; i < table->rows; ++i) {
4424 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4425 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4431 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4433 static MonoClass *System_Version = NULL;
4434 static MonoMethod *create_version = NULL;
4438 if (!System_Version) {
4439 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4440 g_assert (System_Version);
4443 if (!create_version) {
4444 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4445 create_version = mono_method_desc_search_in_class (desc, System_Version);
4446 g_assert (create_version);
4447 mono_method_desc_free (desc);
4453 args [3] = &revision;
4454 result = mono_object_new (domain, System_Version);
4455 mono_runtime_invoke (create_version, result, args, NULL);
4460 ICALL_EXPORT MonoArray*
4461 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4463 static MonoClass *System_Reflection_AssemblyName;
4465 MonoDomain *domain = mono_object_domain (assembly);
4467 static MonoMethod *create_culture = NULL;
4468 MonoImage *image = assembly->assembly->image;
4471 if (!System_Reflection_AssemblyName)
4472 System_Reflection_AssemblyName = mono_class_from_name (
4473 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4475 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4478 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4480 if (count > 0 && !create_culture) {
4481 MonoMethodDesc *desc = mono_method_desc_new (
4482 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4483 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4484 g_assert (create_culture);
4485 mono_method_desc_free (desc);
4488 for (i = 0; i < count; i++) {
4489 MonoReflectionAssemblyName *aname;
4490 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4492 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4494 aname = (MonoReflectionAssemblyName *) mono_object_new (
4495 domain, System_Reflection_AssemblyName);
4497 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4499 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4500 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4501 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4502 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4503 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4504 aname->versioncompat = 1; /* SameMachine (default) */
4505 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4506 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4508 if (create_culture) {
4510 MonoBoolean assembly_ref = 1;
4511 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4512 args [1] = &assembly_ref;
4513 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4516 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4517 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4518 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4520 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4521 /* public key token isn't copied - the class library will
4522 automatically generate it from the public key if required */
4523 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4524 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4526 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4527 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4530 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4533 /* note: this function doesn't return the codebase on purpose (i.e. it can
4534 be used under partial trust as path information isn't present). */
4536 mono_array_setref (result, i, aname);
4541 /* move this in some file in mono/util/ */
4543 g_concat_dir_and_file (const char *dir, const char *file)
4545 g_return_val_if_fail (dir != NULL, NULL);
4546 g_return_val_if_fail (file != NULL, NULL);
4549 * If the directory name doesn't have a / on the end, we need
4550 * to add one so we get a proper path to the file
4552 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4553 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4555 return g_strconcat (dir, file, NULL);
4559 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4561 char *n = mono_string_to_utf8 (name);
4562 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4564 guint32 cols [MONO_MANIFEST_SIZE];
4565 guint32 impl, file_idx;
4569 for (i = 0; i < table->rows; ++i) {
4570 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4571 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4572 if (strcmp (val, n) == 0)
4576 if (i == table->rows)
4579 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4582 * this code should only be called after obtaining the
4583 * ResourceInfo and handling the other cases.
4585 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4586 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4588 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4593 module = assembly->assembly->image;
4595 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4597 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4600 ICALL_EXPORT gboolean
4601 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4603 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4605 guint32 cols [MONO_MANIFEST_SIZE];
4606 guint32 file_cols [MONO_FILE_SIZE];
4610 n = mono_string_to_utf8 (name);
4611 for (i = 0; i < table->rows; ++i) {
4612 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4613 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4614 if (strcmp (val, n) == 0)
4618 if (i == table->rows)
4621 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4622 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4625 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4626 case MONO_IMPLEMENTATION_FILE:
4627 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4628 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4629 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4630 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4631 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4632 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4635 info->location = RESOURCE_LOCATION_EMBEDDED;
4638 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4639 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4640 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4641 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4642 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4643 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4645 mono_set_pending_exception (ex);
4648 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4650 /* Obtain info recursively */
4651 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4652 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4655 case MONO_IMPLEMENTATION_EXP_TYPE:
4656 g_assert_not_reached ();
4664 ICALL_EXPORT MonoObject*
4665 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4667 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4668 MonoArray *result = NULL;
4673 /* check hash if needed */
4675 n = mono_string_to_utf8 (name);
4676 for (i = 0; i < table->rows; ++i) {
4677 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4678 if (strcmp (val, n) == 0) {
4681 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4682 fn = mono_string_new (mono_object_domain (assembly), n);
4684 return (MonoObject*)fn;
4692 for (i = 0; i < table->rows; ++i) {
4693 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4697 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4700 for (i = 0; i < table->rows; ++i) {
4701 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4702 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4703 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4704 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4709 return (MonoObject*)result;
4712 ICALL_EXPORT MonoArray*
4713 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4715 MonoDomain *domain = mono_domain_get();
4718 int i, j, file_count = 0;
4719 MonoImage **modules;
4720 guint32 module_count, real_module_count;
4721 MonoTableInfo *table;
4722 guint32 cols [MONO_FILE_SIZE];
4723 MonoImage *image = assembly->assembly->image;
4725 g_assert (image != NULL);
4726 g_assert (!assembly_is_dynamic (assembly->assembly));
4728 table = &image->tables [MONO_TABLE_FILE];
4729 file_count = table->rows;
4731 modules = image->modules;
4732 module_count = image->module_count;
4734 real_module_count = 0;
4735 for (i = 0; i < module_count; ++i)
4737 real_module_count ++;
4739 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4740 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4742 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4744 for (i = 0; i < module_count; ++i)
4746 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4750 for (i = 0; i < file_count; ++i, ++j) {
4751 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4752 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4753 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4755 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4757 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4758 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
4761 mono_array_setref (res, j, mono_module_get_object (domain, m));
4768 ICALL_EXPORT MonoReflectionMethod*
4769 ves_icall_GetCurrentMethod (void)
4771 MonoMethod *m = mono_method_get_last_managed ();
4774 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
4778 while (m->is_inflated)
4779 m = ((MonoMethodInflated*)m)->declaring;
4781 return mono_method_get_object (mono_domain_get (), m, NULL);
4786 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4789 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4792 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4793 //method is inflated, we should inflate it on the other class
4794 MonoGenericContext ctx;
4795 ctx.method_inst = inflated->context.method_inst;
4796 ctx.class_inst = inflated->context.class_inst;
4797 if (klass->generic_class)
4798 ctx.class_inst = klass->generic_class->context.class_inst;
4799 else if (klass->generic_container)
4800 ctx.class_inst = klass->generic_container->context.class_inst;
4801 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
4802 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4806 mono_class_setup_methods (method->klass);
4807 if (method->klass->exception_type)
4809 for (i = 0; i < method->klass->method.count; ++i) {
4810 if (method->klass->methods [i] == method) {
4815 mono_class_setup_methods (klass);
4816 if (klass->exception_type)
4818 g_assert (offset >= 0 && offset < klass->method.count);
4819 return klass->methods [offset];
4822 ICALL_EXPORT MonoReflectionMethod*
4823 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4827 klass = mono_class_from_mono_type (type);
4828 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4830 if (method->klass != klass) {
4831 method = mono_method_get_equivalent_method (method, klass);
4836 klass = method->klass;
4837 return mono_method_get_object (mono_domain_get (), method, klass);
4840 ICALL_EXPORT MonoReflectionMethodBody*
4841 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4843 return mono_method_body_get_object (mono_domain_get (), method);
4846 ICALL_EXPORT MonoReflectionAssembly*
4847 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4849 MonoMethod *dest = NULL;
4851 mono_stack_walk_no_il (get_executing, &dest);
4853 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4857 ICALL_EXPORT MonoReflectionAssembly*
4858 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4860 MonoDomain* domain = mono_domain_get ();
4862 if (!domain->entry_assembly)
4865 return mono_assembly_get_object (domain, domain->entry_assembly);
4868 ICALL_EXPORT MonoReflectionAssembly*
4869 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4875 mono_stack_walk_no_il (get_executing, &dest);
4877 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
4881 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
4884 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4887 ICALL_EXPORT MonoString *
4888 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4889 gboolean assembly_qualified)
4891 MonoDomain *domain = mono_object_domain (object);
4892 MonoTypeNameFormat format;
4897 format = assembly_qualified ?
4898 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4899 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4901 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4903 name = mono_type_get_name_full (object->type, format);
4907 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4912 res = mono_string_new (domain, name);
4919 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
4921 MonoClass *klass = mono_class_from_mono_type (rfield->type);
4922 mono_class_init_or_throw (klass);
4923 return mono_security_core_clr_class_level (klass);
4927 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
4929 MonoClassField *field = rfield->field;
4930 return mono_security_core_clr_field_level (field, TRUE);
4934 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
4936 MonoMethod *method = rfield->method;
4937 return mono_security_core_clr_method_level (method, TRUE);
4941 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4943 static MonoMethod *create_culture = NULL;
4946 const char *pkey_ptr;
4948 MonoBoolean assembly_ref = 0;
4950 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4951 aname->major = name->major;
4952 aname->minor = name->minor;
4953 aname->build = name->build;
4954 aname->flags = name->flags;
4955 aname->revision = name->revision;
4956 aname->hashalg = name->hash_alg;
4957 aname->versioncompat = 1; /* SameMachine (default) */
4958 aname->processor_architecture = name->arch;
4960 if (by_default_version)
4961 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4964 if (absolute != NULL && *absolute != '\0') {
4965 const gchar *prepend = "file://";
4968 codebase = g_strdup (absolute);
4973 for (i = strlen (codebase) - 1; i >= 0; i--)
4974 if (codebase [i] == '\\')
4977 if (*codebase == '/' && *(codebase + 1) == '/') {
4980 prepend = "file:///";
4984 result = g_strconcat (prepend, codebase, NULL);
4990 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4994 if (!create_culture) {
4995 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4996 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4997 g_assert (create_culture);
4998 mono_method_desc_free (desc);
5001 if (name->culture) {
5002 args [0] = mono_string_new (domain, name->culture);
5003 args [1] = &assembly_ref;
5004 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5007 if (name->public_key) {
5008 pkey_ptr = (char*)name->public_key;
5009 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5011 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5012 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5013 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5014 } else if (default_publickey) {
5015 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5016 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5019 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5020 if (name->public_key_token [0]) {
5024 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5025 p = mono_array_addr (aname->keyToken, char, 0);
5027 for (i = 0, j = 0; i < 8; i++) {
5028 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5029 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5032 } else if (default_token) {
5033 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5037 ICALL_EXPORT MonoString *
5038 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5040 MonoDomain *domain = mono_object_domain (assembly);
5041 MonoAssembly *mass = assembly->assembly;
5045 name = mono_stringify_assembly_name (&mass->aname);
5046 res = mono_string_new (domain, name);
5053 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5056 MonoAssembly *mass = assembly->assembly;
5058 if (g_path_is_absolute (mass->image->name)) {
5059 fill_reflection_assembly_name (mono_object_domain (assembly),
5060 aname, &mass->aname, mass->image->name, TRUE,
5064 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5066 fill_reflection_assembly_name (mono_object_domain (assembly),
5067 aname, &mass->aname, absolute, TRUE, TRUE,
5074 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5077 MonoImageOpenStatus status = MONO_IMAGE_OK;
5080 MonoAssemblyName name;
5083 filename = mono_string_to_utf8 (fname);
5085 dirname = g_path_get_dirname (filename);
5086 replace_shadow_path (mono_domain_get (), dirname, &filename);
5089 image = mono_image_open (filename, &status);
5095 if (status == MONO_IMAGE_IMAGE_INVALID)
5096 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5098 exc = mono_get_exception_file_not_found2 (NULL, fname);
5099 mono_set_pending_exception (exc);
5103 res = mono_assembly_fill_assembly_name (image, &name);
5105 mono_image_close (image);
5107 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5111 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5115 mono_image_close (image);
5118 ICALL_EXPORT MonoBoolean
5119 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5120 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5122 MonoBoolean result = FALSE;
5123 MonoDeclSecurityEntry entry;
5125 /* SecurityAction.RequestMinimum */
5126 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5127 *minimum = entry.blob;
5128 *minLength = entry.size;
5131 /* SecurityAction.RequestOptional */
5132 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5133 *optional = entry.blob;
5134 *optLength = entry.size;
5137 /* SecurityAction.RequestRefuse */
5138 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5139 *refused = entry.blob;
5140 *refLength = entry.size;
5148 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5150 guint32 attrs, visibility;
5152 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5153 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5154 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5157 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5163 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5166 MonoReflectionType *rt;
5169 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5172 /* we start the count from 1 because we skip the special type <Module> */
5175 for (i = 1; i < tdef->rows; ++i) {
5176 if (mono_module_type_is_visible (tdef, image, i + 1))
5180 count = tdef->rows - 1;
5182 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5183 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5185 for (i = 1; i < tdef->rows; ++i) {
5186 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5187 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, &error);
5188 mono_loader_assert_no_error (); /* Plug any leaks */
5189 g_assert (mono_error_ok (&error));
5192 rt = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5193 mono_error_raise_exception (&error); /* FIXME don't raise here */
5195 mono_array_setref (res, count, rt);
5197 MonoException *ex = mono_error_convert_to_exception (&error);
5198 mono_array_setref (*exceptions, count, ex);
5207 ICALL_EXPORT MonoArray*
5208 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5210 MonoArray *res = NULL;
5211 MonoArray *exceptions = NULL;
5212 MonoImage *image = NULL;
5213 MonoTableInfo *table = NULL;
5216 int i, len, ex_count;
5218 domain = mono_object_domain (assembly);
5220 g_assert (!assembly_is_dynamic (assembly->assembly));
5221 image = assembly->assembly->image;
5222 table = &image->tables [MONO_TABLE_FILE];
5223 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5225 /* Append data from all modules in the assembly */
5226 for (i = 0; i < table->rows; ++i) {
5227 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5228 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5231 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5232 /* Append the new types to the end of the array */
5233 if (mono_array_length (res2) > 0) {
5235 MonoArray *res3, *ex3;
5237 len1 = mono_array_length (res);
5238 len2 = mono_array_length (res2);
5240 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5241 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5242 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5245 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5246 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5247 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5254 /* the ReflectionTypeLoadException must have all the types (Types property),
5255 * NULL replacing types which throws an exception. The LoaderException must
5256 * contain all exceptions for NULL items.
5259 len = mono_array_length (res);
5262 for (i = 0; i < len; i++) {
5263 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5267 klass = mono_type_get_class (t->type);
5268 if ((klass != NULL) && klass->exception_type) {
5269 /* keep the class in the list */
5270 list = g_list_append (list, klass);
5271 /* and replace Type with NULL */
5272 mono_array_setref (res, i, NULL);
5279 if (list || ex_count) {
5281 MonoException *exc = NULL;
5282 MonoArray *exl = NULL;
5283 int j, length = g_list_length (list) + ex_count;
5285 mono_loader_clear_error ();
5287 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5288 /* Types for which mono_class_get_checked () succeeded */
5289 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5290 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5291 mono_array_setref (exl, i, exc);
5293 /* Types for which it don't */
5294 for (j = 0; j < mono_array_length (exceptions); ++j) {
5295 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5297 g_assert (i < length);
5298 mono_array_setref (exl, i, exc);
5305 exc = mono_get_exception_reflection_type_load (res, exl);
5306 mono_loader_clear_error ();
5307 mono_set_pending_exception (exc);
5314 ICALL_EXPORT gboolean
5315 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5317 MonoAssemblyName aname;
5318 MonoDomain *domain = mono_object_domain (name);
5320 gboolean is_version_defined;
5321 gboolean is_token_defined;
5323 aname.public_key = NULL;
5324 val = mono_string_to_utf8 (assname);
5325 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5326 g_free ((guint8*) aname.public_key);
5331 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5332 FALSE, is_token_defined);
5334 mono_assembly_name_free (&aname);
5335 g_free ((guint8*) aname.public_key);
5341 ICALL_EXPORT MonoReflectionType*
5342 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5345 MonoReflectionType *ret;
5346 MonoDomain *domain = mono_object_domain (module);
5349 g_assert (module->image);
5351 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5352 /* These images do not have a global type */
5355 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5356 if (!mono_error_ok (&error)) {
5357 mono_error_set_pending_exception (&error);
5361 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5362 if (!mono_error_ok (&error)) {
5363 mono_error_set_pending_exception (&error);
5371 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5373 /*if (module->image)
5374 mono_image_close (module->image);*/
5377 ICALL_EXPORT MonoString*
5378 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5380 MonoDomain *domain = mono_object_domain (module);
5382 g_assert (module->image);
5383 return mono_string_new (domain, module->image->guid);
5386 ICALL_EXPORT gpointer
5387 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5390 if (module->image && module->image->is_module_handle)
5391 return module->image->raw_data;
5394 return (gpointer) (-1);
5398 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5400 if (image_is_dynamic (image)) {
5401 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5402 *pe_kind = dyn->pe_kind;
5403 *machine = dyn->machine;
5406 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5407 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5412 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5414 return (image->md_version_major << 16) | (image->md_version_minor);
5417 ICALL_EXPORT MonoArray*
5418 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5420 MonoArray *exceptions;
5424 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5426 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5427 for (i = 0; i < mono_array_length (exceptions); ++i) {
5428 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5430 mono_set_pending_exception (ex);
5439 mono_memberref_is_method (MonoImage *image, guint32 token)
5441 if (!image_is_dynamic (image)) {
5442 guint32 cols [MONO_MEMBERREF_SIZE];
5444 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5445 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5446 mono_metadata_decode_blob_size (sig, &sig);
5447 return (*sig != 0x6);
5449 MonoClass *handle_class;
5451 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5454 return mono_defaults.methodhandle_class == handle_class;
5459 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5462 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5463 mono_array_addr (type_args, MonoType*, 0));
5465 context->class_inst = NULL;
5467 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5468 mono_array_addr (method_args, MonoType*, 0));
5470 context->method_inst = NULL;
5473 ICALL_EXPORT MonoType*
5474 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5477 int table = mono_metadata_token_table (token);
5478 int index = mono_metadata_token_index (token);
5479 MonoGenericContext context;
5482 *resolve_error = ResolveTokenError_Other;
5484 /* Validate token */
5485 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5486 (table != MONO_TABLE_TYPESPEC)) {
5487 *resolve_error = ResolveTokenError_BadTable;
5491 if (image_is_dynamic (image)) {
5492 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5493 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5494 return klass ? &klass->byval_arg : NULL;
5497 init_generic_context_from_args (&context, type_args, method_args);
5498 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5499 return klass ? &klass->byval_arg : NULL;
5502 if ((index <= 0) || (index > image->tables [table].rows)) {
5503 *resolve_error = ResolveTokenError_OutOfRange;
5507 init_generic_context_from_args (&context, type_args, method_args);
5508 klass = mono_class_get_checked (image, token, &error);
5510 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5511 if (!mono_error_ok (&error)) {
5512 mono_error_set_pending_exception (&error);
5517 return &klass->byval_arg;
5522 ICALL_EXPORT MonoMethod*
5523 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5526 int table = mono_metadata_token_table (token);
5527 int index = mono_metadata_token_index (token);
5528 MonoGenericContext context;
5531 *resolve_error = ResolveTokenError_Other;
5533 /* Validate token */
5534 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5535 (table != MONO_TABLE_MEMBERREF)) {
5536 *resolve_error = ResolveTokenError_BadTable;
5540 if (image_is_dynamic (image)) {
5541 if (table == MONO_TABLE_METHOD)
5542 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5544 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5545 *resolve_error = ResolveTokenError_BadTable;
5549 init_generic_context_from_args (&context, type_args, method_args);
5550 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5553 if ((index <= 0) || (index > image->tables [table].rows)) {
5554 *resolve_error = ResolveTokenError_OutOfRange;
5557 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5558 *resolve_error = ResolveTokenError_BadTable;
5562 init_generic_context_from_args (&context, type_args, method_args);
5563 method = mono_get_method_checked (image, token, NULL, &context, &error);
5564 mono_error_set_pending_exception (&error);
5569 ICALL_EXPORT MonoString*
5570 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5572 int index = mono_metadata_token_index (token);
5574 *error = ResolveTokenError_Other;
5576 /* Validate token */
5577 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5578 *error = ResolveTokenError_BadTable;
5582 if (image_is_dynamic (image))
5583 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5585 if ((index <= 0) || (index >= image->heap_us.size)) {
5586 *error = ResolveTokenError_OutOfRange;
5590 /* FIXME: What to do if the index points into the middle of a string ? */
5592 return mono_ldstr (mono_domain_get (), image, index);
5595 ICALL_EXPORT MonoClassField*
5596 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5600 int table = mono_metadata_token_table (token);
5601 int index = mono_metadata_token_index (token);
5602 MonoGenericContext context;
5603 MonoClassField *field;
5605 *resolve_error = ResolveTokenError_Other;
5607 /* Validate token */
5608 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5609 *resolve_error = ResolveTokenError_BadTable;
5613 if (image_is_dynamic (image)) {
5614 if (table == MONO_TABLE_FIELD)
5615 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5617 if (mono_memberref_is_method (image, token)) {
5618 *resolve_error = ResolveTokenError_BadTable;
5622 init_generic_context_from_args (&context, type_args, method_args);
5623 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5626 if ((index <= 0) || (index > image->tables [table].rows)) {
5627 *resolve_error = ResolveTokenError_OutOfRange;
5630 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5631 *resolve_error = ResolveTokenError_BadTable;
5635 init_generic_context_from_args (&context, type_args, method_args);
5636 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5637 mono_error_set_pending_exception (&error);
5643 ICALL_EXPORT MonoObject*
5644 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5648 int table = mono_metadata_token_table (token);
5650 *error = ResolveTokenError_Other;
5653 case MONO_TABLE_TYPEDEF:
5654 case MONO_TABLE_TYPEREF:
5655 case MONO_TABLE_TYPESPEC: {
5656 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5658 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
5659 mono_error_raise_exception (&merror);
5666 case MONO_TABLE_METHOD:
5667 case MONO_TABLE_METHODSPEC: {
5668 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5670 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5674 case MONO_TABLE_FIELD: {
5675 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5677 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5681 case MONO_TABLE_MEMBERREF:
5682 if (mono_memberref_is_method (image, token)) {
5683 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5685 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5690 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5692 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5699 *error = ResolveTokenError_BadTable;
5705 ICALL_EXPORT MonoArray*
5706 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5708 int table = mono_metadata_token_table (token);
5709 int idx = mono_metadata_token_index (token);
5710 MonoTableInfo *tables = image->tables;
5715 *error = ResolveTokenError_OutOfRange;
5717 /* FIXME: Support other tables ? */
5718 if (table != MONO_TABLE_STANDALONESIG)
5721 if (image_is_dynamic (image))
5724 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5727 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5729 ptr = mono_metadata_blob_heap (image, sig);
5730 len = mono_metadata_decode_blob_size (ptr, &ptr);
5732 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5733 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5737 ICALL_EXPORT MonoReflectionType*
5738 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5741 MonoReflectionType *ret;
5743 int isbyref = 0, rank;
5744 char *str = mono_string_to_utf8 (smodifiers);
5747 klass = mono_class_from_mono_type (tb->type.type);
5749 /* logic taken from mono_reflection_parse_type(): keep in sync */
5753 if (isbyref) { /* only one level allowed by the spec */
5762 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
5763 mono_error_raise_exception (&error);
5767 klass = mono_ptr_class_get (&klass->byval_arg);
5768 mono_class_init (klass);
5779 else if (*p != '*') { /* '*' means unknown lower bound */
5790 klass = mono_array_class_get (klass, rank);
5791 mono_class_init (klass);
5800 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
5801 mono_error_raise_exception (&error);
5806 ICALL_EXPORT MonoBoolean
5807 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5813 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5819 check_for_invalid_type (MonoClass *klass)
5823 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5826 name = mono_type_get_full_name (klass);
5827 str = mono_string_new (mono_domain_get (), name);
5829 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5832 ICALL_EXPORT MonoReflectionType *
5833 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5836 MonoReflectionType *ret;
5837 MonoClass *klass, *aklass;
5839 klass = mono_class_from_mono_type (type->type);
5840 check_for_invalid_type (klass);
5842 if (rank == 0) //single dimentional array
5843 aklass = mono_array_class_get (klass, 1);
5845 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5847 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
5848 mono_error_raise_exception (&error);
5853 ICALL_EXPORT MonoReflectionType *
5854 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5857 MonoReflectionType *ret;
5860 klass = mono_class_from_mono_type (type->type);
5861 mono_class_init_or_throw (klass);
5862 check_for_invalid_type (klass);
5864 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
5865 mono_error_raise_exception (&error);
5870 ICALL_EXPORT MonoReflectionType *
5871 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5874 MonoReflectionType *ret;
5875 MonoClass *klass, *pklass;
5877 klass = mono_class_from_mono_type (type->type);
5878 mono_class_init_or_throw (klass);
5879 check_for_invalid_type (klass);
5881 pklass = mono_ptr_class_get (type->type);
5883 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
5884 mono_error_raise_exception (&error);
5889 ICALL_EXPORT MonoObject *
5890 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5891 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5893 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5894 MonoObject *delegate;
5896 MonoMethod *method = info->method;
5898 mono_class_init_or_throw (delegate_class);
5900 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5902 if (mono_security_core_clr_enabled ()) {
5903 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5907 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5909 if (method_is_dynamic (method)) {
5910 /* Creating a trampoline would leak memory */
5911 func = mono_compile_method (method);
5913 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5914 method = mono_object_get_virtual_method (target, method);
5915 func = mono_create_ftnptr (mono_domain_get (),
5916 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5919 mono_delegate_ctor_with_method (delegate, target, func, method);
5924 ICALL_EXPORT MonoMulticastDelegate *
5925 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
5927 MonoMulticastDelegate *ret;
5929 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
5931 ret = (MonoMulticastDelegate*) mono_object_new (mono_object_domain (delegate), mono_object_class (delegate));
5932 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
5937 ICALL_EXPORT MonoReflectionMethod*
5938 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
5940 return mono_method_get_object (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target));
5945 static inline gint32
5946 mono_array_get_byte_length (MonoArray *array)
5952 klass = array->obj.vtable->klass;
5954 if (array->bounds == NULL)
5955 length = array->max_length;
5958 for (i = 0; i < klass->rank; ++ i)
5959 length *= array->bounds [i].length;
5962 switch (klass->element_class->byval_arg.type) {
5965 case MONO_TYPE_BOOLEAN:
5969 case MONO_TYPE_CHAR:
5977 return length * sizeof (gpointer);
5988 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
5990 return mono_array_get_byte_length (array);
5994 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
5996 return mono_array_get (array, gint8, idx);
6000 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6002 mono_array_set (array, gint8, idx, value);
6005 ICALL_EXPORT MonoBoolean
6006 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6008 guint8 *src_buf, *dest_buf;
6011 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6015 g_assert (count >= 0);
6017 /* This is called directly from the class libraries without going through the managed wrapper */
6018 MONO_CHECK_ARG_NULL (src, FALSE);
6019 MONO_CHECK_ARG_NULL (dest, FALSE);
6021 /* watch out for integer overflow */
6022 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6025 src_buf = (guint8 *)src->vector + src_offset;
6026 dest_buf = (guint8 *)dest->vector + dest_offset;
6029 memcpy (dest_buf, src_buf, count);
6031 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6036 #ifndef DISABLE_REMOTING
6037 ICALL_EXPORT MonoObject *
6038 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6040 MonoDomain *domain = mono_object_domain (this_obj);
6042 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6043 MonoTransparentProxy *tp;
6047 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6048 tp = (MonoTransparentProxy*) res;
6050 MONO_OBJECT_SETREF (tp, rp, rp);
6051 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6052 klass = mono_class_from_mono_type (type);
6054 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6055 mono_class_setup_vtable (klass);
6056 if (klass->exception_type) {
6057 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6061 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
6062 tp->remote_class = mono_remote_class (domain, class_name, klass);
6064 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6068 ICALL_EXPORT MonoReflectionType *
6069 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6072 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6073 mono_error_raise_exception (&error);
6079 /* System.Environment */
6082 ves_icall_System_Environment_get_UserName (void)
6084 /* using glib is more portable */
6085 return mono_string_new (mono_domain_get (), g_get_user_name ());
6089 ICALL_EXPORT MonoString *
6090 ves_icall_System_Environment_get_MachineName (void)
6092 #if defined (HOST_WIN32)
6097 len = MAX_COMPUTERNAME_LENGTH + 1;
6098 buf = g_new (gunichar2, len);
6101 if (GetComputerName (buf, (PDWORD) &len))
6102 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6106 #elif !defined(DISABLE_SOCKETS)
6110 #if defined _SC_HOST_NAME_MAX
6111 n = sysconf (_SC_HOST_NAME_MAX);
6115 buf = g_malloc (n+1);
6117 if (gethostname (buf, n) == 0){
6119 result = mono_string_new (mono_domain_get (), buf);
6126 return mono_string_new (mono_domain_get (), "mono");
6131 ves_icall_System_Environment_get_Platform (void)
6133 #if defined (TARGET_WIN32)
6136 #elif defined(__MACH__)
6139 // Notice that the value is hidden from user code, and only exposed
6140 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6141 // define and making assumptions based on Unix/128/4 values before there
6142 // was a MacOS define. Lots of code would assume that not-Unix meant
6143 // Windows, but in this case, it would be OSX.
6152 ICALL_EXPORT MonoString *
6153 ves_icall_System_Environment_get_NewLine (void)
6155 #if defined (HOST_WIN32)
6156 return mono_string_new (mono_domain_get (), "\r\n");
6158 return mono_string_new (mono_domain_get (), "\n");
6162 ICALL_EXPORT MonoBoolean
6163 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6165 #if SIZEOF_VOID_P == 8
6169 gboolean isWow64Process = FALSE;
6170 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6171 return (MonoBoolean)isWow64Process;
6173 #elif defined(HAVE_SYS_UTSNAME_H)
6174 struct utsname name;
6176 if (uname (&name) >= 0) {
6177 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6184 ICALL_EXPORT MonoString *
6185 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6193 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6194 value = g_getenv (utf8_name);
6201 return mono_string_new (mono_domain_get (), value);
6205 * There is no standard way to get at environ.
6208 #ifndef __MINGW32_VERSION
6209 #if defined(__APPLE__)
6210 #if defined (TARGET_OSX)
6211 /* Apple defines this in crt_externs.h but doesn't provide that header for
6212 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6213 * in fact exist on all implementations (so far)
6215 gchar ***_NSGetEnviron(void);
6216 #define environ (*_NSGetEnviron())
6218 static char *mono_environ[1] = { NULL };
6219 #define environ mono_environ
6220 #endif /* defined (TARGET_OSX) */
6228 ICALL_EXPORT MonoArray *
6229 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6240 env_strings = GetEnvironmentStrings();
6243 env_string = env_strings;
6244 while (*env_string != '\0') {
6245 /* weird case that MS seems to skip */
6246 if (*env_string != '=')
6248 while (*env_string != '\0')
6254 domain = mono_domain_get ();
6255 names = mono_array_new (domain, mono_defaults.string_class, n);
6259 env_string = env_strings;
6260 while (*env_string != '\0') {
6261 /* weird case that MS seems to skip */
6262 if (*env_string != '=') {
6263 equal_str = wcschr(env_string, '=');
6264 g_assert(equal_str);
6265 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6266 mono_array_setref (names, n, str);
6269 while (*env_string != '\0')
6274 FreeEnvironmentStrings (env_strings);
6287 for (e = environ; *e != 0; ++ e)
6290 domain = mono_domain_get ();
6291 names = mono_array_new (domain, mono_defaults.string_class, n);
6294 for (e = environ; *e != 0; ++ e) {
6295 parts = g_strsplit (*e, "=", 2);
6297 str = mono_string_new (domain, *parts);
6298 mono_array_setref (names, n, str);
6311 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6313 #if !GLIB_CHECK_VERSION(2,4,0)
6314 #define g_setenv(a,b,c) setenv(a,b,c)
6315 #define g_unsetenv(a) unsetenv(a)
6319 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6322 gunichar2 *utf16_name, *utf16_value;
6324 gchar *utf8_name, *utf8_value;
6329 utf16_name = mono_string_to_utf16 (name);
6330 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6331 SetEnvironmentVariable (utf16_name, NULL);
6332 g_free (utf16_name);
6336 utf16_value = mono_string_to_utf16 (value);
6338 SetEnvironmentVariable (utf16_name, utf16_value);
6340 g_free (utf16_name);
6341 g_free (utf16_value);
6343 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6345 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6346 g_unsetenv (utf8_name);
6351 utf8_value = mono_string_to_utf8_checked (value, &error);
6352 if (!mono_error_ok (&error)) {
6354 mono_error_set_pending_exception (&error);
6357 g_setenv (utf8_name, utf8_value, TRUE);
6360 g_free (utf8_value);
6365 ves_icall_System_Environment_Exit (int result)
6367 mono_environment_exitcode_set (result);
6369 /* FIXME: There are some cleanup hangs that should be worked out, but
6370 * if the program is going to exit, everything will be cleaned up when
6371 * NaCl exits anyway.
6373 #ifndef __native_client__
6374 if (!mono_runtime_try_shutdown ())
6375 mono_thread_exit ();
6377 /* Suspend all managed threads since the runtime is going away */
6378 mono_thread_suspend_all_other_threads ();
6380 mono_runtime_quit ();
6383 /* we may need to do some cleanup here... */
6387 ICALL_EXPORT MonoString*
6388 ves_icall_System_Environment_GetGacPath (void)
6390 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6393 ICALL_EXPORT MonoString*
6394 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6396 #if defined (HOST_WIN32)
6397 #ifndef CSIDL_FLAG_CREATE
6398 #define CSIDL_FLAG_CREATE 0x8000
6401 WCHAR path [MAX_PATH];
6402 /* Create directory if no existing */
6403 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6407 return mono_string_new_utf16 (mono_domain_get (), path, len);
6410 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6412 return mono_string_new (mono_domain_get (), "");
6415 ICALL_EXPORT MonoArray *
6416 ves_icall_System_Environment_GetLogicalDrives (void)
6418 gunichar2 buf [256], *ptr, *dname;
6420 guint initial_size = 127, size = 128;
6423 MonoString *drivestr;
6424 MonoDomain *domain = mono_domain_get ();
6430 while (size > initial_size) {
6431 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6432 if (size > initial_size) {
6435 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6436 initial_size = size;
6450 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6455 while (*u16) { u16++; len ++; }
6456 drivestr = mono_string_new_utf16 (domain, dname, len);
6457 mono_array_setref (result, ndrives++, drivestr);
6467 ICALL_EXPORT MonoString *
6468 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6470 gunichar2 volume_name [MAX_PATH + 1];
6472 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6474 return mono_string_from_utf16 (volume_name);
6477 ICALL_EXPORT MonoString *
6478 ves_icall_System_Environment_InternalGetHome (void)
6480 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6483 static const char *encodings [] = {
6485 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6486 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6487 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6489 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6490 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6491 "x_unicode_2_0_utf_7",
6493 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6494 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6496 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6499 "unicodefffe", "utf_16be",
6506 * Returns the internal codepage, if the value of "int_code_page" is
6507 * 1 at entry, and we can not compute a suitable code page number,
6508 * returns the code page as a string
6510 ICALL_EXPORT MonoString*
6511 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6516 char *codepage = NULL;
6518 int want_name = *int_code_page;
6521 *int_code_page = -1;
6523 g_get_charset (&cset);
6524 c = codepage = strdup (cset);
6525 for (c = codepage; *c; c++){
6526 if (isascii (*c) && isalpha (*c))
6531 /* g_print ("charset: %s\n", cset); */
6533 /* handle some common aliases */
6536 for (i = 0; p != 0; ){
6539 p = encodings [++i];
6542 if (strcmp (p, codepage) == 0){
6543 *int_code_page = code;
6546 p = encodings [++i];
6549 if (strstr (codepage, "utf_8") != NULL)
6550 *int_code_page |= 0x10000000;
6553 if (want_name && *int_code_page == -1)
6554 return mono_string_new (mono_domain_get (), cset);
6559 ICALL_EXPORT MonoBoolean
6560 ves_icall_System_Environment_get_HasShutdownStarted (void)
6562 if (mono_runtime_is_shutting_down ())
6565 if (mono_domain_is_unloading (mono_domain_get ()))
6572 ves_icall_System_Environment_BroadcastSettingChange (void)
6575 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6580 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6586 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6587 MonoReflectionMethod *method,
6588 MonoArray *out_args)
6590 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6593 #ifndef DISABLE_REMOTING
6594 ICALL_EXPORT MonoBoolean
6595 ves_icall_IsTransparentProxy (MonoObject *proxy)
6600 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6606 ICALL_EXPORT MonoReflectionMethod *
6607 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6608 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6612 MonoMethod **vtable;
6613 MonoMethod *res = NULL;
6615 MONO_CHECK_ARG_NULL (rtype, NULL);
6616 MONO_CHECK_ARG_NULL (rmethod, NULL);
6618 method = rmethod->method;
6619 klass = mono_class_from_mono_type (rtype->type);
6620 mono_class_init_or_throw (klass);
6622 if (MONO_CLASS_IS_INTERFACE (klass))
6625 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6628 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6629 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6635 mono_class_setup_vtable (klass);
6636 vtable = klass->vtable;
6638 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6639 gboolean variance_used = FALSE;
6640 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6641 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6643 res = vtable [offs + method->slot];
6645 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6648 if (method->slot != -1)
6649 res = vtable [method->slot];
6655 return mono_method_get_object (mono_domain_get (), res, NULL);
6659 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6664 klass = mono_class_from_mono_type (type->type);
6665 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6667 mono_vtable_set_is_remote (vtable, enable);
6670 #else /* DISABLE_REMOTING */
6673 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6675 g_assert_not_reached ();
6680 ICALL_EXPORT MonoObject *
6681 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6688 domain = mono_object_domain (type);
6689 klass = mono_class_from_mono_type (type->type);
6690 mono_class_init_or_throw (klass);
6692 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
6693 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6697 if (klass->rank >= 1) {
6698 g_assert (klass->rank == 1);
6699 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6701 /* Bypass remoting object creation check */
6702 ret = mono_object_new_alloc_specific_checked (mono_class_vtable_full (domain, klass, TRUE), &error);
6703 mono_error_set_pending_exception (&error);
6709 ICALL_EXPORT MonoString *
6710 ves_icall_System_IO_get_temp_path (void)
6712 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6715 #ifndef PLATFORM_NO_DRIVEINFO
6716 ICALL_EXPORT MonoBoolean
6717 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6718 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6722 ULARGE_INTEGER wapi_free_bytes_avail;
6723 ULARGE_INTEGER wapi_total_number_of_bytes;
6724 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6726 *error = ERROR_SUCCESS;
6727 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6728 &wapi_total_number_of_free_bytes);
6731 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6732 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6733 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6735 *free_bytes_avail = 0;
6736 *total_number_of_bytes = 0;
6737 *total_number_of_free_bytes = 0;
6738 *error = GetLastError ();
6744 ICALL_EXPORT guint32
6745 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6747 return GetDriveType (mono_string_chars (root_path_name));
6751 ICALL_EXPORT gpointer
6752 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6754 return mono_compile_method (method);
6757 ICALL_EXPORT MonoString *
6758 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6763 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6765 #if defined (HOST_WIN32)
6766 /* Avoid mixing '/' and '\\' */
6769 for (i = strlen (path) - 1; i >= 0; i--)
6770 if (path [i] == '/')
6774 mcpath = mono_string_new (mono_domain_get (), path);
6781 get_bundled_app_config (void)
6783 const gchar *app_config;
6786 gchar *config_file_name, *config_file_path;
6787 gsize len, config_file_path_length, config_ext_length;
6790 domain = mono_domain_get ();
6791 file = domain->setup->configuration_file;
6792 if (!file || file->length == 0)
6795 // Retrieve config file and remove the extension
6796 config_file_name = mono_string_to_utf8 (file);
6797 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6798 if (!config_file_path)
6799 config_file_path = config_file_name;
6801 config_file_path_length = strlen (config_file_path);
6802 config_ext_length = strlen (".config");
6803 if (config_file_path_length <= config_ext_length)
6806 len = config_file_path_length - config_ext_length;
6807 module = (gchar *)g_malloc0 (len + 1);
6808 memcpy (module, config_file_path, len);
6809 // Get the config file from the module name
6810 app_config = mono_config_string_for_assembly_file (module);
6813 if (config_file_name != config_file_path)
6814 g_free (config_file_name);
6815 g_free (config_file_path);
6820 return mono_string_new (mono_domain_get (), app_config);
6824 get_bundled_machine_config (void)
6826 const gchar *machine_config;
6828 machine_config = mono_get_machine_config ();
6830 if (!machine_config)
6833 return mono_string_new (mono_domain_get (), machine_config);
6836 ICALL_EXPORT MonoString *
6837 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6842 path = g_path_get_dirname (mono_get_config_dir ());
6844 #if defined (HOST_WIN32)
6845 /* Avoid mixing '/' and '\\' */
6848 for (i = strlen (path) - 1; i >= 0; i--)
6849 if (path [i] == '/')
6853 ipath = mono_string_new (mono_domain_get (), path);
6859 ICALL_EXPORT gboolean
6860 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6862 MonoPEResourceDataEntry *entry;
6865 if (!assembly || !result || !size)
6870 image = assembly->assembly->image;
6871 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6875 *result = mono_image_rva_map (image, entry->rde_data_offset);
6880 *size = entry->rde_size;
6885 ICALL_EXPORT MonoBoolean
6886 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6888 return mono_is_debugger_attached ();
6891 ICALL_EXPORT MonoBoolean
6892 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
6894 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
6895 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
6901 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
6903 if (mono_get_runtime_callbacks ()->debug_log)
6904 mono_get_runtime_callbacks ()->debug_log (level, category, message);
6908 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6910 #if defined (HOST_WIN32)
6911 OutputDebugString (mono_string_chars (message));
6913 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6917 /* Only used for value types */
6918 ICALL_EXPORT MonoObject *
6919 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6924 domain = mono_object_domain (type);
6925 klass = mono_class_from_mono_type (type->type);
6926 mono_class_init_or_throw (klass);
6928 if (mono_class_is_nullable (klass))
6929 /* No arguments -> null */
6932 return mono_object_new (domain, klass);
6935 ICALL_EXPORT MonoReflectionMethod *
6936 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
6938 MonoClass *klass, *parent;
6939 MonoGenericContext *generic_inst = NULL;
6940 MonoMethod *method = m->method;
6941 MonoMethod *result = NULL;
6944 if (method->klass == NULL)
6947 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6948 MONO_CLASS_IS_INTERFACE (method->klass) ||
6949 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6952 slot = mono_method_get_vtable_slot (method);
6956 klass = method->klass;
6957 if (klass->generic_class) {
6958 generic_inst = mono_class_get_context (klass);
6959 klass = klass->generic_class->container_class;
6963 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6964 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6965 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
6966 or klass is the generic container class and generic_inst is the instantiation.
6968 when we go to the parent, if the parent is an open constructed type, we need to
6969 replace the type parameters by the definitions from the generic_inst, and then take it
6970 apart again into the klass and the generic_inst.
6972 For cases like this:
6973 class C<T> : B<T, int> {
6974 public override void Foo () { ... }
6976 class B<U,V> : A<HashMap<U,V>> {
6977 public override void Foo () { ... }
6980 public virtual void Foo () { ... }
6983 if at each iteration the parent isn't open, we can skip inflating it. if at some
6984 iteration the parent isn't generic (after possible inflation), we set generic_inst to
6987 MonoGenericContext *parent_inst = NULL;
6988 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
6990 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
6991 if (!mono_error_ok (&error)) {
6992 mono_error_set_pending_exception (&error);
6996 if (parent->generic_class) {
6997 parent_inst = mono_class_get_context (parent);
6998 parent = parent->generic_class->container_class;
7001 mono_class_setup_vtable (parent);
7002 if (parent->vtable_size <= slot)
7005 generic_inst = parent_inst;
7008 klass = klass->parent;
7011 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7013 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7014 if (!mono_error_ok (&error)) {
7015 mono_error_set_pending_exception (&error);
7019 generic_inst = NULL;
7021 if (klass->generic_class) {
7022 generic_inst = mono_class_get_context (klass);
7023 klass = klass->generic_class->container_class;
7030 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7031 if (!mono_error_ok (&error)) {
7032 mono_error_set_pending_exception (&error);
7037 if (klass == method->klass)
7040 /*This is possible if definition == FALSE.
7041 * Do it here to be really sure we don't read invalid memory.
7043 if (slot >= klass->vtable_size)
7046 mono_class_setup_vtable (klass);
7048 result = klass->vtable [slot];
7049 if (result == NULL) {
7050 /* It is an abstract method */
7051 gpointer iter = NULL;
7052 while ((result = mono_class_get_methods (klass, &iter)))
7053 if (result->slot == slot)
7060 return mono_method_get_object (mono_domain_get (), result, NULL);
7063 ICALL_EXPORT MonoString*
7064 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7066 MonoMethod *method = m->method;
7068 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7073 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7075 iter->sig = *(MonoMethodSignature**)argsp;
7077 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7078 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7081 /* FIXME: it's not documented what start is exactly... */
7085 iter->args = argsp + sizeof (gpointer);
7087 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7089 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7092 ICALL_EXPORT MonoTypedRef
7093 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7095 guint32 i, arg_size;
7099 i = iter->sig->sentinelpos + iter->next_arg;
7101 g_assert (i < iter->sig->param_count);
7103 res.type = iter->sig->params [i];
7104 res.klass = mono_class_from_mono_type (res.type);
7105 arg_size = mono_type_stack_size (res.type, &align);
7106 #if defined(__arm__) || defined(__mips__)
7107 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7109 res.value = iter->args;
7110 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7111 /* Values are stored as 8 byte register sized objects, but 'value'
7112 * is dereferenced as a pointer in other routines.
7114 res.value = (char*)res.value + 4;
7116 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7117 if (arg_size <= sizeof (gpointer)) {
7119 int padding = arg_size - mono_type_size (res.type, &dummy);
7120 res.value = (guint8*)res.value + padding;
7123 iter->args = (char*)iter->args + arg_size;
7126 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7131 ICALL_EXPORT MonoTypedRef
7132 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7134 guint32 i, arg_size;
7138 i = iter->sig->sentinelpos + iter->next_arg;
7140 g_assert (i < iter->sig->param_count);
7142 while (i < iter->sig->param_count) {
7143 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7145 res.type = iter->sig->params [i];
7146 res.klass = mono_class_from_mono_type (res.type);
7147 /* FIXME: endianess issue... */
7148 arg_size = mono_type_stack_size (res.type, &align);
7149 #if defined(__arm__) || defined(__mips__)
7150 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7152 res.value = iter->args;
7153 iter->args = (char*)iter->args + arg_size;
7155 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7158 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7166 ICALL_EXPORT MonoType*
7167 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7171 i = iter->sig->sentinelpos + iter->next_arg;
7173 g_assert (i < iter->sig->param_count);
7175 return iter->sig->params [i];
7178 ICALL_EXPORT MonoObject*
7179 mono_TypedReference_ToObject (MonoTypedRef* tref)
7181 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7182 MonoObject** objp = (MonoObject **)tref->value;
7186 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
7189 ICALL_EXPORT MonoTypedRef
7190 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7193 MonoReflectionField *f;
7195 MonoType *ftype = NULL;
7199 memset (&res, 0, sizeof (res));
7202 g_assert (mono_array_length (fields) > 0);
7204 klass = target->vtable->klass;
7206 for (i = 0; i < mono_array_length (fields); ++i) {
7207 f = mono_array_get (fields, MonoReflectionField*, i);
7209 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7212 if (f->field->parent != klass) {
7213 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7217 p = (guint8*)target + f->field->offset;
7219 p += f->field->offset - sizeof (MonoObject);
7220 klass = mono_class_from_mono_type (f->field->type);
7221 ftype = f->field->type;
7225 res.klass = mono_class_from_mono_type (ftype);
7232 prelink_method (MonoMethod *method)
7234 const char *exc_class, *exc_arg;
7235 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7237 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7239 mono_raise_exception(
7240 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7242 /* create the wrapper, too? */
7246 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7248 prelink_method (method->method);
7252 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7254 MonoClass *klass = mono_class_from_mono_type (type->type);
7256 gpointer iter = NULL;
7258 mono_class_init_or_throw (klass);
7260 while ((m = mono_class_get_methods (klass, &iter)))
7264 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7266 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7267 gint32 const **exponents,
7268 gunichar2 const **digitLowerTable,
7269 gunichar2 const **digitUpperTable,
7270 gint64 const **tenPowersList,
7271 gint32 const **decHexDigits)
7273 *mantissas = Formatter_MantissaBitsTable;
7274 *exponents = Formatter_TensExponentTable;
7275 *digitLowerTable = Formatter_DigitLowerTable;
7276 *digitUpperTable = Formatter_DigitUpperTable;
7277 *tenPowersList = Formatter_TenPowersList;
7278 *decHexDigits = Formatter_DecHexDigits;
7282 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7283 * and avoid useless allocations.
7288 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7291 MonoReflectionType *rt;
7294 for (i = 0; i < type->num_mods; ++i) {
7295 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7300 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7302 for (i = 0; i < type->num_mods; ++i) {
7303 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7304 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
7305 mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */
7307 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, &error);
7308 mono_error_raise_exception (&error);
7310 mono_array_setref (res, count, rt);
7317 ICALL_EXPORT MonoArray*
7318 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7320 MonoType *type = param->ClassImpl->type;
7321 MonoClass *member_class = mono_object_class (param->MemberImpl);
7322 MonoMethod *method = NULL;
7325 MonoMethodSignature *sig;
7327 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7328 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7329 method = rmethod->method;
7330 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7331 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7332 if (!(method = prop->property->get))
7333 method = prop->property->set;
7336 char *type_name = mono_type_get_full_name (member_class);
7337 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7338 MonoException *ex = mono_get_exception_not_supported (msg);
7341 mono_set_pending_exception (ex);
7345 image = method->klass->image;
7346 pos = param->PositionImpl;
7347 sig = mono_method_signature (method);
7351 type = sig->params [pos];
7353 return type_array_from_modifiers (image, type, optional);
7357 get_property_type (MonoProperty *prop)
7359 MonoMethodSignature *sig;
7361 sig = mono_method_signature (prop->get);
7363 } else if (prop->set) {
7364 sig = mono_method_signature (prop->set);
7365 return sig->params [sig->param_count - 1];
7370 ICALL_EXPORT MonoArray*
7371 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7373 MonoType *type = get_property_type (property->property);
7374 MonoImage *image = property->klass->image;
7378 return type_array_from_modifiers (image, type, optional);
7382 *Construct a MonoType suited to be used to decode a constant blob object.
7384 * @type is the target type which will be constructed
7385 * @blob_type is the blob type, for example, that comes from the constant table
7386 * @real_type is the expected constructed type.
7389 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7391 type->type = blob_type;
7392 type->data.klass = NULL;
7393 if (blob_type == MONO_TYPE_CLASS)
7394 type->data.klass = mono_defaults.object_class;
7395 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7396 /* For enums, we need to use the base type */
7397 type->type = MONO_TYPE_VALUETYPE;
7398 type->data.klass = mono_class_from_mono_type (real_type);
7400 type->data.klass = mono_class_from_mono_type (real_type);
7403 ICALL_EXPORT MonoObject*
7404 property_info_get_default_value (MonoReflectionProperty *property)
7407 MonoProperty *prop = property->property;
7408 MonoType *type = get_property_type (prop);
7409 MonoDomain *domain = mono_object_domain (property);
7410 MonoTypeEnum def_type;
7411 const char *def_value;
7414 mono_class_init (prop->parent);
7416 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7417 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7421 def_value = mono_class_get_property_default_value (prop, &def_type);
7423 mono_type_from_blob_type (&blob_type, def_type, type);
7424 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7429 ICALL_EXPORT MonoBoolean
7430 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7432 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7433 MonoCustomAttrInfo *cinfo;
7436 mono_class_init_or_throw (attr_class);
7438 cinfo = mono_reflection_get_custom_attrs_info (obj);
7441 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7443 mono_custom_attrs_free (cinfo);
7447 ICALL_EXPORT MonoArray*
7448 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7450 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7455 mono_class_init_or_throw (attr_class);
7457 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7458 if (!mono_error_ok (&error)) {
7459 mono_error_set_pending_exception (&error);
7463 if (mono_loader_get_last_error ()) {
7464 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7471 ICALL_EXPORT MonoString*
7472 ves_icall_Mono_Runtime_GetDisplayName (void)
7475 MonoString *display_name;
7477 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7478 display_name = mono_string_new (mono_domain_get (), info);
7480 return display_name;
7483 ICALL_EXPORT MonoString*
7484 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7486 MonoString *message;
7490 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7491 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7494 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7496 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7503 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7506 char *path_str = mono_string_to_utf8 (path);
7508 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7516 #ifndef DISABLE_ICALL_TABLES
7518 #define ICALL_TYPE(id,name,first)
7519 #define ICALL(id,name,func) Icall_ ## id,
7522 #include "metadata/icall-def.h"
7528 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7529 #define ICALL(id,name,func)
7531 #include "metadata/icall-def.h"
7537 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7538 #define ICALL(id,name,func)
7540 guint16 first_icall;
7543 static const IcallTypeDesc
7544 icall_type_descs [] = {
7545 #include "metadata/icall-def.h"
7549 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7552 #define ICALL_TYPE(id,name,first)
7555 #ifdef HAVE_ARRAY_ELEM_INIT
7556 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7557 #define MSGSTRFIELD1(line) str##line
7559 static const struct msgstrtn_t {
7560 #define ICALL(id,name,func)
7562 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7563 #include "metadata/icall-def.h"
7565 } icall_type_names_str = {
7566 #define ICALL_TYPE(id,name,first) (name),
7567 #include "metadata/icall-def.h"
7570 static const guint16 icall_type_names_idx [] = {
7571 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7572 #include "metadata/icall-def.h"
7575 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7577 static const struct msgstr_t {
7579 #define ICALL_TYPE(id,name,first)
7580 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7581 #include "metadata/icall-def.h"
7583 } icall_names_str = {
7584 #define ICALL(id,name,func) (name),
7585 #include "metadata/icall-def.h"
7588 static const guint16 icall_names_idx [] = {
7589 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7590 #include "metadata/icall-def.h"
7593 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7599 #define ICALL_TYPE(id,name,first) name,
7600 #define ICALL(id,name,func)
7601 static const char* const
7602 icall_type_names [] = {
7603 #include "metadata/icall-def.h"
7607 #define icall_type_name_get(id) (icall_type_names [(id)])
7611 #define ICALL_TYPE(id,name,first)
7612 #define ICALL(id,name,func) name,
7613 static const char* const
7615 #include "metadata/icall-def.h"
7618 #define icall_name_get(id) icall_names [(id)]
7620 #endif /* !HAVE_ARRAY_ELEM_INIT */
7624 #define ICALL_TYPE(id,name,first)
7625 #define ICALL(id,name,func) func,
7626 static const gconstpointer
7627 icall_functions [] = {
7628 #include "metadata/icall-def.h"
7632 #ifdef ENABLE_ICALL_SYMBOL_MAP
7635 #define ICALL_TYPE(id,name,first)
7636 #define ICALL(id,name,func) #func,
7637 static const gconstpointer
7638 icall_symbols [] = {
7639 #include "metadata/icall-def.h"
7644 #endif /* DISABLE_ICALL_TABLES */
7646 static mono_mutex_t icall_mutex;
7647 static GHashTable *icall_hash = NULL;
7648 static GHashTable *jit_icall_hash_name = NULL;
7649 static GHashTable *jit_icall_hash_addr = NULL;
7652 mono_icall_init (void)
7654 #ifndef DISABLE_ICALL_TABLES
7657 /* check that tables are sorted: disable in release */
7660 const char *prev_class = NULL;
7661 const char *prev_method;
7663 for (i = 0; i < Icall_type_num; ++i) {
7664 const IcallTypeDesc *desc;
7667 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7668 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7669 prev_class = icall_type_name_get (i);
7670 desc = &icall_type_descs [i];
7671 num_icalls = icall_desc_num_icalls (desc);
7672 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7673 for (j = 0; j < num_icalls; ++j) {
7674 const char *methodn = icall_name_get (desc->first_icall + j);
7675 if (prev_method && strcmp (prev_method, methodn) >= 0)
7676 g_print ("method %s should come before method %s\n", methodn, prev_method);
7677 prev_method = methodn;
7683 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7684 mono_os_mutex_init (&icall_mutex);
7688 mono_icall_lock (void)
7690 mono_locks_os_acquire (&icall_mutex, IcallLock);
7694 mono_icall_unlock (void)
7696 mono_locks_os_release (&icall_mutex, IcallLock);
7700 mono_icall_cleanup (void)
7702 g_hash_table_destroy (icall_hash);
7703 g_hash_table_destroy (jit_icall_hash_name);
7704 g_hash_table_destroy (jit_icall_hash_addr);
7705 mono_os_mutex_destroy (&icall_mutex);
7709 mono_add_internal_call (const char *name, gconstpointer method)
7713 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7715 mono_icall_unlock ();
7718 #ifndef DISABLE_ICALL_TABLES
7720 #ifdef HAVE_ARRAY_ELEM_INIT
7722 compare_method_imap (const void *key, const void *elem)
7724 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7725 return strcmp (key, method_name);
7729 find_method_icall (const IcallTypeDesc *imap, const char *name)
7731 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);
7734 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7738 compare_class_imap (const void *key, const void *elem)
7740 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7741 return strcmp (key, class_name);
7744 static const IcallTypeDesc*
7745 find_class_icalls (const char *name)
7747 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);
7750 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7753 #else /* HAVE_ARRAY_ELEM_INIT */
7756 compare_method_imap (const void *key, const void *elem)
7758 const char** method_name = (const char**)elem;
7759 return strcmp (key, *method_name);
7763 find_method_icall (const IcallTypeDesc *imap, const char *name)
7765 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7768 return (gpointer)icall_functions [(nameslot - icall_names)];
7772 compare_class_imap (const void *key, const void *elem)
7774 const char** class_name = (const char**)elem;
7775 return strcmp (key, *class_name);
7778 static const IcallTypeDesc*
7779 find_class_icalls (const char *name)
7781 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7784 return &icall_type_descs [nameslot - icall_type_names];
7787 #endif /* HAVE_ARRAY_ELEM_INIT */
7789 #endif /* DISABLE_ICALL_TABLES */
7792 * we should probably export this as an helper (handle nested types).
7793 * Returns the number of chars written in buf.
7796 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7798 int nspacelen, cnamelen;
7799 nspacelen = strlen (klass->name_space);
7800 cnamelen = strlen (klass->name);
7801 if (nspacelen + cnamelen + 2 > bufsize)
7804 memcpy (buf, klass->name_space, nspacelen);
7805 buf [nspacelen ++] = '.';
7807 memcpy (buf + nspacelen, klass->name, cnamelen);
7808 buf [nspacelen + cnamelen] = 0;
7809 return nspacelen + cnamelen;
7812 #ifdef DISABLE_ICALL_TABLES
7814 no_icall_table (void)
7816 g_assert_not_reached ();
7821 mono_lookup_internal_call (MonoMethod *method)
7826 int typelen = 0, mlen, siglen;
7828 #ifndef DISABLE_ICALL_TABLES
7829 const IcallTypeDesc *imap = NULL;
7832 g_assert (method != NULL);
7834 if (method->is_inflated)
7835 method = ((MonoMethodInflated *) method)->declaring;
7837 if (method->klass->nested_in) {
7838 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7842 mname [pos++] = '/';
7845 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7851 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7856 #ifndef DISABLE_ICALL_TABLES
7857 imap = find_class_icalls (mname);
7860 mname [typelen] = ':';
7861 mname [typelen + 1] = ':';
7863 mlen = strlen (method->name);
7864 memcpy (mname + typelen + 2, method->name, mlen);
7865 sigstart = mname + typelen + 2 + mlen;
7868 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7869 siglen = strlen (tmpsig);
7870 if (typelen + mlen + siglen + 6 > sizeof (mname))
7873 memcpy (sigstart + 1, tmpsig, siglen);
7874 sigstart [siglen + 1] = ')';
7875 sigstart [siglen + 2] = 0;
7880 res = g_hash_table_lookup (icall_hash, mname);
7882 mono_icall_unlock ();;
7885 /* try without signature */
7887 res = g_hash_table_lookup (icall_hash, mname);
7889 mono_icall_unlock ();
7893 #ifdef DISABLE_ICALL_TABLES
7894 mono_icall_unlock ();
7895 /* Fail only when the result is actually used */
7896 /* mono_marshal_get_native_wrapper () depends on this */
7897 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
7898 return ves_icall_System_String_ctor_RedirectToCreateString;
7900 return no_icall_table;
7902 /* it wasn't found in the static call tables */
7904 mono_icall_unlock ();
7907 res = find_method_icall (imap, sigstart - mlen);
7909 mono_icall_unlock ();
7912 /* try _with_ signature */
7914 res = find_method_icall (imap, sigstart - mlen);
7916 mono_icall_unlock ();
7920 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7921 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7922 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7923 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
7924 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");
7925 g_print ("If you see other errors or faults after this message they are probably related\n");
7926 g_print ("and you need to fix your mono install first.\n");
7928 mono_icall_unlock ();
7934 #ifdef ENABLE_ICALL_SYMBOL_MAP
7936 func_cmp (gconstpointer key, gconstpointer p)
7938 return (gsize)key - (gsize)*(gsize*)p;
7943 * mono_lookup_icall_symbol:
7945 * Given the icall METHOD, returns its C symbol.
7948 mono_lookup_icall_symbol (MonoMethod *m)
7950 #ifdef DISABLE_ICALL_TABLES
7951 g_assert_not_reached ();
7954 #ifdef ENABLE_ICALL_SYMBOL_MAP
7958 static gconstpointer *functions_sorted;
7959 static const char**symbols_sorted;
7960 static gboolean inited;
7965 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7966 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7967 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7968 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7969 /* Bubble sort the two arrays */
7973 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
7974 if (functions_sorted [i] > functions_sorted [i + 1]) {
7977 tmp = functions_sorted [i];
7978 functions_sorted [i] = functions_sorted [i + 1];
7979 functions_sorted [i + 1] = tmp;
7980 tmp = symbols_sorted [i];
7981 symbols_sorted [i] = symbols_sorted [i + 1];
7982 symbols_sorted [i + 1] = tmp;
7989 func = mono_lookup_internal_call (m);
7992 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
7996 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
7998 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
7999 g_assert_not_reached ();
8006 type_from_typename (char *type_name)
8008 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8010 if (!strcmp (type_name, "int"))
8011 klass = mono_defaults.int_class;
8012 else if (!strcmp (type_name, "ptr"))
8013 klass = mono_defaults.int_class;
8014 else if (!strcmp (type_name, "void"))
8015 klass = mono_defaults.void_class;
8016 else if (!strcmp (type_name, "int32"))
8017 klass = mono_defaults.int32_class;
8018 else if (!strcmp (type_name, "uint32"))
8019 klass = mono_defaults.uint32_class;
8020 else if (!strcmp (type_name, "int8"))
8021 klass = mono_defaults.sbyte_class;
8022 else if (!strcmp (type_name, "uint8"))
8023 klass = mono_defaults.byte_class;
8024 else if (!strcmp (type_name, "int16"))
8025 klass = mono_defaults.int16_class;
8026 else if (!strcmp (type_name, "uint16"))
8027 klass = mono_defaults.uint16_class;
8028 else if (!strcmp (type_name, "long"))
8029 klass = mono_defaults.int64_class;
8030 else if (!strcmp (type_name, "ulong"))
8031 klass = mono_defaults.uint64_class;
8032 else if (!strcmp (type_name, "float"))
8033 klass = mono_defaults.single_class;
8034 else if (!strcmp (type_name, "double"))
8035 klass = mono_defaults.double_class;
8036 else if (!strcmp (type_name, "object"))
8037 klass = mono_defaults.object_class;
8038 else if (!strcmp (type_name, "obj"))
8039 klass = mono_defaults.object_class;
8040 else if (!strcmp (type_name, "string"))
8041 klass = mono_defaults.string_class;
8042 else if (!strcmp (type_name, "bool"))
8043 klass = mono_defaults.boolean_class;
8044 else if (!strcmp (type_name, "boolean"))
8045 klass = mono_defaults.boolean_class;
8047 g_error ("%s", type_name);
8048 g_assert_not_reached ();
8050 return &klass->byval_arg;
8054 * LOCKING: Take the corlib image lock.
8056 MonoMethodSignature*
8057 mono_create_icall_signature (const char *sigstr)
8062 MonoMethodSignature *res, *res2;
8063 MonoImage *corlib = mono_defaults.corlib;
8065 mono_image_lock (corlib);
8066 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8067 mono_image_unlock (corlib);
8072 parts = g_strsplit (sigstr, " ", 256);
8081 res = mono_metadata_signature_alloc (corlib, len - 1);
8086 * Under windows, the default pinvoke calling convention is STDCALL but
8089 res->call_convention = MONO_CALL_C;
8092 res->ret = type_from_typename (parts [0]);
8093 for (i = 1; i < len; ++i) {
8094 res->params [i - 1] = type_from_typename (parts [i]);
8099 mono_image_lock (corlib);
8100 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8102 res = res2; /*Value is allocated in the image pool*/
8104 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8105 mono_image_unlock (corlib);
8111 mono_find_jit_icall_by_name (const char *name)
8113 MonoJitICallInfo *info;
8114 g_assert (jit_icall_hash_name);
8117 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8118 mono_icall_unlock ();
8123 mono_find_jit_icall_by_addr (gconstpointer addr)
8125 MonoJitICallInfo *info;
8126 g_assert (jit_icall_hash_addr);
8129 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8130 mono_icall_unlock ();
8136 * mono_get_jit_icall_info:
8138 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8139 * caller should access it while holding the icall lock.
8142 mono_get_jit_icall_info (void)
8144 return jit_icall_hash_name;
8148 * mono_lookup_jit_icall_symbol:
8150 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8153 mono_lookup_jit_icall_symbol (const char *name)
8155 MonoJitICallInfo *info;
8156 const char *res = NULL;
8159 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8161 res = info->c_symbol;
8162 mono_icall_unlock ();
8167 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8170 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8171 mono_icall_unlock ();
8175 * 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
8176 * icalls without wrappers in some cases.
8179 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8181 MonoJitICallInfo *info;
8188 if (!jit_icall_hash_name) {
8189 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8190 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8193 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8194 g_warning ("jit icall already defined \"%s\"\n", name);
8195 g_assert_not_reached ();
8198 info = g_new0 (MonoJitICallInfo, 1);
8203 info->c_symbol = c_symbol;
8204 info->no_raise = no_raise;
8207 info->wrapper = func;
8209 info->wrapper = NULL;
8212 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8213 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8215 mono_icall_unlock ();
8220 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8222 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);