5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
9 * Aleksey Kliger (aleksey@xamarin.com)
11 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
12 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
24 #ifdef HAVE_SYS_TIME_H
30 #if defined (HOST_WIN32)
33 #if defined (HAVE_WCHAR_H)
37 #include "mono/utils/mono-membar.h"
38 #include <mono/metadata/object.h>
39 #include <mono/metadata/threads.h>
40 #include <mono/metadata/threads-types.h>
41 #include <mono/metadata/threadpool-ms.h>
42 #include <mono/metadata/threadpool-ms-io.h>
43 #include <mono/metadata/monitor.h>
44 #include <mono/metadata/reflection.h>
45 #include <mono/metadata/assembly.h>
46 #include <mono/metadata/tabledefs.h>
47 #include <mono/metadata/exception.h>
48 #include <mono/metadata/file-io.h>
49 #include <mono/metadata/console-io.h>
50 #include <mono/metadata/mono-route.h>
51 #include <mono/metadata/socket-io.h>
52 #include <mono/metadata/mono-endian.h>
53 #include <mono/metadata/tokentype.h>
54 #include <mono/metadata/domain-internals.h>
55 #include <mono/metadata/metadata-internals.h>
56 #include <mono/metadata/class-internals.h>
57 #include <mono/metadata/reflection-internals.h>
58 #include <mono/metadata/marshal.h>
59 #include <mono/metadata/gc-internals.h>
60 #include <mono/metadata/mono-gc.h>
61 #include <mono/metadata/rand.h>
62 #include <mono/metadata/sysmath.h>
63 #include <mono/metadata/string-icalls.h>
64 #include <mono/metadata/debug-helpers.h>
65 #include <mono/metadata/process.h>
66 #include <mono/metadata/environment.h>
67 #include <mono/metadata/profiler-private.h>
68 #include <mono/metadata/locales.h>
69 #include <mono/metadata/filewatcher.h>
70 #include <mono/metadata/security.h>
71 #include <mono/metadata/mono-config.h>
72 #include <mono/metadata/cil-coff.h>
73 #include <mono/metadata/number-formatter.h>
74 #include <mono/metadata/security-manager.h>
75 #include <mono/metadata/security-core-clr.h>
76 #include <mono/metadata/mono-perfcounters.h>
77 #include <mono/metadata/mono-debug.h>
78 #include <mono/metadata/mono-ptr-array.h>
79 #include <mono/metadata/verify-internals.h>
80 #include <mono/metadata/runtime.h>
81 #include <mono/metadata/file-mmap.h>
82 #include <mono/metadata/seq-points-data.h>
83 #include <mono/io-layer/io-layer.h>
84 #include <mono/utils/monobitset.h>
85 #include <mono/utils/mono-time.h>
86 #include <mono/utils/mono-proclib.h>
87 #include <mono/utils/mono-string.h>
88 #include <mono/utils/mono-error-internals.h>
89 #include <mono/utils/mono-mmap.h>
90 #include <mono/utils/mono-io-portability.h>
91 #include <mono/utils/mono-digest.h>
92 #include <mono/utils/bsearch.h>
93 #include <mono/utils/mono-os-mutex.h>
94 #include <mono/utils/mono-threads.h>
96 #if defined (HOST_WIN32)
100 #include "decimal-ms.h"
101 #include "number-ms.h"
103 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
104 #include <sys/utsname.h>
107 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
109 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
112 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
114 static inline MonoBoolean
115 is_generic_parameter (MonoType *type)
117 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
121 mono_class_init_or_throw (MonoClass *klass)
123 if (!mono_class_init (klass))
124 mono_raise_exception (mono_class_get_exception_for_failure (klass));
127 ICALL_EXPORT MonoObject *
128 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
134 ac = (MonoClass *)arr->obj.vtable->klass;
136 esize = mono_array_element_size (ac);
137 ea = (gpointer*)((char*)arr->vector + (pos * esize));
139 if (ac->element_class->valuetype)
140 return mono_value_box (arr->obj.vtable->domain, ac->element_class, ea);
142 return (MonoObject *)*ea;
145 ICALL_EXPORT MonoObject *
146 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
152 MONO_CHECK_ARG_NULL (idxs, NULL);
155 ic = (MonoClass *)io->obj.vtable->klass;
157 ac = (MonoClass *)arr->obj.vtable->klass;
159 g_assert (ic->rank == 1);
160 if (io->bounds != NULL || io->max_length != ac->rank) {
161 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
165 ind = (gint32 *)io->vector;
167 if (arr->bounds == NULL) {
168 if (*ind < 0 || *ind >= arr->max_length) {
169 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
173 return ves_icall_System_Array_GetValueImpl (arr, *ind);
176 for (i = 0; i < ac->rank; i++) {
177 if ((ind [i] < arr->bounds [i].lower_bound) ||
178 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
179 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
184 pos = ind [0] - arr->bounds [0].lower_bound;
185 for (i = 1; i < ac->rank; i++)
186 pos = pos * arr->bounds [i].length + ind [i] -
187 arr->bounds [i].lower_bound;
189 return ves_icall_System_Array_GetValueImpl (arr, pos);
193 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
195 MonoClass *ac, *vc, *ec;
205 vc = value->vtable->klass;
209 ac = arr->obj.vtable->klass;
210 ec = ac->element_class;
212 esize = mono_array_element_size (ac);
213 ea = (gpointer*)((char*)arr->vector + (pos * esize));
214 va = (gpointer*)((char*)value + sizeof (MonoObject));
216 if (mono_class_is_nullable (ec)) {
217 mono_nullable_init ((guint8*)ea, value, ec);
222 mono_gc_bzero_atomic (ea, esize);
226 #define NO_WIDENING_CONVERSION G_STMT_START{\
227 mono_set_pending_exception (mono_get_exception_argument ( \
228 "value", "not a widening conversion")); \
232 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
233 if (esize < vsize + (extra)) { \
234 mono_set_pending_exception (mono_get_exception_argument ( \
235 "value", "not a widening conversion")); \
240 #define INVALID_CAST G_STMT_START{ \
241 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
242 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
246 /* Check element (destination) type. */
247 switch (ec->byval_arg.type) {
248 case MONO_TYPE_STRING:
249 switch (vc->byval_arg.type) {
250 case MONO_TYPE_STRING:
256 case MONO_TYPE_BOOLEAN:
257 switch (vc->byval_arg.type) {
258 case MONO_TYPE_BOOLEAN:
271 NO_WIDENING_CONVERSION;
280 if (!ec->valuetype) {
281 if (!mono_object_isinst (value, ec))
283 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
287 if (mono_object_isinst (value, ec)) {
288 if (ec->has_references)
289 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
291 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
298 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
300 et = ec->byval_arg.type;
301 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
302 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
304 vt = vc->byval_arg.type;
305 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
306 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
308 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
314 case MONO_TYPE_CHAR: \
315 CHECK_WIDENING_CONVERSION(0); \
316 *(etype *) ea = (etype) u64; \
318 /* You can't assign a signed value to an unsigned array. */ \
323 /* You can't assign a floating point number to an integer array. */ \
326 NO_WIDENING_CONVERSION; \
330 #define ASSIGN_SIGNED(etype) G_STMT_START{\
336 CHECK_WIDENING_CONVERSION(0); \
337 *(etype *) ea = (etype) i64; \
339 /* You can assign an unsigned value to a signed array if the array's */ \
340 /* element size is larger than the value size. */ \
345 case MONO_TYPE_CHAR: \
346 CHECK_WIDENING_CONVERSION(1); \
347 *(etype *) ea = (etype) u64; \
349 /* You can't assign a floating point number to an integer array. */ \
352 NO_WIDENING_CONVERSION; \
356 #define ASSIGN_REAL(etype) G_STMT_START{\
360 CHECK_WIDENING_CONVERSION(0); \
361 *(etype *) ea = (etype) r64; \
363 /* All integer values fit into a floating point array, so we don't */ \
364 /* need to CHECK_WIDENING_CONVERSION here. */ \
369 *(etype *) ea = (etype) i64; \
375 case MONO_TYPE_CHAR: \
376 *(etype *) ea = (etype) u64; \
383 u64 = *(guint8 *) va;
386 u64 = *(guint16 *) va;
389 u64 = *(guint32 *) va;
392 u64 = *(guint64 *) va;
398 i64 = *(gint16 *) va;
401 i64 = *(gint32 *) va;
404 i64 = *(gint64 *) va;
407 r64 = *(gfloat *) va;
410 r64 = *(gdouble *) va;
413 u64 = *(guint16 *) va;
415 case MONO_TYPE_BOOLEAN:
416 /* Boolean is only compatible with itself. */
429 NO_WIDENING_CONVERSION;
436 /* If we can't do a direct copy, let's try a widening conversion. */
439 ASSIGN_UNSIGNED (guint16);
441 ASSIGN_UNSIGNED (guint8);
443 ASSIGN_UNSIGNED (guint16);
445 ASSIGN_UNSIGNED (guint32);
447 ASSIGN_UNSIGNED (guint64);
449 ASSIGN_SIGNED (gint8);
451 ASSIGN_SIGNED (gint16);
453 ASSIGN_SIGNED (gint32);
455 ASSIGN_SIGNED (gint64);
457 ASSIGN_REAL (gfloat);
459 ASSIGN_REAL (gdouble);
463 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
467 #undef NO_WIDENING_CONVERSION
468 #undef CHECK_WIDENING_CONVERSION
469 #undef ASSIGN_UNSIGNED
475 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
481 MONO_CHECK_ARG_NULL (idxs,);
483 ic = idxs->obj.vtable->klass;
484 ac = arr->obj.vtable->klass;
486 g_assert (ic->rank == 1);
487 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
488 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
492 ind = (gint32 *)idxs->vector;
494 if (arr->bounds == NULL) {
495 if (*ind < 0 || *ind >= arr->max_length) {
496 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
500 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
504 for (i = 0; i < ac->rank; i++)
505 if ((ind [i] < arr->bounds [i].lower_bound) ||
506 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
507 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
511 pos = ind [0] - arr->bounds [0].lower_bound;
512 for (i = 1; i < ac->rank; i++)
513 pos = pos * arr->bounds [i].length + ind [i] -
514 arr->bounds [i].lower_bound;
516 ves_icall_System_Array_SetValueImpl (arr, value, pos);
519 ICALL_EXPORT MonoArray *
520 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
523 MonoClass *aklass, *klass;
526 gboolean bounded = FALSE;
528 MONO_CHECK_ARG_NULL (type, NULL);
529 MONO_CHECK_ARG_NULL (lengths, NULL);
531 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
533 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
535 for (i = 0; i < mono_array_length (lengths); i++) {
536 if (mono_array_get (lengths, gint32, i) < 0) {
537 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
542 klass = mono_class_from_mono_type (type->type);
543 mono_class_init_or_throw (klass);
545 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
546 /* vectors are not the same as one dimensional arrays with no-zero bounds */
551 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
553 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
554 for (i = 0; i < aklass->rank; ++i) {
555 sizes [i] = mono_array_get (lengths, guint32, i);
557 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
559 sizes [i + aklass->rank] = 0;
562 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
563 mono_error_set_pending_exception (&error);
568 ICALL_EXPORT MonoArray *
569 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
572 MonoClass *aklass, *klass;
575 gboolean bounded = FALSE;
577 MONO_CHECK_ARG_NULL (type, NULL);
578 MONO_CHECK_ARG_NULL (lengths, NULL);
580 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
582 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
584 for (i = 0; i < mono_array_length (lengths); i++) {
585 if ((mono_array_get (lengths, gint64, i) < 0) ||
586 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
587 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
592 klass = mono_class_from_mono_type (type->type);
593 mono_class_init_or_throw (klass);
595 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
596 /* vectors are not the same as one dimensional arrays with no-zero bounds */
601 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
603 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
604 for (i = 0; i < aklass->rank; ++i) {
605 sizes [i] = mono_array_get (lengths, guint64, i);
607 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
609 sizes [i + aklass->rank] = 0;
612 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
613 mono_error_set_pending_exception (&error);
619 ves_icall_System_Array_GetRank (MonoObject *arr)
621 return arr->vtable->klass->rank;
625 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
627 gint32 rank = arr->obj.vtable->klass->rank;
630 if ((dimension < 0) || (dimension >= rank)) {
631 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
635 if (arr->bounds == NULL)
636 length = arr->max_length;
638 length = arr->bounds [dimension].length;
640 #ifdef MONO_BIG_ARRAYS
641 if (length > G_MAXINT32) {
642 mono_set_pending_exception (mono_get_exception_overflow ());
650 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
652 gint32 rank = arr->obj.vtable->klass->rank;
654 if ((dimension < 0) || (dimension >= rank)) {
655 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
659 if (arr->bounds == NULL)
660 return arr->max_length;
662 return arr->bounds [dimension].length;
666 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
668 gint32 rank = arr->obj.vtable->klass->rank;
670 if ((dimension < 0) || (dimension >= rank)) {
671 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
675 if (arr->bounds == NULL)
678 return arr->bounds [dimension].lower_bound;
682 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
684 int sz = mono_array_element_size (mono_object_class (arr));
685 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
688 ICALL_EXPORT gboolean
689 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
694 MonoVTable *src_vtable;
695 MonoVTable *dest_vtable;
696 MonoClass *src_class;
697 MonoClass *dest_class;
699 src_vtable = source->obj.vtable;
700 dest_vtable = dest->obj.vtable;
702 if (src_vtable->rank != dest_vtable->rank)
705 if (source->bounds || dest->bounds)
708 /* there's no integer overflow since mono_array_length returns an unsigned integer */
709 if ((dest_idx + length > mono_array_length_fast (dest)) ||
710 (source_idx + length > mono_array_length_fast (source)))
713 src_class = src_vtable->klass->element_class;
714 dest_class = dest_vtable->klass->element_class;
717 * Handle common cases.
720 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
721 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
723 if (src_class == mono_defaults.object_class && dest_class->valuetype)
726 /* Check if we're copying a char[] <==> (u)short[] */
727 if (src_class != dest_class) {
728 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
731 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
732 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
736 if (dest_class->valuetype) {
737 element_size = mono_array_element_size (source->obj.vtable->klass);
738 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
739 if (dest_class->has_references) {
740 mono_value_copy_array (dest, dest_idx, source_addr, length);
742 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
743 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
746 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
753 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
759 ac = (MonoClass *)arr->obj.vtable->klass;
761 esize = mono_array_element_size (ac);
762 ea = (gpointer*)((char*)arr->vector + (pos * esize));
764 mono_gc_memmove_atomic (value, ea, esize);
768 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
774 ac = (MonoClass *)arr->obj.vtable->klass;
775 ec = ac->element_class;
777 esize = mono_array_element_size (ac);
778 ea = (gpointer*)((char*)arr->vector + (pos * esize));
780 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
781 g_assert (esize == sizeof (gpointer));
782 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
784 g_assert (ec->inited);
785 g_assert (esize == mono_class_value_size (ec, NULL));
786 if (ec->has_references)
787 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
789 mono_gc_memmove_atomic (ea, value, esize);
794 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
796 MonoClass *klass = array->obj.vtable->klass;
797 guint32 size = mono_array_element_size (klass);
798 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
800 const char *field_data;
802 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
803 MonoException *exc = mono_get_exception_argument("array",
804 "Cannot initialize array of non-primitive type.");
805 mono_set_pending_exception (exc);
809 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
810 MonoException *exc = mono_get_exception_argument("field_handle",
811 "Field doesn't have an RVA");
812 mono_set_pending_exception (exc);
816 size *= array->max_length;
817 field_data = mono_field_get_data (field_handle);
819 if (size > mono_type_size (field_handle->type, &align)) {
820 MonoException *exc = mono_get_exception_argument("field_handle",
821 "Field not large enough to fill array");
822 mono_set_pending_exception (exc);
826 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
828 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
829 guint ## n *src = (guint ## n *) field_data; \
831 nEnt = (size / sizeof(guint ## n)); \
833 for (i = 0; i < nEnt; i++) { \
834 data[i] = read ## n (&src[i]); \
838 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
840 switch (type->type) {
857 memcpy (mono_array_addr (array, char, 0), field_data, size);
861 memcpy (mono_array_addr (array, char, 0), field_data, size);
866 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
868 return offsetof (MonoString, chars);
871 ICALL_EXPORT MonoObject *
872 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
874 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
878 MonoObject *ret = mono_object_clone_checked (obj, &error);
879 mono_error_set_pending_exception (&error);
886 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
891 MONO_CHECK_ARG_NULL (handle,);
893 klass = mono_class_from_mono_type (handle);
894 MONO_CHECK_ARG (handle, klass,);
896 if (klass->generic_container)
899 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
901 /* This will call the type constructor */
902 mono_runtime_class_init (vtable);
906 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
910 mono_image_check_for_module_cctor (image);
911 if (image->has_module_cctor) {
912 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
913 if (!mono_error_ok (&error)) {
914 mono_error_set_pending_exception (&error);
917 /*It's fine to raise the exception here*/
918 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
922 ICALL_EXPORT MonoBoolean
923 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
928 /* later make this configurable and per-arch */
929 int min_size = 4096 * 4 * sizeof (void*);
930 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
931 /* if we have no info we are optimistic and assume there is enough room */
935 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
939 current = (guint8 *)&stack_addr;
940 if (current > stack_addr) {
941 if ((current - stack_addr) < min_size)
944 if (current - (stack_addr - stack_size) < min_size)
950 ICALL_EXPORT MonoObject *
951 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
954 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
955 mono_error_set_pending_exception (&error);
961 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
964 MonoObject **values = NULL;
967 gint32 result = (int)(gsize)mono_defaults.int32_class;
968 MonoClassField* field;
971 klass = mono_object_class (this_obj);
973 if (mono_class_num_fields (klass) == 0)
977 * Compute the starting value of the hashcode for fields of primitive
978 * types, and return the remaining fields in an array to the managed side.
979 * This way, we can avoid costly reflection operations in managed code.
982 while ((field = mono_class_get_fields (klass, &iter))) {
983 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
985 if (mono_field_is_deleted (field))
987 /* FIXME: Add more types */
988 switch (field->type->type) {
990 result ^= *(gint32*)((guint8*)this_obj + field->offset);
992 case MONO_TYPE_STRING: {
994 s = *(MonoString**)((guint8*)this_obj + field->offset);
996 result ^= mono_string_hash (s);
1001 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1002 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1003 values [count++] = o;
1009 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1010 for (i = 0; i < count; ++i)
1011 mono_array_setref (*fields, i, values [i]);
1018 ICALL_EXPORT MonoBoolean
1019 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1022 MonoObject **values = NULL;
1024 MonoClassField* field;
1028 MONO_CHECK_ARG_NULL (that, FALSE);
1030 if (this_obj->vtable != that->vtable)
1033 klass = mono_object_class (this_obj);
1035 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1036 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1039 * Do the comparison for fields of primitive type and return a result if
1040 * possible. Otherwise, return the remaining fields in an array to the
1041 * managed side. This way, we can avoid costly reflection operations in
1046 while ((field = mono_class_get_fields (klass, &iter))) {
1047 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1049 if (mono_field_is_deleted (field))
1051 /* FIXME: Add more types */
1052 switch (field->type->type) {
1055 case MONO_TYPE_BOOLEAN:
1056 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1061 case MONO_TYPE_CHAR:
1062 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1067 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1072 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1076 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1080 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1085 case MONO_TYPE_STRING: {
1086 MonoString *s1, *s2;
1087 guint32 s1len, s2len;
1088 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1089 s2 = *(MonoString**)((guint8*)that + field->offset);
1092 if ((s1 == NULL) || (s2 == NULL))
1094 s1len = mono_string_length (s1);
1095 s2len = mono_string_length (s2);
1099 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1105 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1106 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1107 values [count++] = o;
1108 o = mono_field_get_value_object (mono_object_domain (this_obj), field, that);
1109 values [count++] = o;
1112 if (klass->enumtype)
1113 /* enums only have one non-static field */
1119 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1120 for (i = 0; i < count; ++i)
1121 mono_array_setref_fast (*fields, i, values [i]);
1128 ICALL_EXPORT MonoReflectionType *
1129 ves_icall_System_Object_GetType (MonoObject *obj)
1132 MonoReflectionType *ret;
1133 #ifndef DISABLE_REMOTING
1134 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1135 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1138 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1140 mono_error_raise_exception (&error);
1146 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1148 mtype->type = &obj->vtable->klass->byval_arg;
1149 g_assert (mtype->type->type);
1153 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1155 MONO_CHECK_ARG_NULL (obj, 0);
1158 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1159 mono_error_raise_exception (&error);
1164 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1165 MonoReflectionMethod *method,
1166 MonoArray *opt_param_types)
1168 MONO_CHECK_ARG_NULL (method, 0);
1171 gint32 result = mono_image_create_method_token (
1172 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1173 mono_error_raise_exception (&error);
1178 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1181 mono_image_create_pefile (mb, file, &error);
1182 mono_error_raise_exception (&error);
1186 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1189 if (!mono_image_build_metadata (mb, &error))
1190 mono_error_raise_exception (&error);
1194 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1196 mono_image_register_token (mb->dynamic_image, token, obj);
1199 ICALL_EXPORT MonoObject*
1200 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1204 mono_loader_lock ();
1205 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1206 mono_loader_unlock ();
1212 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1214 MonoMethod **dest = (MonoMethod **)data;
1216 /* skip unmanaged frames */
1232 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1234 MonoMethod **dest = (MonoMethod **)data;
1236 /* skip unmanaged frames */
1241 if (!strcmp (m->klass->name_space, "System.Reflection"))
1250 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1252 MonoMethod **dest = (MonoMethod **)data;
1254 /* skip unmanaged frames */
1258 if (m->wrapper_type != MONO_WRAPPER_NONE)
1261 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1275 static MonoReflectionType *
1276 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase)
1279 MonoReflectionType *ret;
1280 MonoMethod *m, *dest;
1282 MonoType *type = NULL;
1283 MonoAssembly *assembly = NULL;
1284 gboolean type_resolve = FALSE;
1287 * We must compute the calling assembly as type loading must happen under a metadata context.
1288 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1289 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1291 m = mono_method_get_last_managed ();
1294 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1299 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1300 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1301 * to crash. This only seems to happen in some strange remoting
1302 * scenarios and I was unable to figure out what's happening there.
1303 * Dec 10, 2005 - Martin.
1307 assembly = dest->klass->image->assembly;
1308 type_resolve = TRUE;
1310 g_warning (G_STRLOC);
1313 if (info->assembly.name)
1314 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1318 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1319 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1322 if (!info->assembly.name && !type) /* try mscorlib */
1323 type = mono_reflection_get_type (NULL, info, ignoreCase, &type_resolve);
1325 if (assembly && !type && type_resolve) {
1326 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1327 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1333 ret = mono_type_get_object_checked (mono_domain_get (), type, &error);
1334 mono_error_raise_exception (&error); /* FIXME don't raise here */
1340 MonoReflectionType *
1341 mono_type_get (const char *str)
1343 char *copy = g_strdup (str);
1344 MonoTypeNameParse info;
1345 MonoReflectionType *type;
1348 parsedOk = mono_reflection_parse_type(copy, &info);
1350 mono_reflection_free_type_info (&info);
1355 type = type_from_parsed_name (&info, FALSE);
1357 mono_reflection_free_type_info (&info);
1364 ICALL_EXPORT MonoReflectionType*
1365 ves_icall_type_from_name (MonoString *name,
1366 MonoBoolean throwOnError,
1367 MonoBoolean ignoreCase)
1369 char *str = mono_string_to_utf8 (name);
1370 MonoTypeNameParse info;
1371 MonoReflectionType *type;
1374 parsedOk = mono_reflection_parse_type (str, &info);
1376 /* mono_reflection_parse_type() mangles the string */
1378 mono_reflection_free_type_info (&info);
1381 mono_set_pending_exception (mono_get_exception_argument("typeName", "failed parse"));
1386 type = type_from_parsed_name (&info, ignoreCase);
1388 mono_reflection_free_type_info (&info);
1392 MonoException *e = NULL;
1395 e = mono_get_exception_type_load (name, NULL);
1397 mono_loader_clear_error ();
1399 mono_set_pending_exception (e);
1408 ICALL_EXPORT MonoReflectionType*
1409 ves_icall_type_from_handle (MonoType *handle)
1412 MonoReflectionType *ret;
1413 MonoDomain *domain = mono_domain_get ();
1415 ret = mono_type_get_object_checked (domain, handle, &error);
1416 mono_error_raise_exception (&error);
1421 /* System.TypeCode */
1440 TYPECODE_STRING = 18
1443 ICALL_EXPORT guint32
1444 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1446 int t = type->type->type;
1448 if (type->type->byref)
1449 return TYPECODE_OBJECT;
1453 case MONO_TYPE_VOID:
1454 return TYPECODE_OBJECT;
1455 case MONO_TYPE_BOOLEAN:
1456 return TYPECODE_BOOLEAN;
1458 return TYPECODE_BYTE;
1460 return TYPECODE_SBYTE;
1462 return TYPECODE_UINT16;
1464 return TYPECODE_INT16;
1465 case MONO_TYPE_CHAR:
1466 return TYPECODE_CHAR;
1470 return TYPECODE_OBJECT;
1472 return TYPECODE_UINT32;
1474 return TYPECODE_INT32;
1476 return TYPECODE_UINT64;
1478 return TYPECODE_INT64;
1480 return TYPECODE_SINGLE;
1482 return TYPECODE_DOUBLE;
1483 case MONO_TYPE_VALUETYPE: {
1484 MonoClass *klass = type->type->data.klass;
1486 if (klass->enumtype) {
1487 t = mono_class_enum_basetype (klass)->type;
1489 } else if (mono_is_corlib_image (klass->image)) {
1490 if (strcmp (klass->name_space, "System") == 0) {
1491 if (strcmp (klass->name, "Decimal") == 0)
1492 return TYPECODE_DECIMAL;
1493 else if (strcmp (klass->name, "DateTime") == 0)
1494 return TYPECODE_DATETIME;
1497 return TYPECODE_OBJECT;
1499 case MONO_TYPE_STRING:
1500 return TYPECODE_STRING;
1501 case MONO_TYPE_SZARRAY:
1502 case MONO_TYPE_ARRAY:
1503 case MONO_TYPE_OBJECT:
1505 case MONO_TYPE_MVAR:
1506 case MONO_TYPE_TYPEDBYREF:
1507 return TYPECODE_OBJECT;
1508 case MONO_TYPE_CLASS:
1510 MonoClass *klass = type->type->data.klass;
1511 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1512 if (strcmp (klass->name, "DBNull") == 0)
1513 return TYPECODE_DBNULL;
1516 return TYPECODE_OBJECT;
1517 case MONO_TYPE_GENERICINST:
1518 return TYPECODE_OBJECT;
1520 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1526 mono_type_is_primitive (MonoType *type)
1528 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1529 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1533 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1535 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1536 return mono_class_enum_basetype (type->data.klass);
1537 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1538 return mono_class_enum_basetype (type->data.generic_class->container_class);
1542 ICALL_EXPORT guint32
1543 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1548 g_assert (type != NULL);
1550 klass = mono_class_from_mono_type (type->type);
1551 klassc = mono_class_from_mono_type (c->type);
1553 if (type->type->byref ^ c->type->byref)
1556 if (type->type->byref) {
1557 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1558 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1560 klass = mono_class_from_mono_type (t);
1561 klassc = mono_class_from_mono_type (ot);
1563 if (mono_type_is_primitive (t)) {
1564 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1565 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1566 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1567 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1568 return t->type == ot->type;
1570 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1573 if (klass->valuetype)
1574 return klass == klassc;
1575 return klass->valuetype == klassc->valuetype;
1578 return mono_class_is_assignable_from (klass, klassc);
1581 ICALL_EXPORT guint32
1582 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1584 MonoClass *klass = mono_class_from_mono_type (type->type);
1585 mono_class_init_or_throw (klass);
1586 return mono_object_isinst (obj, klass) != NULL;
1589 ICALL_EXPORT guint32
1590 ves_icall_get_attributes (MonoReflectionType *type)
1592 MonoClass *klass = mono_class_from_mono_type (type->type);
1593 return klass->flags;
1596 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1597 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1600 MonoClass *klass = field->field->parent;
1601 MonoMarshalType *info;
1605 if (klass->generic_container ||
1606 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1609 ftype = mono_field_get_type (field->field);
1610 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1613 info = mono_marshal_load_type_info (klass);
1615 for (i = 0; i < info->num_fields; ++i) {
1616 if (info->fields [i].field == field->field) {
1617 if (!info->fields [i].mspec)
1620 MonoReflectionMarshalAsAttribute* obj;
1621 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1622 if (!mono_error_ok (&error))
1623 mono_error_set_pending_exception (&error);
1632 ICALL_EXPORT MonoReflectionField*
1633 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1636 gboolean found = FALSE;
1643 klass = handle->parent;
1645 klass = mono_class_from_mono_type (type);
1647 /* Check that the field belongs to the class */
1648 for (k = klass; k; k = k->parent) {
1649 if (k == handle->parent) {
1656 /* The managed code will throw the exception */
1660 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1661 mono_error_raise_exception (&error);
1665 ICALL_EXPORT MonoArray*
1666 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1669 MonoType *type = mono_field_get_type_checked (field->field, &error);
1670 if (!mono_error_ok (&error)) {
1671 mono_error_set_pending_exception (&error);
1675 return type_array_from_modifiers (field->field->parent->image, type, optional);
1679 vell_icall_get_method_attributes (MonoMethod *method)
1681 return method->flags;
1685 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1688 MonoReflectionType *rt;
1689 MonoDomain *domain = mono_domain_get ();
1690 MonoMethodSignature* sig;
1692 sig = mono_method_signature_checked (method, &error);
1693 if (!mono_error_ok (&error)) {
1694 mono_error_set_pending_exception (&error);
1698 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1699 if (!mono_error_ok (&error)) {
1700 mono_error_set_pending_exception (&error);
1704 MONO_STRUCT_SETREF (info, parent, rt);
1706 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1707 if (!mono_error_ok (&error)) {
1708 mono_error_set_pending_exception (&error);
1712 MONO_STRUCT_SETREF (info, ret, rt);
1714 info->attrs = method->flags;
1715 info->implattrs = method->iflags;
1716 if (sig->call_convention == MONO_CALL_DEFAULT)
1717 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1719 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1724 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1727 ICALL_EXPORT MonoArray*
1728 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1730 MonoDomain *domain = mono_domain_get ();
1732 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1735 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1736 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1739 MonoDomain *domain = mono_domain_get ();
1740 MonoReflectionMarshalAsAttribute* res = NULL;
1741 MonoMarshalSpec **mspecs;
1744 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1745 mono_method_get_marshal_info (method, mspecs);
1748 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1749 if (!mono_error_ok (&error)) {
1750 mono_error_set_pending_exception (&error);
1755 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1757 mono_metadata_free_marshal_spec (mspecs [i]);
1764 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1766 MonoClass *parent = field->field->parent;
1767 if (!parent->size_inited)
1768 mono_class_init (parent);
1769 mono_class_setup_fields_locking (parent);
1771 return field->field->offset - sizeof (MonoObject);
1774 ICALL_EXPORT MonoReflectionType*
1775 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1778 MonoReflectionType *ret;
1781 parent = declaring? field->field->parent: field->klass;
1783 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1784 mono_error_raise_exception (&error);
1790 ICALL_EXPORT MonoObject *
1791 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1793 MonoClass *fklass = field->klass;
1794 MonoClassField *cf = field->field;
1795 MonoDomain *domain = mono_object_domain (field);
1797 if (fklass->image->assembly->ref_only) {
1798 mono_set_pending_exception (mono_get_exception_invalid_operation (
1799 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1803 if (mono_security_core_clr_enabled ())
1804 mono_security_core_clr_ensure_reflection_access_field (cf);
1806 return mono_field_get_value_object (domain, cf, obj);
1810 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1813 MonoClassField *cf = field->field;
1817 if (field->klass->image->assembly->ref_only) {
1818 mono_set_pending_exception (mono_get_exception_invalid_operation (
1819 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1823 if (mono_security_core_clr_enabled ())
1824 mono_security_core_clr_ensure_reflection_access_field (cf);
1826 type = mono_field_get_type_checked (cf, &error);
1827 if (!mono_error_ok (&error)) {
1828 mono_error_set_pending_exception (&error);
1832 v = (gchar *) value;
1834 switch (type->type) {
1837 case MONO_TYPE_BOOLEAN:
1840 case MONO_TYPE_CHAR:
1849 case MONO_TYPE_VALUETYPE:
1852 v += sizeof (MonoObject);
1854 case MONO_TYPE_STRING:
1855 case MONO_TYPE_OBJECT:
1856 case MONO_TYPE_CLASS:
1857 case MONO_TYPE_ARRAY:
1858 case MONO_TYPE_SZARRAY:
1861 case MONO_TYPE_GENERICINST: {
1862 MonoGenericClass *gclass = type->data.generic_class;
1863 g_assert (!gclass->context.class_inst->is_open);
1865 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1866 MonoClass *nklass = mono_class_from_mono_type (type);
1867 MonoObject *nullable;
1870 * Convert the boxed vtype into a Nullable structure.
1871 * This is complicated by the fact that Nullables have
1872 * a variable structure.
1874 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1875 if (!mono_error_ok (&error)) {
1876 mono_error_set_pending_exception (&error);
1880 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1882 v = (gchar *)mono_object_unbox (nullable);
1885 if (gclass->container_class->valuetype && (v != NULL))
1886 v += sizeof (MonoObject);
1890 g_error ("type 0x%x not handled in "
1891 "ves_icall_FieldInfo_SetValueInternal", type->type);
1896 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1897 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1898 if (!vtable->initialized)
1899 mono_runtime_class_init (vtable);
1900 mono_field_static_set_value (vtable, cf, v);
1902 mono_field_set_value (obj, cf, v);
1907 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1916 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1917 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1921 if (MONO_TYPE_IS_REFERENCE (f->type))
1922 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1924 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1927 ICALL_EXPORT MonoObject *
1928 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1930 MonoObject *o = NULL;
1931 MonoClassField *field = rfield->field;
1933 MonoDomain *domain = mono_object_domain (rfield);
1935 MonoTypeEnum def_type;
1936 const char *def_value;
1940 mono_class_init (field->parent);
1942 t = mono_field_get_type_checked (field, &error);
1943 if (!mono_error_ok (&error)) {
1944 mono_error_set_pending_exception (&error);
1948 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
1949 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1953 if (image_is_dynamic (field->parent->image)) {
1954 MonoClass *klass = field->parent;
1955 int fidx = field - klass->fields;
1957 g_assert (fidx >= 0 && fidx < klass->field.count);
1958 g_assert (klass->ext);
1959 g_assert (klass->ext->field_def_values);
1960 def_type = klass->ext->field_def_values [fidx].def_type;
1961 def_value = klass->ext->field_def_values [fidx].data;
1962 if (def_type == MONO_TYPE_END) {
1963 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1967 def_value = mono_class_get_field_default_value (field, &def_type);
1968 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
1970 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1975 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1979 case MONO_TYPE_BOOLEAN:
1982 case MONO_TYPE_CHAR:
1990 case MONO_TYPE_R8: {
1993 /* boxed value type */
1994 t = g_new0 (MonoType, 1);
1996 klass = mono_class_from_mono_type (t);
1998 o = mono_object_new_checked (domain, klass, &error);
1999 if (!mono_error_ok (&error)) {
2000 mono_error_set_pending_exception (&error);
2003 v = ((gchar *) o) + sizeof (MonoObject);
2004 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2007 case MONO_TYPE_STRING:
2008 case MONO_TYPE_CLASS:
2009 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2012 g_assert_not_reached ();
2018 ICALL_EXPORT MonoReflectionType*
2019 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2022 MonoReflectionType *ret;
2025 type = mono_field_get_type_checked (ref_field->field, &error);
2026 if (!mono_error_ok (&error)) {
2027 mono_error_set_pending_exception (&error);
2031 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2032 if (!mono_error_ok (&error)) {
2033 mono_error_set_pending_exception (&error);
2040 /* From MonoProperty.cs */
2042 PInfo_Attributes = 1,
2043 PInfo_GetMethod = 1 << 1,
2044 PInfo_SetMethod = 1 << 2,
2045 PInfo_ReflectedType = 1 << 3,
2046 PInfo_DeclaringType = 1 << 4,
2051 ves_icall_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2054 MonoReflectionType *rt;
2055 MonoReflectionMethod *rm;
2056 MonoDomain *domain = mono_object_domain (property);
2057 const MonoProperty *pproperty = property->property;
2059 if ((req_info & PInfo_ReflectedType) != 0) {
2060 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2061 mono_error_raise_exception (&error);
2063 MONO_STRUCT_SETREF (info, parent, rt);
2065 if ((req_info & PInfo_DeclaringType) != 0) {
2066 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2067 mono_error_raise_exception (&error);
2069 MONO_STRUCT_SETREF (info, declaring_type, rt);
2072 if ((req_info & PInfo_Name) != 0)
2073 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2075 if ((req_info & PInfo_Attributes) != 0)
2076 info->attrs = pproperty->attrs;
2078 if ((req_info & PInfo_GetMethod) != 0) {
2079 if (pproperty->get &&
2080 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2081 pproperty->get->klass == property->klass)) {
2082 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2083 mono_error_raise_exception (&error);
2088 MONO_STRUCT_SETREF (info, get, rm);
2090 if ((req_info & PInfo_SetMethod) != 0) {
2091 if (pproperty->set &&
2092 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2093 pproperty->set->klass == property->klass)) {
2094 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2095 mono_error_raise_exception (&error);
2100 MONO_STRUCT_SETREF (info, set, rm);
2103 * There may be other methods defined for properties, though, it seems they are not exposed
2104 * in the reflection API
2109 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2112 MonoReflectionType *rt;
2113 MonoReflectionMethod *rm;
2114 MonoDomain *domain = mono_object_domain (event);
2116 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2117 mono_error_raise_exception (&error);
2119 MONO_STRUCT_SETREF (info, reflected_type, rt);
2121 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2122 mono_error_raise_exception (&error);
2124 MONO_STRUCT_SETREF (info, declaring_type, rt);
2126 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2127 info->attrs = event->event->attrs;
2129 if (event->event->add) {
2130 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2131 mono_error_raise_exception (&error);
2136 MONO_STRUCT_SETREF (info, add_method, rm);
2138 if (event->event->remove) {
2139 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2140 mono_error_raise_exception (&error);
2145 MONO_STRUCT_SETREF (info, remove_method, rm);
2147 if (event->event->raise) {
2148 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2149 mono_error_raise_exception (&error);
2154 MONO_STRUCT_SETREF (info, raise_method, rm);
2156 #ifndef MONO_SMALL_CONFIG
2157 if (event->event->other) {
2159 while (event->event->other [n])
2161 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2163 for (i = 0; i < n; i++) {
2164 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2165 mono_error_raise_exception (&error);
2166 mono_array_setref (info->other_methods, i, rm);
2173 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2178 mono_class_setup_interfaces (klass, error);
2179 if (!mono_error_ok (error))
2182 for (i = 0; i < klass->interface_count; i++) {
2183 ic = klass->interfaces [i];
2184 g_hash_table_insert (ifaces, ic, ic);
2186 collect_interfaces (ic, ifaces, error);
2187 if (!mono_error_ok (error))
2193 MonoArray *iface_array;
2194 MonoGenericContext *context;
2198 } FillIfaceArrayData;
2201 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2203 MonoReflectionType *rt;
2204 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2205 MonoClass *ic = (MonoClass *)key;
2206 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2208 if (!mono_error_ok (data->error))
2211 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2212 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2213 if (!mono_error_ok (data->error))
2217 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2218 if (!mono_error_ok (data->error))
2221 mono_array_setref (data->iface_array, data->next_idx++, rt);
2224 mono_metadata_free_type (inflated);
2228 get_interfaces_hash (gconstpointer v1)
2230 MonoClass *k = (MonoClass*)v1;
2232 return k->type_token;
2235 ICALL_EXPORT MonoArray*
2236 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2239 MonoClass *klass = mono_class_from_mono_type (type->type);
2241 FillIfaceArrayData data = { 0 };
2244 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2246 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2247 data.context = mono_class_get_context (klass);
2248 klass = klass->generic_class->container_class;
2251 for (parent = klass; parent; parent = parent->parent) {
2252 mono_class_setup_interfaces (parent, &error);
2253 if (!mono_error_ok (&error))
2255 collect_interfaces (parent, iface_hash, &error);
2256 if (!mono_error_ok (&error))
2260 data.error = &error;
2261 data.domain = mono_object_domain (type);
2263 len = g_hash_table_size (iface_hash);
2265 g_hash_table_destroy (iface_hash);
2266 if (!data.domain->empty_types)
2267 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2268 return data.domain->empty_types;
2271 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2272 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2273 if (!mono_error_ok (&error))
2276 g_hash_table_destroy (iface_hash);
2277 return data.iface_array;
2280 g_hash_table_destroy (iface_hash);
2281 mono_error_set_pending_exception (&error);
2286 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2288 gboolean variance_used;
2289 MonoClass *klass = mono_class_from_mono_type (type->type);
2290 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2291 MonoReflectionMethod *member;
2294 int i = 0, len, ioffset;
2298 mono_class_init_or_throw (klass);
2299 mono_class_init_or_throw (iclass);
2301 mono_class_setup_vtable (klass);
2303 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2307 len = mono_class_num_methods (iclass);
2308 domain = mono_object_domain (type);
2309 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2310 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2312 while ((method = mono_class_get_methods (iclass, &iter))) {
2313 member = mono_method_get_object_checked (domain, method, iclass, &error);
2314 mono_error_raise_exception (&error);
2315 mono_array_setref (*methods, i, member);
2316 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2317 mono_error_raise_exception (&error);
2318 mono_array_setref (*targets, i, member);
2325 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2327 MonoClass *klass = mono_class_from_mono_type (type->type);
2328 mono_class_init_or_throw (klass);
2330 if (image_is_dynamic (klass->image)) {
2331 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2332 *packing = tb->packing_size;
2333 *size = tb->class_size;
2335 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2339 ICALL_EXPORT MonoReflectionType*
2340 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2343 MonoReflectionType *ret;
2346 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2347 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2348 mono_error_raise_exception (&error);
2353 klass = mono_class_from_mono_type (type->type);
2354 mono_class_init_or_throw (klass);
2356 // GetElementType should only return a type for:
2357 // Array Pointer PassedByRef
2358 if (type->type->byref)
2359 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2360 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2361 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2362 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2363 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2367 mono_error_raise_exception (&error);
2372 ICALL_EXPORT MonoReflectionType*
2373 ves_icall_get_type_parent (MonoReflectionType *type)
2376 MonoReflectionType *ret;
2378 if (type->type->byref)
2381 MonoClass *klass = mono_class_from_mono_type (type->type);
2385 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2386 mono_error_raise_exception (&error);
2391 ICALL_EXPORT MonoBoolean
2392 ves_icall_type_ispointer (MonoReflectionType *type)
2394 return type->type->type == MONO_TYPE_PTR;
2397 ICALL_EXPORT MonoBoolean
2398 ves_icall_type_isprimitive (MonoReflectionType *type)
2400 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)));
2403 ICALL_EXPORT MonoBoolean
2404 ves_icall_type_isbyref (MonoReflectionType *type)
2406 return type->type->byref;
2409 ICALL_EXPORT MonoBoolean
2410 ves_icall_type_iscomobject (MonoReflectionType *type)
2412 MonoClass *klass = mono_class_from_mono_type (type->type);
2413 mono_class_init_or_throw (klass);
2415 return mono_class_is_com_object (klass);
2418 ICALL_EXPORT MonoReflectionModule*
2419 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2422 MonoReflectionModule *result = NULL;
2423 MonoClass *klass = mono_class_from_mono_type (type->type);
2424 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2425 if (!mono_error_ok (&error))
2426 mono_error_set_pending_exception (&error);
2430 ICALL_EXPORT MonoReflectionAssembly*
2431 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2434 MonoDomain *domain = mono_domain_get ();
2435 MonoClass *klass = mono_class_from_mono_type (type->type);
2436 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2438 mono_error_set_pending_exception (&error);
2442 ICALL_EXPORT MonoReflectionType*
2443 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2446 MonoReflectionType *ret;
2447 MonoDomain *domain = mono_domain_get ();
2450 if (type->type->byref)
2452 if (type->type->type == MONO_TYPE_VAR) {
2453 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2454 klass = param ? param->owner.klass : NULL;
2455 } else if (type->type->type == MONO_TYPE_MVAR) {
2456 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2457 klass = param ? param->owner.method->klass : NULL;
2459 klass = mono_class_from_mono_type (type->type)->nested_in;
2465 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2466 mono_error_raise_exception (&error);
2471 ICALL_EXPORT MonoString*
2472 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2474 MonoDomain *domain = mono_domain_get ();
2475 MonoClass *klass = mono_class_from_mono_type (type->type);
2477 if (type->type->byref) {
2478 char *n = g_strdup_printf ("%s&", klass->name);
2479 MonoString *res = mono_string_new (domain, n);
2485 return mono_string_new (domain, klass->name);
2489 ICALL_EXPORT MonoString*
2490 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2492 MonoDomain *domain = mono_domain_get ();
2493 MonoClass *klass = mono_class_from_mono_type (type->type);
2495 while (klass->nested_in)
2496 klass = klass->nested_in;
2498 if (klass->name_space [0] == '\0')
2501 return mono_string_new (domain, klass->name_space);
2505 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2509 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2510 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2514 klass = mono_class_from_mono_type (type->type);
2520 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2523 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2527 ICALL_EXPORT MonoArray*
2528 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2531 MonoReflectionType *rt;
2533 MonoClass *klass, *pklass;
2534 MonoDomain *domain = mono_object_domain (type);
2537 klass = mono_class_from_mono_type (type->type);
2539 if (klass->generic_container) {
2540 MonoGenericContainer *container = klass->generic_container;
2541 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2542 for (i = 0; i < container->type_argc; ++i) {
2543 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2545 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2546 mono_error_raise_exception (&error);
2548 mono_array_setref (res, i, rt);
2550 } else if (klass->generic_class) {
2551 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2552 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2553 for (i = 0; i < inst->type_argc; ++i) {
2554 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2555 mono_error_raise_exception (&error);
2557 mono_array_setref (res, i, rt);
2565 ICALL_EXPORT gboolean
2566 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2570 if (!IS_MONOTYPE (type))
2573 if (type->type->byref)
2576 klass = mono_class_from_mono_type (type->type);
2577 return klass->generic_container != NULL;
2580 ICALL_EXPORT MonoReflectionType*
2581 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2584 MonoReflectionType *ret;
2587 if (type->type->byref)
2590 klass = mono_class_from_mono_type (type->type);
2592 if (klass->generic_container) {
2593 return type; /* check this one */
2595 if (klass->generic_class) {
2596 MonoClass *generic_class = klass->generic_class->container_class;
2599 tb = mono_class_get_ref_info (generic_class);
2601 if (generic_class->wastypebuilder && tb)
2602 return (MonoReflectionType *)tb;
2604 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2605 mono_error_raise_exception (&error);
2613 ICALL_EXPORT MonoReflectionType*
2614 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2617 MonoReflectionType *ret;
2619 MonoType *geninst, **types;
2622 g_assert (IS_MONOTYPE (type));
2623 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2625 count = mono_array_length (type_array);
2626 types = g_new0 (MonoType *, count);
2628 for (i = 0; i < count; i++) {
2629 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2630 types [i] = t->type;
2633 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2638 klass = mono_class_from_mono_type (geninst);
2640 /*we might inflate to the GTD*/
2641 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2642 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2646 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2647 mono_error_raise_exception (&error);
2652 ICALL_EXPORT gboolean
2653 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2657 if (!IS_MONOTYPE (type))
2660 if (type->type->byref)
2663 klass = mono_class_from_mono_type (type->type);
2664 return klass->generic_class != NULL || klass->generic_container != NULL;
2668 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2670 if (!IS_MONOTYPE (type))
2673 if (is_generic_parameter (type->type))
2674 return mono_type_get_generic_param_num (type->type);
2678 ICALL_EXPORT GenericParameterAttributes
2679 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2681 g_assert (IS_MONOTYPE (type));
2682 g_assert (is_generic_parameter (type->type));
2683 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2686 ICALL_EXPORT MonoArray *
2687 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2690 MonoReflectionType *rt;
2691 MonoGenericParamInfo *param_info;
2697 g_assert (IS_MONOTYPE (type));
2699 domain = mono_object_domain (type);
2700 param_info = mono_generic_param_info (type->type->data.generic_param);
2701 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2704 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2705 for (i = 0; i < count; i++) {
2706 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2707 mono_error_raise_exception (&error);
2709 mono_array_setref (res, i, rt);
2716 ICALL_EXPORT MonoBoolean
2717 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2719 return is_generic_parameter (type->type);
2722 ICALL_EXPORT MonoBoolean
2723 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2725 return is_generic_parameter (tb->type.type);
2729 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2730 MonoReflectionType *t)
2732 enumtype->type = t->type;
2735 ICALL_EXPORT MonoReflectionMethod*
2736 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2737 MonoReflectionMethod* generic)
2744 MonoReflectionMethod *ret = NULL;
2746 domain = ((MonoObject *)type)->vtable->domain;
2748 klass = mono_class_from_mono_type (type->type);
2749 mono_class_init_or_throw (klass);
2752 while ((method = mono_class_get_methods (klass, &iter))) {
2753 if (method->token == generic->method->token) {
2754 ret = mono_method_get_object_checked (domain, method, klass, &error);
2755 mono_error_raise_exception (&error);
2762 ICALL_EXPORT MonoReflectionMethod *
2763 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2766 MonoType *type = ref_type->type;
2768 MonoReflectionMethod *ret = NULL;
2770 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2771 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2774 if (type->type == MONO_TYPE_VAR)
2777 method = mono_type_get_generic_param_owner (type)->owner.method;
2780 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2781 if (!mono_error_ok (&error))
2782 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2786 ICALL_EXPORT MonoBoolean
2787 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2789 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2793 ICALL_EXPORT MonoBoolean
2794 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2796 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2801 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2803 MonoDomain *domain = mono_domain_get ();
2804 MonoImage *image = method->method->klass->image;
2805 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2806 MonoTableInfo *tables = image->tables;
2807 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2808 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2809 guint32 im_cols [MONO_IMPLMAP_SIZE];
2810 guint32 scope_token;
2811 const char *import = NULL;
2812 const char *scope = NULL;
2814 if (image_is_dynamic (image)) {
2815 MonoReflectionMethodAux *method_aux =
2816 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2818 import = method_aux->dllentry;
2819 scope = method_aux->dll;
2822 if (!import || !scope) {
2823 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2828 if (piinfo->implmap_idx) {
2829 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2831 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2832 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2833 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2834 scope = mono_metadata_string_heap (image, scope_token);
2838 *flags = piinfo->piflags;
2839 *entry_point = mono_string_new (domain, import);
2840 *dll_name = mono_string_new (domain, scope);
2843 ICALL_EXPORT MonoReflectionMethod *
2844 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2846 MonoMethodInflated *imethod;
2848 MonoReflectionMethod *ret = NULL;
2851 if (method->method->is_generic)
2854 if (!method->method->is_inflated)
2857 imethod = (MonoMethodInflated *) method->method;
2859 result = imethod->declaring;
2860 /* Not a generic method. */
2861 if (!result->is_generic)
2864 if (image_is_dynamic (method->method->klass->image)) {
2865 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2866 MonoReflectionMethod *res;
2869 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2870 * the dynamic case as well ?
2872 mono_image_lock ((MonoImage*)image);
2873 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2874 mono_image_unlock ((MonoImage*)image);
2880 if (imethod->context.class_inst) {
2881 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2882 /*Generic methods gets the context of the GTD.*/
2883 if (mono_class_get_context (klass)) {
2884 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2885 if (!mono_error_ok (&error))
2890 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2892 if (!mono_error_ok (&error))
2893 mono_error_set_pending_exception (&error);
2897 ICALL_EXPORT gboolean
2898 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2900 return mono_method_signature (method->method)->generic_param_count != 0;
2903 ICALL_EXPORT gboolean
2904 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2906 return method->method->is_generic;
2909 ICALL_EXPORT MonoArray*
2910 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2913 MonoReflectionType *rt;
2918 domain = mono_object_domain (method);
2920 if (method->method->is_inflated) {
2921 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2924 count = inst->type_argc;
2925 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2927 for (i = 0; i < count; i++) {
2928 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2929 mono_error_raise_exception (&error);
2931 mono_array_setref (res, i, rt);
2938 count = mono_method_signature (method->method)->generic_param_count;
2939 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2941 for (i = 0; i < count; i++) {
2942 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2943 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2944 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
2946 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2947 mono_error_raise_exception (&error);
2949 mono_array_setref (res, i, rt);
2955 ICALL_EXPORT MonoObject *
2956 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
2960 * Invoke from reflection is supposed to always be a virtual call (the API
2961 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2962 * greater flexibility.
2964 MonoMethod *m = method->method;
2965 MonoMethodSignature *sig = mono_method_signature (m);
2968 void *obj = this_arg;
2972 if (mono_security_core_clr_enabled ())
2973 mono_security_core_clr_ensure_reflection_access_method (m);
2975 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2976 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2977 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2982 if (!mono_object_isinst (this_arg, m->klass)) {
2983 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
2984 char *target_name = mono_type_get_full_name (m->klass);
2985 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2986 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2988 g_free (target_name);
2992 m = mono_object_get_virtual_method (this_arg, m);
2993 /* must pass the pointer to the value for valuetype methods */
2994 if (m->klass->valuetype)
2995 obj = mono_object_unbox (this_arg);
2996 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2997 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3002 if (sig->ret->byref) {
3003 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"));
3007 pcount = params? mono_array_length (params): 0;
3008 if (pcount != sig->param_count) {
3009 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3013 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3014 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."));
3018 image = m->klass->image;
3019 if (image->assembly->ref_only) {
3020 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."));
3024 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3025 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3029 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3033 intptr_t *lower_bounds;
3034 pcount = mono_array_length (params);
3035 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3036 /* Note: the synthetized array .ctors have int32 as argument type */
3037 for (i = 0; i < pcount; ++i)
3038 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3040 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3041 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3042 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3043 if (!mono_error_ok (&error)) {
3044 mono_error_set_pending_exception (&error);
3048 for (i = 0; i < mono_array_length (arr); ++i) {
3049 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3050 if (!mono_error_ok (&error)) {
3051 mono_error_set_pending_exception (&error);
3054 mono_array_setref_fast (arr, i, subarray);
3056 return (MonoObject*)arr;
3059 if (m->klass->rank == pcount) {
3060 /* Only lengths provided. */
3061 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3062 if (!mono_error_ok (&error)) {
3063 mono_error_set_pending_exception (&error);
3067 return (MonoObject*)arr;
3069 g_assert (pcount == (m->klass->rank * 2));
3070 /* The arguments are lower-bound-length pairs */
3071 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3073 for (i = 0; i < pcount / 2; ++i) {
3074 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3075 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3078 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3079 if (!mono_error_ok (&error)) {
3080 mono_error_set_pending_exception (&error);
3084 return (MonoObject*)arr;
3087 return mono_runtime_invoke_array (m, obj, params, NULL);
3090 #ifndef DISABLE_REMOTING
3091 ICALL_EXPORT MonoObject *
3092 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3094 MonoDomain *domain = mono_object_domain (method);
3095 MonoMethod *m = method->method;
3096 MonoMethodSignature *sig = mono_method_signature (m);
3097 MonoArray *out_args;
3099 int i, j, outarg_count = 0;
3101 if (m->klass == mono_defaults.object_class) {
3102 if (!strcmp (m->name, "FieldGetter")) {
3103 MonoClass *k = this_arg->vtable->klass;
3107 /* If this is a proxy, then it must be a CBO */
3108 if (k == mono_defaults.transparent_proxy_class) {
3109 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3110 this_arg = tp->rp->unwrapped_server;
3111 g_assert (this_arg);
3112 k = this_arg->vtable->klass;
3115 name = mono_array_get (params, MonoString *, 1);
3116 str = mono_string_to_utf8 (name);
3119 MonoClassField* field = mono_class_get_field_from_name (k, str);
3121 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3122 if (field_klass->valuetype)
3123 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
3125 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3127 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3128 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3129 mono_array_setref (out_args, 0, result);
3137 g_assert_not_reached ();
3139 } else if (!strcmp (m->name, "FieldSetter")) {
3140 MonoClass *k = this_arg->vtable->klass;
3146 /* If this is a proxy, then it must be a CBO */
3147 if (k == mono_defaults.transparent_proxy_class) {
3148 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3149 this_arg = tp->rp->unwrapped_server;
3150 g_assert (this_arg);
3151 k = this_arg->vtable->klass;
3154 name = mono_array_get (params, MonoString *, 1);
3155 str = mono_string_to_utf8 (name);
3158 MonoClassField* field = mono_class_get_field_from_name (k, str);
3160 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3161 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3163 if (field_klass->valuetype) {
3164 size = mono_type_size (field->type, &align);
3165 g_assert (size == mono_class_value_size (field_klass, NULL));
3166 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3168 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3171 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3172 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3182 g_assert_not_reached ();
3187 for (i = 0; i < mono_array_length (params); i++) {
3188 if (sig->params [i]->byref)
3192 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3194 /* handle constructors only for objects already allocated */
3195 if (!strcmp (method->method->name, ".ctor"))
3196 g_assert (this_arg);
3198 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3199 g_assert (!method->method->klass->valuetype);
3200 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3202 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3203 if (sig->params [i]->byref) {
3205 arg = mono_array_get (params, gpointer, i);
3206 mono_array_setref (out_args, j, arg);
3211 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3218 read_enum_value (const char *mem, int type)
3221 case MONO_TYPE_BOOLEAN:
3223 return *(guint8*)mem;
3225 return *(gint8*)mem;
3226 case MONO_TYPE_CHAR:
3228 return read16 (mem);
3230 return (gint16) read16 (mem);
3232 return read32 (mem);
3234 return (gint32) read32 (mem);
3237 return read64 (mem);
3239 g_assert_not_reached ();
3245 write_enum_value (char *mem, int type, guint64 value)
3249 case MONO_TYPE_I1: {
3250 guint8 *p = (guint8*)mem;
3255 case MONO_TYPE_I2: {
3256 guint16 *p = (guint16 *)mem;
3261 case MONO_TYPE_I4: {
3262 guint32 *p = (guint32 *)mem;
3267 case MONO_TYPE_I8: {
3268 guint64 *p = (guint64 *)mem;
3273 g_assert_not_reached ();
3278 ICALL_EXPORT MonoObject *
3279 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3287 domain = mono_object_domain (enumType);
3288 enumc = mono_class_from_mono_type (enumType->type);
3290 mono_class_init_or_throw (enumc);
3292 etype = mono_class_enum_basetype (enumc);
3294 res = mono_object_new_checked (domain, enumc, &error);
3295 mono_error_raise_exception (&error);
3296 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3301 ICALL_EXPORT MonoBoolean
3302 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3304 int size = mono_class_value_size (a->vtable->klass, NULL);
3305 guint64 a_val = 0, b_val = 0;
3307 memcpy (&a_val, mono_object_unbox (a), size);
3308 memcpy (&b_val, mono_object_unbox (b), size);
3310 return (a_val & b_val) == b_val;
3313 ICALL_EXPORT MonoObject *
3314 ves_icall_System_Enum_get_value (MonoObject *eobj)
3326 g_assert (eobj->vtable->klass->enumtype);
3328 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3329 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3330 mono_error_raise_exception (&error);
3331 dst = (char *)res + sizeof (MonoObject);
3332 src = (char *)eobj + sizeof (MonoObject);
3333 size = mono_class_value_size (enumc, NULL);
3335 memcpy (dst, src, size);
3340 ICALL_EXPORT MonoReflectionType *
3341 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3344 MonoReflectionType *ret;
3348 klass = mono_class_from_mono_type (type->type);
3349 mono_class_init_or_throw (klass);
3351 etype = mono_class_enum_basetype (klass);
3353 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3357 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3358 mono_error_raise_exception (&error);
3364 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3366 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3367 gpointer odata = (char *)other + sizeof (MonoObject);
3368 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3369 g_assert (basetype);
3374 if (eobj->vtable->klass != other->vtable->klass)
3377 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3378 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3379 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3382 return me > other ? 1 : -1; \
3385 switch (basetype->type) {
3387 COMPARE_ENUM_VALUES (guint8);
3389 COMPARE_ENUM_VALUES (gint8);
3390 case MONO_TYPE_CHAR:
3392 COMPARE_ENUM_VALUES (guint16);
3394 COMPARE_ENUM_VALUES (gint16);
3396 COMPARE_ENUM_VALUES (guint32);
3398 COMPARE_ENUM_VALUES (gint32);
3400 COMPARE_ENUM_VALUES (guint64);
3402 COMPARE_ENUM_VALUES (gint64);
3406 #undef COMPARE_ENUM_VALUES
3407 /* indicates that the enum was of an unsupported unerlying type */
3412 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3414 gpointer data = (char *)eobj + sizeof (MonoObject);
3415 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3416 g_assert (basetype);
3418 switch (basetype->type) {
3419 case MONO_TYPE_I1: {
3420 gint8 value = *((gint8*)data);
3421 return ((int)value ^ (int)value << 8);
3424 return *((guint8*)data);
3425 case MONO_TYPE_CHAR:
3427 return *((guint16*)data);
3429 case MONO_TYPE_I2: {
3430 gint16 value = *((gint16*)data);
3431 return ((int)(guint16)value | (((int)value) << 16));
3434 return *((guint32*)data);
3436 return *((gint32*)data);
3438 case MONO_TYPE_I8: {
3439 gint64 value = *((gint64*)data);
3440 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3443 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3448 ICALL_EXPORT MonoBoolean
3449 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3451 MonoDomain *domain = mono_object_domain (type);
3452 MonoClass *enumc = mono_class_from_mono_type (type->type);
3453 guint j = 0, nvalues;
3455 MonoClassField *field;
3457 guint64 field_value, previous_value = 0;
3458 gboolean sorted = TRUE;
3460 mono_class_init_or_throw (enumc);
3462 if (!enumc->enumtype) {
3463 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3467 base_type = mono_class_enum_basetype (enumc)->type;
3469 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3470 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3471 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3474 while ((field = mono_class_get_fields (enumc, &iter))) {
3476 MonoTypeEnum def_type;
3478 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3480 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3482 if (mono_field_is_deleted (field))
3484 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3486 p = mono_class_get_field_default_value (field, &def_type);
3487 /* len = */ mono_metadata_decode_blob_size (p, &p);
3489 field_value = read_enum_value (p, base_type);
3490 mono_array_set (*values, guint64, j, field_value);
3492 if (previous_value > field_value)
3495 previous_value = field_value;
3503 BFLAGS_IgnoreCase = 1,
3504 BFLAGS_DeclaredOnly = 2,
3505 BFLAGS_Instance = 4,
3507 BFLAGS_Public = 0x10,
3508 BFLAGS_NonPublic = 0x20,
3509 BFLAGS_FlattenHierarchy = 0x40,
3510 BFLAGS_InvokeMethod = 0x100,
3511 BFLAGS_CreateInstance = 0x200,
3512 BFLAGS_GetField = 0x400,
3513 BFLAGS_SetField = 0x800,
3514 BFLAGS_GetProperty = 0x1000,
3515 BFLAGS_SetProperty = 0x2000,
3516 BFLAGS_ExactBinding = 0x10000,
3517 BFLAGS_SuppressChangeType = 0x20000,
3518 BFLAGS_OptionalParamBinding = 0x40000
3521 ICALL_EXPORT MonoArray*
3522 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3526 MonoClass *startklass, *klass, *refklass;
3531 char *utf8_name = NULL;
3532 int (*compare_func) (const char *s1, const char *s2) = NULL;
3533 MonoClassField *field;
3534 MonoPtrArray tmp_array;
3536 domain = ((MonoObject *)type)->vtable->domain;
3537 if (type->type->byref)
3538 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3540 klass = startklass = mono_class_from_mono_type (type->type);
3541 refklass = mono_class_from_mono_type (reftype->type);
3543 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3546 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3547 mono_ptr_array_destroy (tmp_array);
3548 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3553 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3554 guint32 flags = mono_field_get_flags (field);
3556 if (mono_field_is_deleted_with_flags (field, flags))
3558 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3559 if (bflags & BFLAGS_Public)
3561 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3562 if (bflags & BFLAGS_NonPublic) {
3569 if (flags & FIELD_ATTRIBUTE_STATIC) {
3570 if (bflags & BFLAGS_Static)
3571 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3574 if (bflags & BFLAGS_Instance)
3582 if (utf8_name == NULL) {
3583 utf8_name = mono_string_to_utf8 (name);
3584 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3587 if (compare_func (mono_field_get_name (field), utf8_name))
3591 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3592 if (!mono_error_ok (&error))
3594 mono_ptr_array_append (tmp_array, member);
3596 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3599 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3601 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3602 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3604 mono_ptr_array_destroy (tmp_array);
3606 if (utf8_name != NULL)
3611 mono_ptr_array_destroy (tmp_array);
3612 mono_error_raise_exception (&error);
3613 g_assert_not_reached ();
3617 method_nonpublic (MonoMethod* method, gboolean start_klass)
3619 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3620 case METHOD_ATTRIBUTE_ASSEM:
3621 return (start_klass || mono_defaults.generic_ilist_class);
3622 case METHOD_ATTRIBUTE_PRIVATE:
3624 case METHOD_ATTRIBUTE_PUBLIC:
3632 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3635 MonoClass *startklass;
3639 /*FIXME, use MonoBitSet*/
3640 guint32 method_slots_default [8];
3641 guint32 *method_slots = NULL;
3642 int (*compare_func) (const char *s1, const char *s2) = NULL;
3644 array = g_ptr_array_new ();
3649 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3651 /* An optimization for calls made from Delegate:CreateDelegate () */
3652 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3653 method = mono_get_delegate_invoke (klass);
3654 if (mono_loader_get_last_error ())
3657 g_ptr_array_add (array, method);
3661 mono_class_setup_methods (klass);
3662 mono_class_setup_vtable (klass);
3663 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3666 if (is_generic_parameter (&klass->byval_arg))
3667 nslots = mono_class_get_vtable_size (klass->parent);
3669 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3670 if (nslots >= sizeof (method_slots_default) * 8) {
3671 method_slots = g_new0 (guint32, nslots / 32 + 1);
3673 method_slots = method_slots_default;
3674 memset (method_slots, 0, sizeof (method_slots_default));
3677 mono_class_setup_methods (klass);
3678 mono_class_setup_vtable (klass);
3679 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3683 while ((method = mono_class_get_methods (klass, &iter))) {
3685 if (method->slot != -1) {
3686 g_assert (method->slot < nslots);
3687 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3689 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3690 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3693 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3695 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3696 if (bflags & BFLAGS_Public)
3698 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3704 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3705 if (bflags & BFLAGS_Static)
3706 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3709 if (bflags & BFLAGS_Instance)
3717 if (compare_func (name, method->name))
3722 g_ptr_array_add (array, method);
3724 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3726 if (method_slots != method_slots_default)
3727 g_free (method_slots);
3732 if (method_slots != method_slots_default)
3733 g_free (method_slots);
3734 g_ptr_array_free (array, TRUE);
3736 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3737 *ex = mono_class_get_exception_for_failure (klass);
3739 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3740 mono_loader_clear_error ();
3745 ICALL_EXPORT MonoArray*
3746 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3748 static MonoClass *MethodInfo_array;
3752 MonoVTable *array_vtable;
3753 MonoException *ex = NULL;
3754 const char *mname = NULL;
3755 GPtrArray *method_array;
3756 MonoClass *klass, *refklass;
3759 mono_error_init (&error);
3761 if (!MethodInfo_array) {
3762 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3763 mono_memory_barrier ();
3764 MethodInfo_array = klass;
3767 klass = mono_class_from_mono_type (type->type);
3768 refklass = mono_class_from_mono_type (reftype->type);
3769 domain = ((MonoObject *)type)->vtable->domain;
3770 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3771 if (type->type->byref) {
3772 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3773 mono_error_set_pending_exception (&error);
3779 mname = mono_string_to_utf8 (name);
3781 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3782 g_free ((char*)mname);
3784 mono_set_pending_exception (ex);
3788 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3789 if (!mono_error_ok (&error)) {
3790 mono_error_set_pending_exception (&error);
3794 for (i = 0; i < method_array->len; ++i) {
3795 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3796 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3797 if (!mono_error_ok (&error))
3799 mono_array_setref (res, i, rm);
3803 g_ptr_array_free (method_array, TRUE);
3804 if (!mono_error_ok (&error))
3805 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3809 ICALL_EXPORT MonoArray*
3810 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3813 static MonoClass *System_Reflection_ConstructorInfo;
3814 MonoClass *startklass, *klass, *refklass;
3819 gpointer iter = NULL;
3820 MonoPtrArray tmp_array;
3823 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3825 domain = ((MonoObject *)type)->vtable->domain;
3826 if (type->type->byref)
3827 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3828 klass = startklass = mono_class_from_mono_type (type->type);
3829 refklass = mono_class_from_mono_type (reftype->type);
3831 if (!System_Reflection_ConstructorInfo)
3832 System_Reflection_ConstructorInfo = mono_class_from_name (
3833 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3835 mono_class_setup_methods (klass);
3836 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3837 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3842 while ((method = mono_class_get_methods (klass, &iter))) {
3844 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3846 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3847 if (bflags & BFLAGS_Public)
3850 if (bflags & BFLAGS_NonPublic)
3856 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3857 if (bflags & BFLAGS_Static)
3858 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3861 if (bflags & BFLAGS_Instance)
3867 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3868 if (!mono_error_ok (&error)) {
3869 mono_error_set_pending_exception (&error);
3873 mono_ptr_array_append (tmp_array, member);
3876 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3878 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3879 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3881 mono_ptr_array_destroy (tmp_array);
3887 property_hash (gconstpointer data)
3889 MonoProperty *prop = (MonoProperty*)data;
3891 return g_str_hash (prop->name);
3895 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3897 if (method1->is_inflated)
3898 method1 = ((MonoMethodInflated*) method1)->declaring;
3899 if (method2->is_inflated)
3900 method2 = ((MonoMethodInflated*) method2)->declaring;
3902 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3906 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3908 // Properties are hide-by-name-and-signature
3909 if (!g_str_equal (prop1->name, prop2->name))
3912 /* If we see a property in a generic method, we want to
3913 compare the generic signatures, not the inflated signatures
3914 because we might conflate two properties that were
3918 public T this[T t] { getter { return t; } } // method 1
3919 public U this[U u] { getter { return u; } } // method 2
3922 If we see int Foo<int,int>::Item[int] we need to know if
3923 the indexer came from method 1 or from method 2, and we
3924 shouldn't conflate them. (Bugzilla 36283)
3926 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
3929 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
3936 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3941 return method_nonpublic (accessor, start_klass);
3944 ICALL_EXPORT MonoArray*
3945 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3949 static MonoClass *System_Reflection_PropertyInfo;
3950 MonoClass *startklass, *klass;
3956 gchar *propname = NULL;
3957 int (*compare_func) (const char *s1, const char *s2) = NULL;
3959 GHashTable *properties = NULL;
3960 MonoPtrArray tmp_array;
3962 mono_error_init (&error);
3964 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
3966 if (!System_Reflection_PropertyInfo)
3967 System_Reflection_PropertyInfo = mono_class_from_name (
3968 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3970 domain = ((MonoObject *)type)->vtable->domain;
3971 if (type->type->byref)
3972 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3973 klass = startklass = mono_class_from_mono_type (type->type);
3976 propname = mono_string_to_utf8 (name);
3977 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3980 properties = g_hash_table_new (property_hash, (GEqualFunc)property_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 ((prop = mono_class_get_properties (klass, &iter))) {
3994 flags = method->flags;
3997 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3998 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3999 if (bflags & BFLAGS_Public)
4001 } else if (bflags & BFLAGS_NonPublic) {
4002 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4003 property_accessor_nonpublic(prop->set, startklass == klass)) {
4010 if (flags & METHOD_ATTRIBUTE_STATIC) {
4011 if (bflags & BFLAGS_Static)
4012 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4015 if (bflags & BFLAGS_Instance)
4024 if (compare_func (propname, prop->name))
4028 if (g_hash_table_lookup (properties, prop))
4031 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4034 mono_ptr_array_append (tmp_array, pr);
4036 g_hash_table_insert (properties, prop, prop);
4038 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4041 g_hash_table_destroy (properties);
4044 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
4045 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4046 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4048 mono_ptr_array_destroy (tmp_array);
4055 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4056 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4058 mono_error_set_from_loader_error (&error);
4059 mono_loader_clear_error ();
4064 g_hash_table_destroy (properties);
4067 mono_ptr_array_destroy (tmp_array);
4069 mono_error_set_pending_exception (&error);
4075 event_hash (gconstpointer data)
4077 MonoEvent *event = (MonoEvent*)data;
4079 return g_str_hash (event->name);
4083 event_equal (MonoEvent *event1, MonoEvent *event2)
4085 // Events are hide-by-name
4086 return g_str_equal (event1->name, event2->name);
4089 ICALL_EXPORT MonoArray*
4090 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4094 static MonoClass *System_Reflection_EventInfo;
4095 MonoClass *startklass, *klass;
4101 char *utf8_name = NULL;
4102 int (*compare_func) (const char *s1, const char *s2) = NULL;
4103 GHashTable *events = NULL;
4104 MonoPtrArray tmp_array;
4106 mono_error_init (&error);
4108 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4110 if (!System_Reflection_EventInfo)
4111 System_Reflection_EventInfo = mono_class_from_name (
4112 mono_defaults.corlib, "System.Reflection", "EventInfo");
4114 domain = mono_object_domain (type);
4115 if (type->type->byref)
4116 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
4117 klass = startklass = mono_class_from_mono_type (type->type);
4119 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4121 mono_class_setup_methods (klass);
4122 mono_class_setup_vtable (klass);
4123 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
4127 while ((event = mono_class_get_events (klass, &iter))) {
4129 method = event->add;
4131 method = event->remove;
4133 method = event->raise;
4135 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4136 if (bflags & BFLAGS_Public)
4138 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4139 if (bflags & BFLAGS_NonPublic)
4144 if (bflags & BFLAGS_NonPublic)
4150 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4151 if (bflags & BFLAGS_Static)
4152 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4155 if (bflags & BFLAGS_Instance)
4160 if (bflags & BFLAGS_Instance)
4166 if (utf8_name == NULL) {
4167 utf8_name = mono_string_to_utf8 (name);
4168 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4171 if (compare_func (event->name, utf8_name))
4175 if (g_hash_table_lookup (events, event))
4178 MonoReflectionEvent *ev_obj;
4179 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4182 mono_ptr_array_append (tmp_array, ev_obj);
4184 g_hash_table_insert (events, event, event);
4186 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4189 g_hash_table_destroy (events);
4191 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
4193 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4194 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4196 mono_ptr_array_destroy (tmp_array);
4198 if (utf8_name != NULL)
4204 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4205 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4207 mono_error_set_from_loader_error (&error);
4208 mono_loader_clear_error ();
4214 g_hash_table_destroy (events);
4215 if (utf8_name != NULL)
4218 mono_ptr_array_destroy (tmp_array);
4220 mono_error_set_pending_exception (&error);
4224 ICALL_EXPORT MonoArray*
4225 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4228 MonoReflectionType *rt;
4236 MonoPtrArray tmp_array;
4238 domain = ((MonoObject *)type)->vtable->domain;
4239 if (type->type->byref)
4240 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4241 klass = mono_class_from_mono_type (type->type);
4244 * If a nested type is generic, return its generic type definition.
4245 * Note that this means that the return value is essentially the set
4246 * of nested types of the generic type definition of @klass.
4248 * A note in MSDN claims that a generic type definition can have
4249 * nested types that aren't generic. In any case, the container of that
4250 * nested type would be the generic type definition.
4252 if (klass->generic_class)
4253 klass = klass->generic_class->container_class;
4255 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4257 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4259 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4260 if (bflags & BFLAGS_Public)
4263 if (bflags & BFLAGS_NonPublic)
4271 str = mono_string_to_utf8 (name);
4272 mono_identifier_unescape_type_name_chars (str);
4275 if (strcmp (nested->name, str))
4279 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4280 mono_error_raise_exception (&error);
4282 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4285 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4287 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4288 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4290 mono_ptr_array_destroy (tmp_array);
4298 ICALL_EXPORT MonoReflectionType*
4299 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4302 MonoReflectionType *ret;
4304 MonoType *type = NULL;
4305 MonoTypeNameParse info;
4306 gboolean type_resolve;
4308 /* On MS.NET, this does not fire a TypeResolve event */
4309 type_resolve = TRUE;
4310 str = mono_string_to_utf8 (name);
4311 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4312 if (!mono_reflection_parse_type (str, &info)) {
4314 mono_reflection_free_type_info (&info);
4316 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4319 /*g_print ("failed parse\n");*/
4323 if (info.assembly.name) {
4325 mono_reflection_free_type_info (&info);
4327 /* 1.0 and 2.0 throw different exceptions */
4328 if (mono_defaults.generic_ilist_class)
4329 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4331 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4337 if (module != NULL) {
4339 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4344 if (assembly_is_dynamic (assembly->assembly)) {
4345 /* Enumerate all modules */
4346 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4350 if (abuilder->modules) {
4351 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4352 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4353 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4359 if (!type && abuilder->loaded_modules) {
4360 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4361 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4362 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4369 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4371 mono_reflection_free_type_info (&info);
4373 MonoException *e = NULL;
4376 e = mono_get_exception_type_load (name, NULL);
4378 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4379 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4381 mono_loader_clear_error ();
4384 mono_set_pending_exception (e);
4386 } else if (mono_loader_get_last_error ()) {
4388 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4391 mono_loader_clear_error ();
4394 if (type->type == MONO_TYPE_CLASS) {
4395 MonoClass *klass = mono_type_get_class (type);
4397 /* need to report exceptions ? */
4398 if (throwOnError && klass->exception_type) {
4399 /* report SecurityException (or others) that occured when loading the assembly */
4400 MonoException *exc = mono_class_get_exception_for_failure (klass);
4401 mono_loader_clear_error ();
4402 mono_set_pending_exception (exc);
4407 /* g_print ("got it\n"); */
4408 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4409 mono_error_raise_exception (&error);
4415 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4418 gchar *shadow_ini_file;
4421 /* Check for shadow-copied assembly */
4422 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4423 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4425 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4426 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4432 g_free (shadow_ini_file);
4433 if (content != NULL) {
4436 *filename = content;
4443 ICALL_EXPORT MonoString *
4444 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4446 MonoDomain *domain = mono_object_domain (assembly);
4447 MonoAssembly *mass = assembly->assembly;
4448 MonoString *res = NULL;
4453 if (g_path_is_absolute (mass->image->name)) {
4454 absolute = g_strdup (mass->image->name);
4455 dirname = g_path_get_dirname (absolute);
4457 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4458 dirname = g_strdup (mass->basedir);
4461 replace_shadow_path (domain, dirname, &absolute);
4466 for (i = strlen (absolute) - 1; i >= 0; i--)
4467 if (absolute [i] == '\\')
4472 uri = g_filename_to_uri (absolute, NULL, NULL);
4474 const char *prepend = "file://";
4476 if (*absolute == '/' && *(absolute + 1) == '/') {
4479 prepend = "file:///";
4482 uri = g_strconcat (prepend, absolute, NULL);
4486 res = mono_string_new (domain, uri);
4493 ICALL_EXPORT MonoBoolean
4494 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4496 MonoAssembly *mass = assembly->assembly;
4498 return mass->in_gac;
4501 ICALL_EXPORT MonoReflectionAssembly*
4502 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4507 MonoImageOpenStatus status;
4508 MonoReflectionAssembly* result = NULL;
4510 name = mono_string_to_utf8 (mname);
4511 res = mono_assembly_load_with_partial_name (name, &status);
4517 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4519 mono_error_set_pending_exception (&error);
4523 ICALL_EXPORT MonoString *
4524 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4526 MonoDomain *domain = mono_object_domain (assembly);
4529 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4534 ICALL_EXPORT MonoBoolean
4535 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4537 return assembly->assembly->ref_only;
4540 ICALL_EXPORT MonoString *
4541 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4543 MonoDomain *domain = mono_object_domain (assembly);
4545 return mono_string_new (domain, assembly->assembly->image->version);
4548 ICALL_EXPORT MonoReflectionMethod*
4549 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4552 MonoReflectionMethod *res = NULL;
4555 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4559 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4560 if (!mono_error_ok (&error))
4563 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4566 if (!mono_error_ok (&error))
4567 mono_error_set_pending_exception (&error);
4571 ICALL_EXPORT MonoReflectionModule*
4572 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4575 MonoReflectionModule *result = NULL;
4576 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4577 if (!mono_error_ok (&error))
4578 mono_error_set_pending_exception (&error);
4582 ICALL_EXPORT MonoArray*
4583 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4585 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4586 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4590 for (i = 0; i < table->rows; ++i) {
4591 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4592 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4598 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4600 static MonoClass *System_Version = NULL;
4601 static MonoMethod *create_version = NULL;
4606 if (!System_Version) {
4607 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4608 g_assert (System_Version);
4611 if (!create_version) {
4612 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4613 create_version = mono_method_desc_search_in_class (desc, System_Version);
4614 g_assert (create_version);
4615 mono_method_desc_free (desc);
4621 args [3] = &revision;
4622 result = mono_object_new_checked (domain, System_Version, &error);
4623 mono_error_raise_exception (&error); /* FIXME don't raise here */
4625 mono_runtime_invoke_checked (create_version, result, args, &error);
4626 mono_error_raise_exception (&error); /* FIXME don't raise here */
4631 ICALL_EXPORT MonoArray*
4632 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4634 static MonoClass *System_Reflection_AssemblyName;
4637 MonoDomain *domain = mono_object_domain (assembly);
4639 static MonoMethod *create_culture = NULL;
4640 MonoImage *image = assembly->assembly->image;
4644 if (!System_Reflection_AssemblyName)
4645 System_Reflection_AssemblyName = mono_class_from_name (
4646 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4648 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4651 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4653 if (count > 0 && !create_culture) {
4654 MonoMethodDesc *desc = mono_method_desc_new (
4655 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4656 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4657 g_assert (create_culture);
4658 mono_method_desc_free (desc);
4661 for (i = 0; i < count; i++) {
4662 MonoReflectionAssemblyName *aname;
4663 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4665 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4667 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4668 domain, System_Reflection_AssemblyName, &error);
4669 mono_error_raise_exception (&error);
4671 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4673 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4674 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4675 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4676 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4677 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4678 aname->versioncompat = 1; /* SameMachine (default) */
4679 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4680 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4682 if (create_culture) {
4684 MonoBoolean assembly_ref = 1;
4685 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4686 args [1] = &assembly_ref;
4688 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4689 mono_error_raise_exception (&error);
4691 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4694 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4695 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4696 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4698 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4699 /* public key token isn't copied - the class library will
4700 automatically generate it from the public key if required */
4701 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4702 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4704 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4705 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4708 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4711 /* note: this function doesn't return the codebase on purpose (i.e. it can
4712 be used under partial trust as path information isn't present). */
4714 mono_array_setref (result, i, aname);
4719 /* move this in some file in mono/util/ */
4721 g_concat_dir_and_file (const char *dir, const char *file)
4723 g_return_val_if_fail (dir != NULL, NULL);
4724 g_return_val_if_fail (file != NULL, NULL);
4727 * If the directory name doesn't have a / on the end, we need
4728 * to add one so we get a proper path to the file
4730 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4731 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4733 return g_strconcat (dir, file, NULL);
4737 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4740 char *n = mono_string_to_utf8 (name);
4741 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4743 guint32 cols [MONO_MANIFEST_SIZE];
4744 guint32 impl, file_idx;
4748 for (i = 0; i < table->rows; ++i) {
4749 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4750 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4751 if (strcmp (val, n) == 0)
4755 if (i == table->rows)
4758 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4761 * this code should only be called after obtaining the
4762 * ResourceInfo and handling the other cases.
4764 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4765 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4767 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4772 module = assembly->assembly->image;
4775 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4776 mono_error_raise_exception (&error);
4777 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4779 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4782 ICALL_EXPORT gboolean
4783 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4786 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4788 guint32 cols [MONO_MANIFEST_SIZE];
4789 guint32 file_cols [MONO_FILE_SIZE];
4793 n = mono_string_to_utf8 (name);
4794 for (i = 0; i < table->rows; ++i) {
4795 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4796 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4797 if (strcmp (val, n) == 0)
4801 if (i == table->rows)
4804 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4805 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4808 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4809 case MONO_IMPLEMENTATION_FILE:
4810 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4811 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4812 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4813 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4814 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4815 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4818 info->location = RESOURCE_LOCATION_EMBEDDED;
4821 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4822 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4823 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4824 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4825 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4826 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4828 mono_set_pending_exception (ex);
4831 MonoReflectionAssembly *assm_obj;
4832 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4834 mono_error_set_pending_exception (&error);
4837 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4839 /* Obtain info recursively */
4840 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4841 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4844 case MONO_IMPLEMENTATION_EXP_TYPE:
4845 g_assert_not_reached ();
4853 ICALL_EXPORT MonoObject*
4854 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4856 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4857 MonoArray *result = NULL;
4862 /* check hash if needed */
4864 n = mono_string_to_utf8 (name);
4865 for (i = 0; i < table->rows; ++i) {
4866 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4867 if (strcmp (val, n) == 0) {
4870 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4871 fn = mono_string_new (mono_object_domain (assembly), n);
4873 return (MonoObject*)fn;
4881 for (i = 0; i < table->rows; ++i) {
4882 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4886 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4889 for (i = 0; i < table->rows; ++i) {
4890 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4891 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4892 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4893 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4898 return (MonoObject*)result;
4901 ICALL_EXPORT MonoArray*
4902 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4905 MonoDomain *domain = mono_domain_get();
4908 int i, j, file_count = 0;
4909 MonoImage **modules;
4910 guint32 module_count, real_module_count;
4911 MonoTableInfo *table;
4912 guint32 cols [MONO_FILE_SIZE];
4913 MonoImage *image = assembly->assembly->image;
4915 g_assert (image != NULL);
4916 g_assert (!assembly_is_dynamic (assembly->assembly));
4918 table = &image->tables [MONO_TABLE_FILE];
4919 file_count = table->rows;
4921 modules = image->modules;
4922 module_count = image->module_count;
4924 real_module_count = 0;
4925 for (i = 0; i < module_count; ++i)
4927 real_module_count ++;
4929 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4930 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4932 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
4933 mono_error_raise_exception (&error);
4934 mono_array_setref (res, 0, image_obj);
4936 for (i = 0; i < module_count; ++i)
4938 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
4939 mono_error_raise_exception (&error);
4940 mono_array_setref (res, j, rm);
4944 for (i = 0; i < file_count; ++i, ++j) {
4945 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4946 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
4947 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
4948 mono_error_raise_exception (&error);
4949 mono_array_setref (res, j, rm);
4952 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4954 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4955 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
4958 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
4959 mono_error_raise_exception (&error);
4960 mono_array_setref (res, j, rm);
4967 ICALL_EXPORT MonoReflectionMethod*
4968 ves_icall_GetCurrentMethod (void)
4970 MonoReflectionMethod *res = NULL;
4973 MonoMethod *m = mono_method_get_last_managed ();
4976 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
4980 while (m->is_inflated)
4981 m = ((MonoMethodInflated*)m)->declaring;
4983 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
4984 mono_error_raise_exception (&error);
4990 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4993 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4996 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4997 //method is inflated, we should inflate it on the other class
4998 MonoGenericContext ctx;
4999 ctx.method_inst = inflated->context.method_inst;
5000 ctx.class_inst = inflated->context.class_inst;
5001 if (klass->generic_class)
5002 ctx.class_inst = klass->generic_class->context.class_inst;
5003 else if (klass->generic_container)
5004 ctx.class_inst = klass->generic_container->context.class_inst;
5005 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5006 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5010 mono_class_setup_methods (method->klass);
5011 if (method->klass->exception_type)
5013 for (i = 0; i < method->klass->method.count; ++i) {
5014 if (method->klass->methods [i] == method) {
5019 mono_class_setup_methods (klass);
5020 if (klass->exception_type)
5022 g_assert (offset >= 0 && offset < klass->method.count);
5023 return klass->methods [offset];
5026 ICALL_EXPORT MonoReflectionMethod*
5027 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5029 MonoReflectionMethod *res = NULL;
5033 klass = mono_class_from_mono_type (type);
5034 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5036 if (method->klass != klass) {
5037 method = mono_method_get_equivalent_method (method, klass);
5042 klass = method->klass;
5043 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5044 mono_error_raise_exception (&error);
5048 ICALL_EXPORT MonoReflectionMethodBody*
5049 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5051 return mono_method_body_get_object (mono_domain_get (), method);
5054 ICALL_EXPORT MonoReflectionAssembly*
5055 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5058 MonoReflectionAssembly *result;
5059 MonoMethod *dest = NULL;
5061 mono_stack_walk_no_il (get_executing, &dest);
5063 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5065 mono_error_set_pending_exception (&error);
5070 ICALL_EXPORT MonoReflectionAssembly*
5071 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5074 MonoReflectionAssembly *result;
5075 MonoDomain* domain = mono_domain_get ();
5077 if (!domain->entry_assembly)
5080 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5082 mono_error_set_pending_exception (&error);
5086 ICALL_EXPORT MonoReflectionAssembly*
5087 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5092 MonoReflectionAssembly *result;
5095 mono_stack_walk_no_il (get_executing, &dest);
5097 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5101 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5104 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5106 mono_error_set_pending_exception (&error);
5110 ICALL_EXPORT MonoString *
5111 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5112 gboolean assembly_qualified)
5114 MonoDomain *domain = mono_object_domain (object);
5115 MonoTypeNameFormat format;
5120 format = assembly_qualified ?
5121 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5122 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5124 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5126 name = mono_type_get_name_full (object->type, format);
5130 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5135 res = mono_string_new (domain, name);
5142 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5144 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5145 mono_class_init_or_throw (klass);
5146 return mono_security_core_clr_class_level (klass);
5150 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5152 MonoClassField *field = rfield->field;
5153 return mono_security_core_clr_field_level (field, TRUE);
5157 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5159 MonoMethod *method = rfield->method;
5160 return mono_security_core_clr_method_level (method, TRUE);
5164 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
5166 static MonoMethod *create_culture = NULL;
5171 const char *pkey_ptr;
5173 MonoBoolean assembly_ref = 0;
5175 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5176 aname->major = name->major;
5177 aname->minor = name->minor;
5178 aname->build = name->build;
5179 aname->flags = name->flags;
5180 aname->revision = name->revision;
5181 aname->hashalg = name->hash_alg;
5182 aname->versioncompat = 1; /* SameMachine (default) */
5183 aname->processor_architecture = name->arch;
5185 if (by_default_version)
5186 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
5189 if (absolute != NULL && *absolute != '\0') {
5190 const gchar *prepend = "file://";
5193 codebase = g_strdup (absolute);
5198 for (i = strlen (codebase) - 1; i >= 0; i--)
5199 if (codebase [i] == '\\')
5202 if (*codebase == '/' && *(codebase + 1) == '/') {
5205 prepend = "file:///";
5209 result = g_strconcat (prepend, codebase, NULL);
5215 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5219 if (!create_culture) {
5220 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5221 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5222 g_assert (create_culture);
5223 mono_method_desc_free (desc);
5226 if (name->culture) {
5227 args [0] = mono_string_new (domain, name->culture);
5228 args [1] = &assembly_ref;
5230 obj = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
5231 mono_error_raise_exception (&error); /* FIXME don't raise here */
5233 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5236 if (name->public_key) {
5237 pkey_ptr = (char*)name->public_key;
5238 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5240 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5241 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5242 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5243 } else if (default_publickey) {
5244 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5245 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5248 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5249 if (name->public_key_token [0]) {
5253 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5254 p = mono_array_addr (aname->keyToken, char, 0);
5256 for (i = 0, j = 0; i < 8; i++) {
5257 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5258 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5261 } else if (default_token) {
5262 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5266 ICALL_EXPORT MonoString *
5267 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5269 MonoDomain *domain = mono_object_domain (assembly);
5270 MonoAssembly *mass = assembly->assembly;
5274 name = mono_stringify_assembly_name (&mass->aname);
5275 res = mono_string_new (domain, name);
5282 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5285 MonoAssembly *mass = assembly->assembly;
5287 if (g_path_is_absolute (mass->image->name)) {
5288 fill_reflection_assembly_name (mono_object_domain (assembly),
5289 aname, &mass->aname, mass->image->name, TRUE,
5293 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5295 fill_reflection_assembly_name (mono_object_domain (assembly),
5296 aname, &mass->aname, absolute, TRUE, TRUE,
5303 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5306 MonoImageOpenStatus status = MONO_IMAGE_OK;
5309 MonoAssemblyName name;
5312 filename = mono_string_to_utf8 (fname);
5314 dirname = g_path_get_dirname (filename);
5315 replace_shadow_path (mono_domain_get (), dirname, &filename);
5318 image = mono_image_open (filename, &status);
5324 if (status == MONO_IMAGE_IMAGE_INVALID)
5325 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5327 exc = mono_get_exception_file_not_found2 (NULL, fname);
5328 mono_set_pending_exception (exc);
5332 res = mono_assembly_fill_assembly_name (image, &name);
5334 mono_image_close (image);
5336 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5340 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5344 mono_image_close (image);
5347 ICALL_EXPORT MonoBoolean
5348 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5349 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5351 MonoBoolean result = FALSE;
5352 MonoDeclSecurityEntry entry;
5354 /* SecurityAction.RequestMinimum */
5355 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5356 *minimum = entry.blob;
5357 *minLength = entry.size;
5360 /* SecurityAction.RequestOptional */
5361 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5362 *optional = entry.blob;
5363 *optLength = entry.size;
5366 /* SecurityAction.RequestRefuse */
5367 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5368 *refused = entry.blob;
5369 *refLength = entry.size;
5377 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5379 guint32 attrs, visibility;
5381 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5382 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5383 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5386 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5392 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5395 MonoReflectionType *rt;
5398 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5401 /* we start the count from 1 because we skip the special type <Module> */
5404 for (i = 1; i < tdef->rows; ++i) {
5405 if (mono_module_type_is_visible (tdef, image, i + 1))
5409 count = tdef->rows - 1;
5411 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5412 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5414 for (i = 1; i < tdef->rows; ++i) {
5415 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5416 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, &error);
5417 mono_loader_assert_no_error (); /* Plug any leaks */
5418 g_assert (mono_error_ok (&error));
5421 rt = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5422 mono_error_raise_exception (&error); /* FIXME don't raise here */
5424 mono_array_setref (res, count, rt);
5426 MonoException *ex = mono_error_convert_to_exception (&error);
5427 mono_array_setref (*exceptions, count, ex);
5436 ICALL_EXPORT MonoArray*
5437 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5439 MonoArray *res = NULL;
5440 MonoArray *exceptions = NULL;
5441 MonoImage *image = NULL;
5442 MonoTableInfo *table = NULL;
5445 int i, len, ex_count;
5447 domain = mono_object_domain (assembly);
5449 g_assert (!assembly_is_dynamic (assembly->assembly));
5450 image = assembly->assembly->image;
5451 table = &image->tables [MONO_TABLE_FILE];
5452 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5454 /* Append data from all modules in the assembly */
5455 for (i = 0; i < table->rows; ++i) {
5456 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5457 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5460 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5461 /* Append the new types to the end of the array */
5462 if (mono_array_length (res2) > 0) {
5464 MonoArray *res3, *ex3;
5466 len1 = mono_array_length (res);
5467 len2 = mono_array_length (res2);
5469 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5470 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5471 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5474 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5475 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5476 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5483 /* the ReflectionTypeLoadException must have all the types (Types property),
5484 * NULL replacing types which throws an exception. The LoaderException must
5485 * contain all exceptions for NULL items.
5488 len = mono_array_length (res);
5491 for (i = 0; i < len; i++) {
5492 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5496 klass = mono_type_get_class (t->type);
5497 if ((klass != NULL) && klass->exception_type) {
5498 /* keep the class in the list */
5499 list = g_list_append (list, klass);
5500 /* and replace Type with NULL */
5501 mono_array_setref (res, i, NULL);
5508 if (list || ex_count) {
5510 MonoException *exc = NULL;
5511 MonoArray *exl = NULL;
5512 int j, length = g_list_length (list) + ex_count;
5514 mono_loader_clear_error ();
5516 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5517 /* Types for which mono_class_get_checked () succeeded */
5518 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5519 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5520 mono_array_setref (exl, i, exc);
5522 /* Types for which it don't */
5523 for (j = 0; j < mono_array_length (exceptions); ++j) {
5524 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5526 g_assert (i < length);
5527 mono_array_setref (exl, i, exc);
5534 exc = mono_get_exception_reflection_type_load (res, exl);
5535 mono_loader_clear_error ();
5536 mono_set_pending_exception (exc);
5543 ICALL_EXPORT gboolean
5544 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5546 MonoAssemblyName aname;
5547 MonoDomain *domain = mono_object_domain (name);
5549 gboolean is_version_defined;
5550 gboolean is_token_defined;
5552 aname.public_key = NULL;
5553 val = mono_string_to_utf8 (assname);
5554 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5555 g_free ((guint8*) aname.public_key);
5560 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5561 FALSE, is_token_defined);
5563 mono_assembly_name_free (&aname);
5564 g_free ((guint8*) aname.public_key);
5570 ICALL_EXPORT MonoReflectionType*
5571 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5574 MonoReflectionType *ret;
5575 MonoDomain *domain = mono_object_domain (module);
5578 g_assert (module->image);
5580 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5581 /* These images do not have a global type */
5584 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5585 if (!mono_error_ok (&error)) {
5586 mono_error_set_pending_exception (&error);
5590 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5591 if (!mono_error_ok (&error)) {
5592 mono_error_set_pending_exception (&error);
5600 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5602 /*if (module->image)
5603 mono_image_close (module->image);*/
5606 ICALL_EXPORT MonoString*
5607 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5609 MonoDomain *domain = mono_object_domain (module);
5611 g_assert (module->image);
5612 return mono_string_new (domain, module->image->guid);
5615 ICALL_EXPORT gpointer
5616 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5619 if (module->image && module->image->is_module_handle)
5620 return module->image->raw_data;
5623 return (gpointer) (-1);
5627 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5629 if (image_is_dynamic (image)) {
5630 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5631 *pe_kind = dyn->pe_kind;
5632 *machine = dyn->machine;
5635 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5636 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5641 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5643 return (image->md_version_major << 16) | (image->md_version_minor);
5646 ICALL_EXPORT MonoArray*
5647 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5649 MonoArray *exceptions;
5653 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5655 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5656 for (i = 0; i < mono_array_length (exceptions); ++i) {
5657 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5659 mono_set_pending_exception (ex);
5668 mono_memberref_is_method (MonoImage *image, guint32 token)
5670 if (!image_is_dynamic (image)) {
5671 guint32 cols [MONO_MEMBERREF_SIZE];
5673 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5674 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5675 mono_metadata_decode_blob_size (sig, &sig);
5676 return (*sig != 0x6);
5678 MonoClass *handle_class;
5680 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5683 return mono_defaults.methodhandle_class == handle_class;
5688 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5691 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5692 mono_array_addr (type_args, MonoType*, 0));
5694 context->class_inst = NULL;
5696 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5697 mono_array_addr (method_args, MonoType*, 0));
5699 context->method_inst = NULL;
5702 ICALL_EXPORT MonoType*
5703 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5706 int table = mono_metadata_token_table (token);
5707 int index = mono_metadata_token_index (token);
5708 MonoGenericContext context;
5711 *resolve_error = ResolveTokenError_Other;
5713 /* Validate token */
5714 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5715 (table != MONO_TABLE_TYPESPEC)) {
5716 *resolve_error = ResolveTokenError_BadTable;
5720 if (image_is_dynamic (image)) {
5721 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5722 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5723 return klass ? &klass->byval_arg : NULL;
5726 init_generic_context_from_args (&context, type_args, method_args);
5727 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5728 return klass ? &klass->byval_arg : NULL;
5731 if ((index <= 0) || (index > image->tables [table].rows)) {
5732 *resolve_error = ResolveTokenError_OutOfRange;
5736 init_generic_context_from_args (&context, type_args, method_args);
5737 klass = mono_class_get_checked (image, token, &error);
5739 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5740 if (!mono_error_ok (&error)) {
5741 mono_error_set_pending_exception (&error);
5746 return &klass->byval_arg;
5751 ICALL_EXPORT MonoMethod*
5752 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5755 int table = mono_metadata_token_table (token);
5756 int index = mono_metadata_token_index (token);
5757 MonoGenericContext context;
5760 *resolve_error = ResolveTokenError_Other;
5762 /* Validate token */
5763 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5764 (table != MONO_TABLE_MEMBERREF)) {
5765 *resolve_error = ResolveTokenError_BadTable;
5769 if (image_is_dynamic (image)) {
5770 if (table == MONO_TABLE_METHOD)
5771 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5773 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5774 *resolve_error = ResolveTokenError_BadTable;
5778 init_generic_context_from_args (&context, type_args, method_args);
5779 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5782 if ((index <= 0) || (index > image->tables [table].rows)) {
5783 *resolve_error = ResolveTokenError_OutOfRange;
5786 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5787 *resolve_error = ResolveTokenError_BadTable;
5791 init_generic_context_from_args (&context, type_args, method_args);
5792 method = mono_get_method_checked (image, token, NULL, &context, &error);
5793 mono_error_set_pending_exception (&error);
5798 ICALL_EXPORT MonoString*
5799 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5801 int index = mono_metadata_token_index (token);
5803 *error = ResolveTokenError_Other;
5805 /* Validate token */
5806 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5807 *error = ResolveTokenError_BadTable;
5811 if (image_is_dynamic (image))
5812 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5814 if ((index <= 0) || (index >= image->heap_us.size)) {
5815 *error = ResolveTokenError_OutOfRange;
5819 /* FIXME: What to do if the index points into the middle of a string ? */
5821 return mono_ldstr (mono_domain_get (), image, index);
5824 ICALL_EXPORT MonoClassField*
5825 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5829 int table = mono_metadata_token_table (token);
5830 int index = mono_metadata_token_index (token);
5831 MonoGenericContext context;
5832 MonoClassField *field;
5834 *resolve_error = ResolveTokenError_Other;
5836 /* Validate token */
5837 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5838 *resolve_error = ResolveTokenError_BadTable;
5842 if (image_is_dynamic (image)) {
5843 if (table == MONO_TABLE_FIELD)
5844 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5846 if (mono_memberref_is_method (image, token)) {
5847 *resolve_error = ResolveTokenError_BadTable;
5851 init_generic_context_from_args (&context, type_args, method_args);
5852 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5855 if ((index <= 0) || (index > image->tables [table].rows)) {
5856 *resolve_error = ResolveTokenError_OutOfRange;
5859 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5860 *resolve_error = ResolveTokenError_BadTable;
5864 init_generic_context_from_args (&context, type_args, method_args);
5865 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5866 mono_error_set_pending_exception (&error);
5872 ICALL_EXPORT MonoObject*
5873 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5877 int table = mono_metadata_token_table (token);
5879 *error = ResolveTokenError_Other;
5882 case MONO_TABLE_TYPEDEF:
5883 case MONO_TABLE_TYPEREF:
5884 case MONO_TABLE_TYPESPEC: {
5885 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5887 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
5888 mono_error_raise_exception (&merror);
5895 case MONO_TABLE_METHOD:
5896 case MONO_TABLE_METHODSPEC: {
5897 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5899 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5900 mono_error_raise_exception (&merror);
5906 case MONO_TABLE_FIELD: {
5907 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5909 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5910 mono_error_raise_exception (&merror);
5916 case MONO_TABLE_MEMBERREF:
5917 if (mono_memberref_is_method (image, token)) {
5918 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5920 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5921 mono_error_raise_exception (&merror);
5928 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5930 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5931 mono_error_raise_exception (&merror);
5940 *error = ResolveTokenError_BadTable;
5946 ICALL_EXPORT MonoArray*
5947 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5949 int table = mono_metadata_token_table (token);
5950 int idx = mono_metadata_token_index (token);
5951 MonoTableInfo *tables = image->tables;
5956 *error = ResolveTokenError_OutOfRange;
5958 /* FIXME: Support other tables ? */
5959 if (table != MONO_TABLE_STANDALONESIG)
5962 if (image_is_dynamic (image))
5965 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5968 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5970 ptr = mono_metadata_blob_heap (image, sig);
5971 len = mono_metadata_decode_blob_size (ptr, &ptr);
5973 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5974 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5978 ICALL_EXPORT MonoReflectionType*
5979 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5982 MonoReflectionType *ret;
5984 int isbyref = 0, rank;
5985 char *str = mono_string_to_utf8 (smodifiers);
5988 klass = mono_class_from_mono_type (tb->type.type);
5990 /* logic taken from mono_reflection_parse_type(): keep in sync */
5994 if (isbyref) { /* only one level allowed by the spec */
6003 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6004 mono_error_raise_exception (&error);
6008 klass = mono_ptr_class_get (&klass->byval_arg);
6009 mono_class_init (klass);
6020 else if (*p != '*') { /* '*' means unknown lower bound */
6031 klass = mono_array_class_get (klass, rank);
6032 mono_class_init (klass);
6041 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6042 mono_error_raise_exception (&error);
6047 ICALL_EXPORT MonoBoolean
6048 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
6054 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6060 check_for_invalid_type (MonoClass *klass)
6064 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6067 name = mono_type_get_full_name (klass);
6068 str = mono_string_new (mono_domain_get (), name);
6070 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
6073 ICALL_EXPORT MonoReflectionType *
6074 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6077 MonoReflectionType *ret;
6078 MonoClass *klass, *aklass;
6080 klass = mono_class_from_mono_type (type->type);
6081 check_for_invalid_type (klass);
6083 if (rank == 0) //single dimentional array
6084 aklass = mono_array_class_get (klass, 1);
6086 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6088 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6089 mono_error_raise_exception (&error);
6094 ICALL_EXPORT MonoReflectionType *
6095 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6098 MonoReflectionType *ret;
6101 klass = mono_class_from_mono_type (type->type);
6102 mono_class_init_or_throw (klass);
6103 check_for_invalid_type (klass);
6105 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6106 mono_error_raise_exception (&error);
6111 ICALL_EXPORT MonoReflectionType *
6112 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6115 MonoReflectionType *ret;
6116 MonoClass *klass, *pklass;
6118 klass = mono_class_from_mono_type (type->type);
6119 mono_class_init_or_throw (klass);
6120 check_for_invalid_type (klass);
6122 pklass = mono_ptr_class_get (type->type);
6124 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6125 mono_error_raise_exception (&error);
6130 ICALL_EXPORT MonoObject *
6131 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6132 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6135 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6136 MonoObject *delegate;
6138 MonoMethod *method = info->method;
6140 mono_class_init_or_throw (delegate_class);
6142 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
6144 if (mono_security_core_clr_enabled ()) {
6145 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6149 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6150 mono_error_raise_exception (&error);
6152 if (method_is_dynamic (method)) {
6153 /* Creating a trampoline would leak memory */
6154 func = mono_compile_method (method);
6156 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6157 method = mono_object_get_virtual_method (target, method);
6158 func = mono_create_ftnptr (mono_domain_get (),
6159 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6162 mono_delegate_ctor_with_method (delegate, target, func, method);
6167 ICALL_EXPORT MonoMulticastDelegate *
6168 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6171 MonoMulticastDelegate *ret;
6173 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6175 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6176 mono_error_raise_exception (&error);
6177 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6182 ICALL_EXPORT MonoReflectionMethod*
6183 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6185 MonoReflectionMethod *ret = NULL;
6187 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6188 mono_error_raise_exception (&error);
6194 static inline gint32
6195 mono_array_get_byte_length (MonoArray *array)
6201 klass = array->obj.vtable->klass;
6203 if (array->bounds == NULL)
6204 length = array->max_length;
6207 for (i = 0; i < klass->rank; ++ i)
6208 length *= array->bounds [i].length;
6211 switch (klass->element_class->byval_arg.type) {
6214 case MONO_TYPE_BOOLEAN:
6218 case MONO_TYPE_CHAR:
6226 return length * sizeof (gpointer);
6237 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6239 return mono_array_get_byte_length (array);
6243 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6245 return mono_array_get (array, gint8, idx);
6249 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6251 mono_array_set (array, gint8, idx, value);
6254 ICALL_EXPORT MonoBoolean
6255 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6257 guint8 *src_buf, *dest_buf;
6260 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6264 g_assert (count >= 0);
6266 /* This is called directly from the class libraries without going through the managed wrapper */
6267 MONO_CHECK_ARG_NULL (src, FALSE);
6268 MONO_CHECK_ARG_NULL (dest, FALSE);
6270 /* watch out for integer overflow */
6271 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6274 src_buf = (guint8 *)src->vector + src_offset;
6275 dest_buf = (guint8 *)dest->vector + dest_offset;
6278 memcpy (dest_buf, src_buf, count);
6280 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6285 #ifndef DISABLE_REMOTING
6286 ICALL_EXPORT MonoObject *
6287 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6290 MonoDomain *domain = mono_object_domain (this_obj);
6292 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6293 MonoTransparentProxy *tp;
6297 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6298 mono_error_raise_exception (&error);
6299 tp = (MonoTransparentProxy*) res;
6301 MONO_OBJECT_SETREF (tp, rp, rp);
6302 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6303 klass = mono_class_from_mono_type (type);
6305 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6306 mono_class_setup_vtable (klass);
6307 if (klass->exception_type) {
6308 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6312 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
6313 tp->remote_class = mono_remote_class (domain, class_name, klass);
6315 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6319 ICALL_EXPORT MonoReflectionType *
6320 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6323 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6324 mono_error_raise_exception (&error);
6330 /* System.Environment */
6333 ves_icall_System_Environment_get_UserName (void)
6335 /* using glib is more portable */
6336 return mono_string_new (mono_domain_get (), g_get_user_name ());
6340 ICALL_EXPORT MonoString *
6341 ves_icall_System_Environment_get_MachineName (void)
6343 #if defined (HOST_WIN32)
6348 len = MAX_COMPUTERNAME_LENGTH + 1;
6349 buf = g_new (gunichar2, len);
6352 if (GetComputerName (buf, (PDWORD) &len)) {
6354 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6355 mono_error_raise_exception (&error);
6360 #elif !defined(DISABLE_SOCKETS)
6364 #if defined _SC_HOST_NAME_MAX
6365 n = sysconf (_SC_HOST_NAME_MAX);
6369 buf = g_malloc (n+1);
6371 if (gethostname (buf, n) == 0){
6373 result = mono_string_new (mono_domain_get (), buf);
6380 return mono_string_new (mono_domain_get (), "mono");
6385 ves_icall_System_Environment_get_Platform (void)
6387 #if defined (TARGET_WIN32)
6390 #elif defined(__MACH__)
6393 // Notice that the value is hidden from user code, and only exposed
6394 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6395 // define and making assumptions based on Unix/128/4 values before there
6396 // was a MacOS define. Lots of code would assume that not-Unix meant
6397 // Windows, but in this case, it would be OSX.
6406 ICALL_EXPORT MonoString *
6407 ves_icall_System_Environment_get_NewLine (void)
6409 #if defined (HOST_WIN32)
6410 return mono_string_new (mono_domain_get (), "\r\n");
6412 return mono_string_new (mono_domain_get (), "\n");
6416 ICALL_EXPORT MonoBoolean
6417 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6419 #if SIZEOF_VOID_P == 8
6423 gboolean isWow64Process = FALSE;
6424 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6425 return (MonoBoolean)isWow64Process;
6427 #elif defined(HAVE_SYS_UTSNAME_H)
6428 struct utsname name;
6430 if (uname (&name) >= 0) {
6431 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6438 ICALL_EXPORT MonoString *
6439 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6447 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6448 value = g_getenv (utf8_name);
6455 return mono_string_new (mono_domain_get (), value);
6459 * There is no standard way to get at environ.
6462 #ifndef __MINGW32_VERSION
6463 #if defined(__APPLE__)
6464 #if defined (TARGET_OSX)
6465 /* Apple defines this in crt_externs.h but doesn't provide that header for
6466 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6467 * in fact exist on all implementations (so far)
6469 gchar ***_NSGetEnviron(void);
6470 #define environ (*_NSGetEnviron())
6472 static char *mono_environ[1] = { NULL };
6473 #define environ mono_environ
6474 #endif /* defined (TARGET_OSX) */
6482 ICALL_EXPORT MonoArray *
6483 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6494 env_strings = GetEnvironmentStrings();
6497 env_string = env_strings;
6498 while (*env_string != '\0') {
6499 /* weird case that MS seems to skip */
6500 if (*env_string != '=')
6502 while (*env_string != '\0')
6508 domain = mono_domain_get ();
6509 names = mono_array_new (domain, mono_defaults.string_class, n);
6513 env_string = env_strings;
6514 while (*env_string != '\0') {
6515 /* weird case that MS seems to skip */
6516 if (*env_string != '=') {
6517 equal_str = wcschr(env_string, '=');
6518 g_assert(equal_str);
6520 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6521 mono_error_raise_exception (&error);
6522 mono_array_setref (names, n, str);
6525 while (*env_string != '\0')
6530 FreeEnvironmentStrings (env_strings);
6543 for (e = environ; *e != 0; ++ e)
6546 domain = mono_domain_get ();
6547 names = mono_array_new (domain, mono_defaults.string_class, n);
6550 for (e = environ; *e != 0; ++ e) {
6551 parts = g_strsplit (*e, "=", 2);
6553 str = mono_string_new (domain, *parts);
6554 mono_array_setref (names, n, str);
6567 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6569 #if !GLIB_CHECK_VERSION(2,4,0)
6570 #define g_setenv(a,b,c) setenv(a,b,c)
6571 #define g_unsetenv(a) unsetenv(a)
6575 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6578 gunichar2 *utf16_name, *utf16_value;
6580 gchar *utf8_name, *utf8_value;
6585 utf16_name = mono_string_to_utf16 (name);
6586 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6587 SetEnvironmentVariable (utf16_name, NULL);
6588 g_free (utf16_name);
6592 utf16_value = mono_string_to_utf16 (value);
6594 SetEnvironmentVariable (utf16_name, utf16_value);
6596 g_free (utf16_name);
6597 g_free (utf16_value);
6599 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6601 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6602 g_unsetenv (utf8_name);
6607 utf8_value = mono_string_to_utf8_checked (value, &error);
6608 if (!mono_error_ok (&error)) {
6610 mono_error_set_pending_exception (&error);
6613 g_setenv (utf8_name, utf8_value, TRUE);
6616 g_free (utf8_value);
6621 ves_icall_System_Environment_Exit (int result)
6623 mono_environment_exitcode_set (result);
6625 /* FIXME: There are some cleanup hangs that should be worked out, but
6626 * if the program is going to exit, everything will be cleaned up when
6627 * NaCl exits anyway.
6629 #ifndef __native_client__
6630 if (!mono_runtime_try_shutdown ())
6631 mono_thread_exit ();
6633 /* Suspend all managed threads since the runtime is going away */
6634 mono_thread_suspend_all_other_threads ();
6636 mono_runtime_quit ();
6639 /* we may need to do some cleanup here... */
6643 ICALL_EXPORT MonoString*
6644 ves_icall_System_Environment_GetGacPath (void)
6646 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6649 ICALL_EXPORT MonoString*
6650 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6652 #if defined (HOST_WIN32)
6653 #ifndef CSIDL_FLAG_CREATE
6654 #define CSIDL_FLAG_CREATE 0x8000
6657 WCHAR path [MAX_PATH];
6658 /* Create directory if no existing */
6659 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6664 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6665 mono_error_raise_exception (&error);
6669 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6671 return mono_string_new (mono_domain_get (), "");
6674 ICALL_EXPORT MonoArray *
6675 ves_icall_System_Environment_GetLogicalDrives (void)
6678 gunichar2 buf [256], *ptr, *dname;
6680 guint initial_size = 127, size = 128;
6683 MonoString *drivestr;
6684 MonoDomain *domain = mono_domain_get ();
6690 while (size > initial_size) {
6691 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6692 if (size > initial_size) {
6695 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6696 initial_size = size;
6710 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6715 while (*u16) { u16++; len ++; }
6716 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6717 mono_error_raise_exception (&error);
6718 mono_array_setref (result, ndrives++, drivestr);
6728 ICALL_EXPORT MonoString *
6729 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6731 gunichar2 volume_name [MAX_PATH + 1];
6733 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6735 return mono_string_from_utf16 (volume_name);
6738 ICALL_EXPORT MonoString *
6739 ves_icall_System_Environment_InternalGetHome (void)
6741 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6744 static const char *encodings [] = {
6746 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6747 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6748 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6750 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6751 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6752 "x_unicode_2_0_utf_7",
6754 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6755 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6757 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6760 "unicodefffe", "utf_16be",
6767 * Returns the internal codepage, if the value of "int_code_page" is
6768 * 1 at entry, and we can not compute a suitable code page number,
6769 * returns the code page as a string
6771 ICALL_EXPORT MonoString*
6772 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6777 char *codepage = NULL;
6779 int want_name = *int_code_page;
6782 *int_code_page = -1;
6784 g_get_charset (&cset);
6785 c = codepage = strdup (cset);
6786 for (c = codepage; *c; c++){
6787 if (isascii (*c) && isalpha (*c))
6792 /* g_print ("charset: %s\n", cset); */
6794 /* handle some common aliases */
6797 for (i = 0; p != 0; ){
6800 p = encodings [++i];
6803 if (strcmp (p, codepage) == 0){
6804 *int_code_page = code;
6807 p = encodings [++i];
6810 if (strstr (codepage, "utf_8") != NULL)
6811 *int_code_page |= 0x10000000;
6814 if (want_name && *int_code_page == -1)
6815 return mono_string_new (mono_domain_get (), cset);
6820 ICALL_EXPORT MonoBoolean
6821 ves_icall_System_Environment_get_HasShutdownStarted (void)
6823 if (mono_runtime_is_shutting_down ())
6826 if (mono_domain_is_unloading (mono_domain_get ()))
6833 ves_icall_System_Environment_BroadcastSettingChange (void)
6836 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6841 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6847 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6848 MonoReflectionMethod *method,
6849 MonoArray *out_args)
6851 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6854 #ifndef DISABLE_REMOTING
6855 ICALL_EXPORT MonoBoolean
6856 ves_icall_IsTransparentProxy (MonoObject *proxy)
6861 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6867 ICALL_EXPORT MonoReflectionMethod *
6868 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6869 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6871 MonoReflectionMethod *ret = NULL;
6876 MonoMethod **vtable;
6877 MonoMethod *res = NULL;
6879 MONO_CHECK_ARG_NULL (rtype, NULL);
6880 MONO_CHECK_ARG_NULL (rmethod, NULL);
6882 method = rmethod->method;
6883 klass = mono_class_from_mono_type (rtype->type);
6884 mono_class_init_or_throw (klass);
6886 if (MONO_CLASS_IS_INTERFACE (klass))
6889 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6892 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6893 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6899 mono_class_setup_vtable (klass);
6900 vtable = klass->vtable;
6902 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6903 gboolean variance_used = FALSE;
6904 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6905 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6907 res = vtable [offs + method->slot];
6909 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6912 if (method->slot != -1)
6913 res = vtable [method->slot];
6919 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
6920 mono_error_raise_exception (&error);
6925 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6930 klass = mono_class_from_mono_type (type->type);
6931 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6933 mono_vtable_set_is_remote (vtable, enable);
6936 #else /* DISABLE_REMOTING */
6939 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6941 g_assert_not_reached ();
6946 ICALL_EXPORT MonoObject *
6947 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6954 domain = mono_object_domain (type);
6955 klass = mono_class_from_mono_type (type->type);
6956 mono_class_init_or_throw (klass);
6958 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
6959 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6963 if (klass->rank >= 1) {
6964 g_assert (klass->rank == 1);
6965 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6967 /* Bypass remoting object creation check */
6968 ret = mono_object_new_alloc_specific_checked (mono_class_vtable_full (domain, klass, TRUE), &error);
6969 mono_error_set_pending_exception (&error);
6975 ICALL_EXPORT MonoString *
6976 ves_icall_System_IO_get_temp_path (void)
6978 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6981 #ifndef PLATFORM_NO_DRIVEINFO
6982 ICALL_EXPORT MonoBoolean
6983 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6984 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6988 ULARGE_INTEGER wapi_free_bytes_avail;
6989 ULARGE_INTEGER wapi_total_number_of_bytes;
6990 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6992 *error = ERROR_SUCCESS;
6993 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6994 &wapi_total_number_of_free_bytes);
6997 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6998 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6999 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7001 *free_bytes_avail = 0;
7002 *total_number_of_bytes = 0;
7003 *total_number_of_free_bytes = 0;
7004 *error = GetLastError ();
7010 ICALL_EXPORT guint32
7011 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7013 return GetDriveType (mono_string_chars (root_path_name));
7017 ICALL_EXPORT gpointer
7018 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
7020 return mono_compile_method (method);
7023 ICALL_EXPORT MonoString *
7024 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7029 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7031 #if defined (HOST_WIN32)
7032 /* Avoid mixing '/' and '\\' */
7035 for (i = strlen (path) - 1; i >= 0; i--)
7036 if (path [i] == '/')
7040 mcpath = mono_string_new (mono_domain_get (), path);
7047 get_bundled_app_config (void)
7049 const gchar *app_config;
7052 gchar *config_file_name, *config_file_path;
7053 gsize len, config_file_path_length, config_ext_length;
7056 domain = mono_domain_get ();
7057 file = domain->setup->configuration_file;
7058 if (!file || file->length == 0)
7061 // Retrieve config file and remove the extension
7062 config_file_name = mono_string_to_utf8 (file);
7063 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7064 if (!config_file_path)
7065 config_file_path = config_file_name;
7067 config_file_path_length = strlen (config_file_path);
7068 config_ext_length = strlen (".config");
7069 if (config_file_path_length <= config_ext_length)
7072 len = config_file_path_length - config_ext_length;
7073 module = (gchar *)g_malloc0 (len + 1);
7074 memcpy (module, config_file_path, len);
7075 // Get the config file from the module name
7076 app_config = mono_config_string_for_assembly_file (module);
7079 if (config_file_name != config_file_path)
7080 g_free (config_file_name);
7081 g_free (config_file_path);
7086 return mono_string_new (mono_domain_get (), app_config);
7090 get_bundled_machine_config (void)
7092 const gchar *machine_config;
7094 machine_config = mono_get_machine_config ();
7096 if (!machine_config)
7099 return mono_string_new (mono_domain_get (), machine_config);
7102 ICALL_EXPORT MonoString *
7103 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7108 path = g_path_get_dirname (mono_get_config_dir ());
7110 #if defined (HOST_WIN32)
7111 /* Avoid mixing '/' and '\\' */
7114 for (i = strlen (path) - 1; i >= 0; i--)
7115 if (path [i] == '/')
7119 ipath = mono_string_new (mono_domain_get (), path);
7125 ICALL_EXPORT gboolean
7126 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7128 MonoPEResourceDataEntry *entry;
7131 if (!assembly || !result || !size)
7136 image = assembly->assembly->image;
7137 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7141 *result = mono_image_rva_map (image, entry->rde_data_offset);
7146 *size = entry->rde_size;
7151 ICALL_EXPORT MonoBoolean
7152 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7154 return mono_is_debugger_attached ();
7157 ICALL_EXPORT MonoBoolean
7158 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7160 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7161 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7167 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7169 if (mono_get_runtime_callbacks ()->debug_log)
7170 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7174 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7176 #if defined (HOST_WIN32)
7177 OutputDebugString (mono_string_chars (message));
7179 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7183 /* Only used for value types */
7184 ICALL_EXPORT MonoObject *
7185 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7192 domain = mono_object_domain (type);
7193 klass = mono_class_from_mono_type (type->type);
7194 mono_class_init_or_throw (klass);
7196 if (mono_class_is_nullable (klass))
7197 /* No arguments -> null */
7200 result = mono_object_new_checked (domain, klass, &error);
7201 mono_error_raise_exception (&error);
7205 ICALL_EXPORT MonoReflectionMethod *
7206 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7208 MonoReflectionMethod *ret = NULL;
7211 MonoClass *klass, *parent;
7212 MonoGenericContext *generic_inst = NULL;
7213 MonoMethod *method = m->method;
7214 MonoMethod *result = NULL;
7217 if (method->klass == NULL)
7220 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7221 MONO_CLASS_IS_INTERFACE (method->klass) ||
7222 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7225 slot = mono_method_get_vtable_slot (method);
7229 klass = method->klass;
7230 if (klass->generic_class) {
7231 generic_inst = mono_class_get_context (klass);
7232 klass = klass->generic_class->container_class;
7236 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7237 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7238 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7239 or klass is the generic container class and generic_inst is the instantiation.
7241 when we go to the parent, if the parent is an open constructed type, we need to
7242 replace the type parameters by the definitions from the generic_inst, and then take it
7243 apart again into the klass and the generic_inst.
7245 For cases like this:
7246 class C<T> : B<T, int> {
7247 public override void Foo () { ... }
7249 class B<U,V> : A<HashMap<U,V>> {
7250 public override void Foo () { ... }
7253 public virtual void Foo () { ... }
7256 if at each iteration the parent isn't open, we can skip inflating it. if at some
7257 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7260 MonoGenericContext *parent_inst = NULL;
7261 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7263 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7264 if (!mono_error_ok (&error)) {
7265 mono_error_set_pending_exception (&error);
7269 if (parent->generic_class) {
7270 parent_inst = mono_class_get_context (parent);
7271 parent = parent->generic_class->container_class;
7274 mono_class_setup_vtable (parent);
7275 if (parent->vtable_size <= slot)
7278 generic_inst = parent_inst;
7281 klass = klass->parent;
7284 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7285 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7286 if (!mono_error_ok (&error)) {
7287 mono_error_set_pending_exception (&error);
7291 generic_inst = NULL;
7293 if (klass->generic_class) {
7294 generic_inst = mono_class_get_context (klass);
7295 klass = klass->generic_class->container_class;
7301 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7302 if (!mono_error_ok (&error)) {
7303 mono_error_set_pending_exception (&error);
7308 if (klass == method->klass)
7311 /*This is possible if definition == FALSE.
7312 * Do it here to be really sure we don't read invalid memory.
7314 if (slot >= klass->vtable_size)
7317 mono_class_setup_vtable (klass);
7319 result = klass->vtable [slot];
7320 if (result == NULL) {
7321 /* It is an abstract method */
7322 gpointer iter = NULL;
7323 while ((result = mono_class_get_methods (klass, &iter)))
7324 if (result->slot == slot)
7331 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7332 mono_error_raise_exception (&error);
7336 ICALL_EXPORT MonoString*
7337 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7339 MonoMethod *method = m->method;
7341 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7346 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7348 iter->sig = *(MonoMethodSignature**)argsp;
7350 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7351 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7354 /* FIXME: it's not documented what start is exactly... */
7358 iter->args = argsp + sizeof (gpointer);
7360 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7362 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7365 ICALL_EXPORT MonoTypedRef
7366 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7368 guint32 i, arg_size;
7372 i = iter->sig->sentinelpos + iter->next_arg;
7374 g_assert (i < iter->sig->param_count);
7376 res.type = iter->sig->params [i];
7377 res.klass = mono_class_from_mono_type (res.type);
7378 arg_size = mono_type_stack_size (res.type, &align);
7379 #if defined(__arm__) || defined(__mips__)
7380 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7382 res.value = iter->args;
7383 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7384 /* Values are stored as 8 byte register sized objects, but 'value'
7385 * is dereferenced as a pointer in other routines.
7387 res.value = (char*)res.value + 4;
7389 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7390 if (arg_size <= sizeof (gpointer)) {
7392 int padding = arg_size - mono_type_size (res.type, &dummy);
7393 res.value = (guint8*)res.value + padding;
7396 iter->args = (char*)iter->args + arg_size;
7399 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7404 ICALL_EXPORT MonoTypedRef
7405 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7407 guint32 i, arg_size;
7411 i = iter->sig->sentinelpos + iter->next_arg;
7413 g_assert (i < iter->sig->param_count);
7415 while (i < iter->sig->param_count) {
7416 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7418 res.type = iter->sig->params [i];
7419 res.klass = mono_class_from_mono_type (res.type);
7420 /* FIXME: endianess issue... */
7421 arg_size = mono_type_stack_size (res.type, &align);
7422 #if defined(__arm__) || defined(__mips__)
7423 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7425 res.value = iter->args;
7426 iter->args = (char*)iter->args + arg_size;
7428 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7431 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7439 ICALL_EXPORT MonoType*
7440 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7444 i = iter->sig->sentinelpos + iter->next_arg;
7446 g_assert (i < iter->sig->param_count);
7448 return iter->sig->params [i];
7451 ICALL_EXPORT MonoObject*
7452 mono_TypedReference_ToObject (MonoTypedRef* tref)
7454 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7455 MonoObject** objp = (MonoObject **)tref->value;
7459 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
7462 ICALL_EXPORT MonoTypedRef
7463 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7466 MonoReflectionField *f;
7468 MonoType *ftype = NULL;
7472 memset (&res, 0, sizeof (res));
7475 g_assert (mono_array_length (fields) > 0);
7477 klass = target->vtable->klass;
7479 for (i = 0; i < mono_array_length (fields); ++i) {
7480 f = mono_array_get (fields, MonoReflectionField*, i);
7482 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7485 if (f->field->parent != klass) {
7486 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7490 p = (guint8*)target + f->field->offset;
7492 p += f->field->offset - sizeof (MonoObject);
7493 klass = mono_class_from_mono_type (f->field->type);
7494 ftype = f->field->type;
7498 res.klass = mono_class_from_mono_type (ftype);
7505 prelink_method (MonoMethod *method)
7507 const char *exc_class, *exc_arg;
7508 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7510 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7512 mono_raise_exception(
7513 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7515 /* create the wrapper, too? */
7519 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7521 prelink_method (method->method);
7525 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7527 MonoClass *klass = mono_class_from_mono_type (type->type);
7529 gpointer iter = NULL;
7531 mono_class_init_or_throw (klass);
7533 while ((m = mono_class_get_methods (klass, &iter)))
7537 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7539 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7540 gint32 const **exponents,
7541 gunichar2 const **digitLowerTable,
7542 gunichar2 const **digitUpperTable,
7543 gint64 const **tenPowersList,
7544 gint32 const **decHexDigits)
7546 *mantissas = Formatter_MantissaBitsTable;
7547 *exponents = Formatter_TensExponentTable;
7548 *digitLowerTable = Formatter_DigitLowerTable;
7549 *digitUpperTable = Formatter_DigitUpperTable;
7550 *tenPowersList = Formatter_TenPowersList;
7551 *decHexDigits = Formatter_DecHexDigits;
7555 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7556 * and avoid useless allocations.
7561 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7564 MonoReflectionType *rt;
7567 for (i = 0; i < type->num_mods; ++i) {
7568 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7573 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7575 for (i = 0; i < type->num_mods; ++i) {
7576 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7577 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
7578 mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */
7580 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, &error);
7581 mono_error_raise_exception (&error);
7583 mono_array_setref (res, count, rt);
7590 ICALL_EXPORT MonoArray*
7591 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7593 MonoType *type = param->ClassImpl->type;
7594 MonoClass *member_class = mono_object_class (param->MemberImpl);
7595 MonoMethod *method = NULL;
7598 MonoMethodSignature *sig;
7600 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7601 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7602 method = rmethod->method;
7603 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7604 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7605 if (!(method = prop->property->get))
7606 method = prop->property->set;
7609 char *type_name = mono_type_get_full_name (member_class);
7610 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7611 MonoException *ex = mono_get_exception_not_supported (msg);
7614 mono_set_pending_exception (ex);
7618 image = method->klass->image;
7619 pos = param->PositionImpl;
7620 sig = mono_method_signature (method);
7624 type = sig->params [pos];
7626 return type_array_from_modifiers (image, type, optional);
7630 get_property_type (MonoProperty *prop)
7632 MonoMethodSignature *sig;
7634 sig = mono_method_signature (prop->get);
7636 } else if (prop->set) {
7637 sig = mono_method_signature (prop->set);
7638 return sig->params [sig->param_count - 1];
7643 ICALL_EXPORT MonoArray*
7644 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7646 MonoType *type = get_property_type (property->property);
7647 MonoImage *image = property->klass->image;
7651 return type_array_from_modifiers (image, type, optional);
7655 *Construct a MonoType suited to be used to decode a constant blob object.
7657 * @type is the target type which will be constructed
7658 * @blob_type is the blob type, for example, that comes from the constant table
7659 * @real_type is the expected constructed type.
7662 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7664 type->type = blob_type;
7665 type->data.klass = NULL;
7666 if (blob_type == MONO_TYPE_CLASS)
7667 type->data.klass = mono_defaults.object_class;
7668 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7669 /* For enums, we need to use the base type */
7670 type->type = MONO_TYPE_VALUETYPE;
7671 type->data.klass = mono_class_from_mono_type (real_type);
7673 type->data.klass = mono_class_from_mono_type (real_type);
7676 ICALL_EXPORT MonoObject*
7677 property_info_get_default_value (MonoReflectionProperty *property)
7680 MonoProperty *prop = property->property;
7681 MonoType *type = get_property_type (prop);
7682 MonoDomain *domain = mono_object_domain (property);
7683 MonoTypeEnum def_type;
7684 const char *def_value;
7687 mono_class_init (prop->parent);
7689 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7690 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7694 def_value = mono_class_get_property_default_value (prop, &def_type);
7696 mono_type_from_blob_type (&blob_type, def_type, type);
7697 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7702 ICALL_EXPORT MonoBoolean
7703 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7705 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7706 MonoCustomAttrInfo *cinfo;
7709 mono_class_init_or_throw (attr_class);
7711 cinfo = mono_reflection_get_custom_attrs_info (obj);
7714 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7716 mono_custom_attrs_free (cinfo);
7720 ICALL_EXPORT MonoArray*
7721 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7723 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7728 mono_class_init_or_throw (attr_class);
7730 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7731 if (!mono_error_ok (&error)) {
7732 mono_error_set_pending_exception (&error);
7736 if (mono_loader_get_last_error ()) {
7737 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7744 ICALL_EXPORT MonoString*
7745 ves_icall_Mono_Runtime_GetDisplayName (void)
7748 MonoString *display_name;
7750 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7751 display_name = mono_string_new (mono_domain_get (), info);
7753 return display_name;
7756 ICALL_EXPORT MonoString*
7757 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7760 MonoString *message;
7764 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7765 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7768 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7770 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7771 mono_error_raise_exception (&error);
7778 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7781 char *path_str = mono_string_to_utf8 (path);
7783 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7791 #ifndef DISABLE_ICALL_TABLES
7793 #define ICALL_TYPE(id,name,first)
7794 #define ICALL(id,name,func) Icall_ ## id,
7797 #include "metadata/icall-def.h"
7803 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7804 #define ICALL(id,name,func)
7806 #include "metadata/icall-def.h"
7812 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7813 #define ICALL(id,name,func)
7815 guint16 first_icall;
7818 static const IcallTypeDesc
7819 icall_type_descs [] = {
7820 #include "metadata/icall-def.h"
7824 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7827 #define ICALL_TYPE(id,name,first)
7830 #ifdef HAVE_ARRAY_ELEM_INIT
7831 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7832 #define MSGSTRFIELD1(line) str##line
7834 static const struct msgstrtn_t {
7835 #define ICALL(id,name,func)
7837 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7838 #include "metadata/icall-def.h"
7840 } icall_type_names_str = {
7841 #define ICALL_TYPE(id,name,first) (name),
7842 #include "metadata/icall-def.h"
7845 static const guint16 icall_type_names_idx [] = {
7846 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7847 #include "metadata/icall-def.h"
7850 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7852 static const struct msgstr_t {
7854 #define ICALL_TYPE(id,name,first)
7855 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7856 #include "metadata/icall-def.h"
7858 } icall_names_str = {
7859 #define ICALL(id,name,func) (name),
7860 #include "metadata/icall-def.h"
7863 static const guint16 icall_names_idx [] = {
7864 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7865 #include "metadata/icall-def.h"
7868 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7874 #define ICALL_TYPE(id,name,first) name,
7875 #define ICALL(id,name,func)
7876 static const char* const
7877 icall_type_names [] = {
7878 #include "metadata/icall-def.h"
7882 #define icall_type_name_get(id) (icall_type_names [(id)])
7886 #define ICALL_TYPE(id,name,first)
7887 #define ICALL(id,name,func) name,
7888 static const char* const
7890 #include "metadata/icall-def.h"
7893 #define icall_name_get(id) icall_names [(id)]
7895 #endif /* !HAVE_ARRAY_ELEM_INIT */
7899 #define ICALL_TYPE(id,name,first)
7900 #define ICALL(id,name,func) func,
7901 static const gconstpointer
7902 icall_functions [] = {
7903 #include "metadata/icall-def.h"
7907 #ifdef ENABLE_ICALL_SYMBOL_MAP
7910 #define ICALL_TYPE(id,name,first)
7911 #define ICALL(id,name,func) #func,
7912 static const gconstpointer
7913 icall_symbols [] = {
7914 #include "metadata/icall-def.h"
7919 #endif /* DISABLE_ICALL_TABLES */
7921 static mono_mutex_t icall_mutex;
7922 static GHashTable *icall_hash = NULL;
7923 static GHashTable *jit_icall_hash_name = NULL;
7924 static GHashTable *jit_icall_hash_addr = NULL;
7927 mono_icall_init (void)
7929 #ifndef DISABLE_ICALL_TABLES
7932 /* check that tables are sorted: disable in release */
7935 const char *prev_class = NULL;
7936 const char *prev_method;
7938 for (i = 0; i < Icall_type_num; ++i) {
7939 const IcallTypeDesc *desc;
7942 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7943 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7944 prev_class = icall_type_name_get (i);
7945 desc = &icall_type_descs [i];
7946 num_icalls = icall_desc_num_icalls (desc);
7947 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7948 for (j = 0; j < num_icalls; ++j) {
7949 const char *methodn = icall_name_get (desc->first_icall + j);
7950 if (prev_method && strcmp (prev_method, methodn) >= 0)
7951 g_print ("method %s should come before method %s\n", methodn, prev_method);
7952 prev_method = methodn;
7958 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7959 mono_os_mutex_init (&icall_mutex);
7963 mono_icall_lock (void)
7965 mono_locks_os_acquire (&icall_mutex, IcallLock);
7969 mono_icall_unlock (void)
7971 mono_locks_os_release (&icall_mutex, IcallLock);
7975 mono_icall_cleanup (void)
7977 g_hash_table_destroy (icall_hash);
7978 g_hash_table_destroy (jit_icall_hash_name);
7979 g_hash_table_destroy (jit_icall_hash_addr);
7980 mono_os_mutex_destroy (&icall_mutex);
7984 * mono_add_internal_call:
7985 * @name: method specification to surface to the managed world
7986 * @method: pointer to a C method to invoke when the method is called
7988 * This method surfaces the C function pointed by @method as a method
7989 * that has been surfaced in managed code with the method specified in
7990 * @name as an internal call.
7992 * Internal calls are surfaced to all app domains loaded and they are
7993 * accessibly by a type with the specified name.
7995 * You must provide a fully qualified type name, that is namespaces
7996 * and type name, followed by a colon and the method name, with an
7997 * optional signature to bind.
7999 * For example, the following are all valid declarations:
8001 * "MyApp.Services.ScriptService:Accelerate"
8002 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8004 * You use method parameters in cases where there might be more than
8005 * one surface method to managed code. That way you can register different
8006 * internal calls for different method overloads.
8008 * The internal calls are invoked with no marshalling. This means that .NET
8009 * types like System.String are exposed as `MonoString *` parameters. This is
8010 * different than the way that strings are surfaced in P/Invoke.
8012 * For more information on how the parameters are marshalled, see the
8013 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8016 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8017 * reference for more information on the format of method descriptions.
8020 mono_add_internal_call (const char *name, gconstpointer method)
8024 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8026 mono_icall_unlock ();
8029 #ifndef DISABLE_ICALL_TABLES
8031 #ifdef HAVE_ARRAY_ELEM_INIT
8033 compare_method_imap (const void *key, const void *elem)
8035 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8036 return strcmp (key, method_name);
8040 find_method_icall (const IcallTypeDesc *imap, const char *name)
8042 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);
8045 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8049 compare_class_imap (const void *key, const void *elem)
8051 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8052 return strcmp (key, class_name);
8055 static const IcallTypeDesc*
8056 find_class_icalls (const char *name)
8058 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);
8061 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8064 #else /* HAVE_ARRAY_ELEM_INIT */
8067 compare_method_imap (const void *key, const void *elem)
8069 const char** method_name = (const char**)elem;
8070 return strcmp (key, *method_name);
8074 find_method_icall (const IcallTypeDesc *imap, const char *name)
8076 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8079 return (gpointer)icall_functions [(nameslot - icall_names)];
8083 compare_class_imap (const void *key, const void *elem)
8085 const char** class_name = (const char**)elem;
8086 return strcmp (key, *class_name);
8089 static const IcallTypeDesc*
8090 find_class_icalls (const char *name)
8092 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8095 return &icall_type_descs [nameslot - icall_type_names];
8098 #endif /* HAVE_ARRAY_ELEM_INIT */
8100 #endif /* DISABLE_ICALL_TABLES */
8103 * we should probably export this as an helper (handle nested types).
8104 * Returns the number of chars written in buf.
8107 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8109 int nspacelen, cnamelen;
8110 nspacelen = strlen (klass->name_space);
8111 cnamelen = strlen (klass->name);
8112 if (nspacelen + cnamelen + 2 > bufsize)
8115 memcpy (buf, klass->name_space, nspacelen);
8116 buf [nspacelen ++] = '.';
8118 memcpy (buf + nspacelen, klass->name, cnamelen);
8119 buf [nspacelen + cnamelen] = 0;
8120 return nspacelen + cnamelen;
8123 #ifdef DISABLE_ICALL_TABLES
8125 no_icall_table (void)
8127 g_assert_not_reached ();
8132 mono_lookup_internal_call (MonoMethod *method)
8137 int typelen = 0, mlen, siglen;
8139 #ifndef DISABLE_ICALL_TABLES
8140 const IcallTypeDesc *imap = NULL;
8143 g_assert (method != NULL);
8145 if (method->is_inflated)
8146 method = ((MonoMethodInflated *) method)->declaring;
8148 if (method->klass->nested_in) {
8149 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8153 mname [pos++] = '/';
8156 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8162 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8167 #ifndef DISABLE_ICALL_TABLES
8168 imap = find_class_icalls (mname);
8171 mname [typelen] = ':';
8172 mname [typelen + 1] = ':';
8174 mlen = strlen (method->name);
8175 memcpy (mname + typelen + 2, method->name, mlen);
8176 sigstart = mname + typelen + 2 + mlen;
8179 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8180 siglen = strlen (tmpsig);
8181 if (typelen + mlen + siglen + 6 > sizeof (mname))
8184 memcpy (sigstart + 1, tmpsig, siglen);
8185 sigstart [siglen + 1] = ')';
8186 sigstart [siglen + 2] = 0;
8191 res = g_hash_table_lookup (icall_hash, mname);
8193 mono_icall_unlock ();;
8196 /* try without signature */
8198 res = g_hash_table_lookup (icall_hash, mname);
8200 mono_icall_unlock ();
8204 #ifdef DISABLE_ICALL_TABLES
8205 mono_icall_unlock ();
8206 /* Fail only when the result is actually used */
8207 /* mono_marshal_get_native_wrapper () depends on this */
8208 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8209 return ves_icall_System_String_ctor_RedirectToCreateString;
8211 return no_icall_table;
8213 /* it wasn't found in the static call tables */
8215 mono_icall_unlock ();
8218 res = find_method_icall (imap, sigstart - mlen);
8220 mono_icall_unlock ();
8223 /* try _with_ signature */
8225 res = find_method_icall (imap, sigstart - mlen);
8227 mono_icall_unlock ();
8231 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8232 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8233 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8234 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8235 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");
8236 g_print ("If you see other errors or faults after this message they are probably related\n");
8237 g_print ("and you need to fix your mono install first.\n");
8239 mono_icall_unlock ();
8245 #ifdef ENABLE_ICALL_SYMBOL_MAP
8247 func_cmp (gconstpointer key, gconstpointer p)
8249 return (gsize)key - (gsize)*(gsize*)p;
8254 * mono_lookup_icall_symbol:
8256 * Given the icall METHOD, returns its C symbol.
8259 mono_lookup_icall_symbol (MonoMethod *m)
8261 #ifdef DISABLE_ICALL_TABLES
8262 g_assert_not_reached ();
8265 #ifdef ENABLE_ICALL_SYMBOL_MAP
8269 static gconstpointer *functions_sorted;
8270 static const char**symbols_sorted;
8271 static gboolean inited;
8276 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8277 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8278 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8279 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8280 /* Bubble sort the two arrays */
8284 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8285 if (functions_sorted [i] > functions_sorted [i + 1]) {
8288 tmp = functions_sorted [i];
8289 functions_sorted [i] = functions_sorted [i + 1];
8290 functions_sorted [i + 1] = tmp;
8291 tmp = symbols_sorted [i];
8292 symbols_sorted [i] = symbols_sorted [i + 1];
8293 symbols_sorted [i + 1] = tmp;
8300 func = mono_lookup_internal_call (m);
8303 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8307 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8309 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8310 g_assert_not_reached ();
8317 type_from_typename (char *type_name)
8319 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8321 if (!strcmp (type_name, "int"))
8322 klass = mono_defaults.int_class;
8323 else if (!strcmp (type_name, "ptr"))
8324 klass = mono_defaults.int_class;
8325 else if (!strcmp (type_name, "void"))
8326 klass = mono_defaults.void_class;
8327 else if (!strcmp (type_name, "int32"))
8328 klass = mono_defaults.int32_class;
8329 else if (!strcmp (type_name, "uint32"))
8330 klass = mono_defaults.uint32_class;
8331 else if (!strcmp (type_name, "int8"))
8332 klass = mono_defaults.sbyte_class;
8333 else if (!strcmp (type_name, "uint8"))
8334 klass = mono_defaults.byte_class;
8335 else if (!strcmp (type_name, "int16"))
8336 klass = mono_defaults.int16_class;
8337 else if (!strcmp (type_name, "uint16"))
8338 klass = mono_defaults.uint16_class;
8339 else if (!strcmp (type_name, "long"))
8340 klass = mono_defaults.int64_class;
8341 else if (!strcmp (type_name, "ulong"))
8342 klass = mono_defaults.uint64_class;
8343 else if (!strcmp (type_name, "float"))
8344 klass = mono_defaults.single_class;
8345 else if (!strcmp (type_name, "double"))
8346 klass = mono_defaults.double_class;
8347 else if (!strcmp (type_name, "object"))
8348 klass = mono_defaults.object_class;
8349 else if (!strcmp (type_name, "obj"))
8350 klass = mono_defaults.object_class;
8351 else if (!strcmp (type_name, "string"))
8352 klass = mono_defaults.string_class;
8353 else if (!strcmp (type_name, "bool"))
8354 klass = mono_defaults.boolean_class;
8355 else if (!strcmp (type_name, "boolean"))
8356 klass = mono_defaults.boolean_class;
8358 g_error ("%s", type_name);
8359 g_assert_not_reached ();
8361 return &klass->byval_arg;
8365 * LOCKING: Take the corlib image lock.
8367 MonoMethodSignature*
8368 mono_create_icall_signature (const char *sigstr)
8373 MonoMethodSignature *res, *res2;
8374 MonoImage *corlib = mono_defaults.corlib;
8376 mono_image_lock (corlib);
8377 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8378 mono_image_unlock (corlib);
8383 parts = g_strsplit (sigstr, " ", 256);
8392 res = mono_metadata_signature_alloc (corlib, len - 1);
8397 * Under windows, the default pinvoke calling convention is STDCALL but
8400 res->call_convention = MONO_CALL_C;
8403 res->ret = type_from_typename (parts [0]);
8404 for (i = 1; i < len; ++i) {
8405 res->params [i - 1] = type_from_typename (parts [i]);
8410 mono_image_lock (corlib);
8411 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8413 res = res2; /*Value is allocated in the image pool*/
8415 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8416 mono_image_unlock (corlib);
8422 mono_find_jit_icall_by_name (const char *name)
8424 MonoJitICallInfo *info;
8425 g_assert (jit_icall_hash_name);
8428 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8429 mono_icall_unlock ();
8434 mono_find_jit_icall_by_addr (gconstpointer addr)
8436 MonoJitICallInfo *info;
8437 g_assert (jit_icall_hash_addr);
8440 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8441 mono_icall_unlock ();
8447 * mono_get_jit_icall_info:
8449 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8450 * caller should access it while holding the icall lock.
8453 mono_get_jit_icall_info (void)
8455 return jit_icall_hash_name;
8459 * mono_lookup_jit_icall_symbol:
8461 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8464 mono_lookup_jit_icall_symbol (const char *name)
8466 MonoJitICallInfo *info;
8467 const char *res = NULL;
8470 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8472 res = info->c_symbol;
8473 mono_icall_unlock ();
8478 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8481 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8482 mono_icall_unlock ();
8486 * 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
8487 * icalls without wrappers in some cases.
8490 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8492 MonoJitICallInfo *info;
8499 if (!jit_icall_hash_name) {
8500 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8501 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8504 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8505 g_warning ("jit icall already defined \"%s\"\n", name);
8506 g_assert_not_reached ();
8509 info = g_new0 (MonoJitICallInfo, 1);
8514 info->c_symbol = c_symbol;
8515 info->no_raise = no_raise;
8518 info->wrapper = func;
8520 info->wrapper = NULL;
8523 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8524 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8526 mono_icall_unlock ();
8531 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8533 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);