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);
111 /* Lazy class loading functions */
112 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
113 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
114 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
115 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
116 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
120 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
122 static inline MonoBoolean
123 is_generic_parameter (MonoType *type)
125 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
129 mono_class_init_or_throw (MonoClass *klass)
131 if (!mono_class_init (klass))
132 mono_raise_exception (mono_class_get_exception_for_failure (klass));
135 ICALL_EXPORT MonoObject *
136 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
142 ac = (MonoClass *)arr->obj.vtable->klass;
144 esize = mono_array_element_size (ac);
145 ea = (gpointer*)((char*)arr->vector + (pos * esize));
147 if (ac->element_class->valuetype)
148 return mono_value_box (arr->obj.vtable->domain, ac->element_class, ea);
150 return (MonoObject *)*ea;
153 ICALL_EXPORT MonoObject *
154 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
160 MONO_CHECK_ARG_NULL (idxs, NULL);
163 ic = (MonoClass *)io->obj.vtable->klass;
165 ac = (MonoClass *)arr->obj.vtable->klass;
167 g_assert (ic->rank == 1);
168 if (io->bounds != NULL || io->max_length != ac->rank) {
169 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
173 ind = (gint32 *)io->vector;
175 if (arr->bounds == NULL) {
176 if (*ind < 0 || *ind >= arr->max_length) {
177 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
181 return ves_icall_System_Array_GetValueImpl (arr, *ind);
184 for (i = 0; i < ac->rank; i++) {
185 if ((ind [i] < arr->bounds [i].lower_bound) ||
186 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
187 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
192 pos = ind [0] - arr->bounds [0].lower_bound;
193 for (i = 1; i < ac->rank; i++)
194 pos = pos * arr->bounds [i].length + ind [i] -
195 arr->bounds [i].lower_bound;
197 return ves_icall_System_Array_GetValueImpl (arr, pos);
201 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
203 MonoClass *ac, *vc, *ec;
213 vc = value->vtable->klass;
217 ac = arr->obj.vtable->klass;
218 ec = ac->element_class;
220 esize = mono_array_element_size (ac);
221 ea = (gpointer*)((char*)arr->vector + (pos * esize));
222 va = (gpointer*)((char*)value + sizeof (MonoObject));
224 if (mono_class_is_nullable (ec)) {
225 mono_nullable_init ((guint8*)ea, value, ec);
230 mono_gc_bzero_atomic (ea, esize);
234 #define NO_WIDENING_CONVERSION G_STMT_START{\
235 mono_set_pending_exception (mono_get_exception_argument ( \
236 "value", "not a widening conversion")); \
240 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
241 if (esize < vsize + (extra)) { \
242 mono_set_pending_exception (mono_get_exception_argument ( \
243 "value", "not a widening conversion")); \
248 #define INVALID_CAST G_STMT_START{ \
249 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
250 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
254 /* Check element (destination) type. */
255 switch (ec->byval_arg.type) {
256 case MONO_TYPE_STRING:
257 switch (vc->byval_arg.type) {
258 case MONO_TYPE_STRING:
264 case MONO_TYPE_BOOLEAN:
265 switch (vc->byval_arg.type) {
266 case MONO_TYPE_BOOLEAN:
279 NO_WIDENING_CONVERSION;
288 if (!ec->valuetype) {
289 if (!mono_object_isinst (value, ec))
291 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
295 if (mono_object_isinst (value, ec)) {
296 if (ec->has_references)
297 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
299 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
306 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
308 et = ec->byval_arg.type;
309 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
310 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
312 vt = vc->byval_arg.type;
313 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
314 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
316 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
322 case MONO_TYPE_CHAR: \
323 CHECK_WIDENING_CONVERSION(0); \
324 *(etype *) ea = (etype) u64; \
326 /* You can't assign a signed value to an unsigned array. */ \
331 /* You can't assign a floating point number to an integer array. */ \
334 NO_WIDENING_CONVERSION; \
338 #define ASSIGN_SIGNED(etype) G_STMT_START{\
344 CHECK_WIDENING_CONVERSION(0); \
345 *(etype *) ea = (etype) i64; \
347 /* You can assign an unsigned value to a signed array if the array's */ \
348 /* element size is larger than the value size. */ \
353 case MONO_TYPE_CHAR: \
354 CHECK_WIDENING_CONVERSION(1); \
355 *(etype *) ea = (etype) u64; \
357 /* You can't assign a floating point number to an integer array. */ \
360 NO_WIDENING_CONVERSION; \
364 #define ASSIGN_REAL(etype) G_STMT_START{\
368 CHECK_WIDENING_CONVERSION(0); \
369 *(etype *) ea = (etype) r64; \
371 /* All integer values fit into a floating point array, so we don't */ \
372 /* need to CHECK_WIDENING_CONVERSION here. */ \
377 *(etype *) ea = (etype) i64; \
383 case MONO_TYPE_CHAR: \
384 *(etype *) ea = (etype) u64; \
391 u64 = *(guint8 *) va;
394 u64 = *(guint16 *) va;
397 u64 = *(guint32 *) va;
400 u64 = *(guint64 *) va;
406 i64 = *(gint16 *) va;
409 i64 = *(gint32 *) va;
412 i64 = *(gint64 *) va;
415 r64 = *(gfloat *) va;
418 r64 = *(gdouble *) va;
421 u64 = *(guint16 *) va;
423 case MONO_TYPE_BOOLEAN:
424 /* Boolean is only compatible with itself. */
437 NO_WIDENING_CONVERSION;
444 /* If we can't do a direct copy, let's try a widening conversion. */
447 ASSIGN_UNSIGNED (guint16);
449 ASSIGN_UNSIGNED (guint8);
451 ASSIGN_UNSIGNED (guint16);
453 ASSIGN_UNSIGNED (guint32);
455 ASSIGN_UNSIGNED (guint64);
457 ASSIGN_SIGNED (gint8);
459 ASSIGN_SIGNED (gint16);
461 ASSIGN_SIGNED (gint32);
463 ASSIGN_SIGNED (gint64);
465 ASSIGN_REAL (gfloat);
467 ASSIGN_REAL (gdouble);
471 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
475 #undef NO_WIDENING_CONVERSION
476 #undef CHECK_WIDENING_CONVERSION
477 #undef ASSIGN_UNSIGNED
483 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
489 MONO_CHECK_ARG_NULL (idxs,);
491 ic = idxs->obj.vtable->klass;
492 ac = arr->obj.vtable->klass;
494 g_assert (ic->rank == 1);
495 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
496 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
500 ind = (gint32 *)idxs->vector;
502 if (arr->bounds == NULL) {
503 if (*ind < 0 || *ind >= arr->max_length) {
504 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
508 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
512 for (i = 0; i < ac->rank; i++)
513 if ((ind [i] < arr->bounds [i].lower_bound) ||
514 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
515 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
519 pos = ind [0] - arr->bounds [0].lower_bound;
520 for (i = 1; i < ac->rank; i++)
521 pos = pos * arr->bounds [i].length + ind [i] -
522 arr->bounds [i].lower_bound;
524 ves_icall_System_Array_SetValueImpl (arr, value, pos);
527 ICALL_EXPORT MonoArray *
528 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
531 MonoClass *aklass, *klass;
534 gboolean bounded = FALSE;
536 MONO_CHECK_ARG_NULL (type, NULL);
537 MONO_CHECK_ARG_NULL (lengths, NULL);
539 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
541 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
543 for (i = 0; i < mono_array_length (lengths); i++) {
544 if (mono_array_get (lengths, gint32, i) < 0) {
545 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
550 klass = mono_class_from_mono_type (type->type);
551 mono_class_init_or_throw (klass);
553 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
554 /* vectors are not the same as one dimensional arrays with no-zero bounds */
559 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
561 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
562 for (i = 0; i < aklass->rank; ++i) {
563 sizes [i] = mono_array_get (lengths, guint32, i);
565 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
567 sizes [i + aklass->rank] = 0;
570 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
571 mono_error_set_pending_exception (&error);
576 ICALL_EXPORT MonoArray *
577 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
580 MonoClass *aklass, *klass;
583 gboolean bounded = FALSE;
585 MONO_CHECK_ARG_NULL (type, NULL);
586 MONO_CHECK_ARG_NULL (lengths, NULL);
588 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
590 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
592 for (i = 0; i < mono_array_length (lengths); i++) {
593 if ((mono_array_get (lengths, gint64, i) < 0) ||
594 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
595 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
600 klass = mono_class_from_mono_type (type->type);
601 mono_class_init_or_throw (klass);
603 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
604 /* vectors are not the same as one dimensional arrays with no-zero bounds */
609 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
611 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
612 for (i = 0; i < aklass->rank; ++i) {
613 sizes [i] = mono_array_get (lengths, guint64, i);
615 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
617 sizes [i + aklass->rank] = 0;
620 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
621 mono_error_set_pending_exception (&error);
627 ves_icall_System_Array_GetRank (MonoObject *arr)
629 return arr->vtable->klass->rank;
633 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
635 gint32 rank = arr->obj.vtable->klass->rank;
638 if ((dimension < 0) || (dimension >= rank)) {
639 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
643 if (arr->bounds == NULL)
644 length = arr->max_length;
646 length = arr->bounds [dimension].length;
648 #ifdef MONO_BIG_ARRAYS
649 if (length > G_MAXINT32) {
650 mono_set_pending_exception (mono_get_exception_overflow ());
658 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
660 gint32 rank = arr->obj.vtable->klass->rank;
662 if ((dimension < 0) || (dimension >= rank)) {
663 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
667 if (arr->bounds == NULL)
668 return arr->max_length;
670 return arr->bounds [dimension].length;
674 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
676 gint32 rank = arr->obj.vtable->klass->rank;
678 if ((dimension < 0) || (dimension >= rank)) {
679 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
683 if (arr->bounds == NULL)
686 return arr->bounds [dimension].lower_bound;
690 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
692 int sz = mono_array_element_size (mono_object_class (arr));
693 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
696 ICALL_EXPORT gboolean
697 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
702 MonoVTable *src_vtable;
703 MonoVTable *dest_vtable;
704 MonoClass *src_class;
705 MonoClass *dest_class;
707 src_vtable = source->obj.vtable;
708 dest_vtable = dest->obj.vtable;
710 if (src_vtable->rank != dest_vtable->rank)
713 if (source->bounds || dest->bounds)
716 /* there's no integer overflow since mono_array_length returns an unsigned integer */
717 if ((dest_idx + length > mono_array_length_fast (dest)) ||
718 (source_idx + length > mono_array_length_fast (source)))
721 src_class = src_vtable->klass->element_class;
722 dest_class = dest_vtable->klass->element_class;
725 * Handle common cases.
728 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
729 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
731 if (src_class == mono_defaults.object_class && dest_class->valuetype)
734 /* Check if we're copying a char[] <==> (u)short[] */
735 if (src_class != dest_class) {
736 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
739 /* 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. */
740 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
744 if (dest_class->valuetype) {
745 element_size = mono_array_element_size (source->obj.vtable->klass);
746 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
747 if (dest_class->has_references) {
748 mono_value_copy_array (dest, dest_idx, source_addr, length);
750 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
751 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
754 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
761 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
767 ac = (MonoClass *)arr->obj.vtable->klass;
769 esize = mono_array_element_size (ac);
770 ea = (gpointer*)((char*)arr->vector + (pos * esize));
772 mono_gc_memmove_atomic (value, ea, esize);
776 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
782 ac = (MonoClass *)arr->obj.vtable->klass;
783 ec = ac->element_class;
785 esize = mono_array_element_size (ac);
786 ea = (gpointer*)((char*)arr->vector + (pos * esize));
788 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
789 g_assert (esize == sizeof (gpointer));
790 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
792 g_assert (ec->inited);
793 g_assert (esize == mono_class_value_size (ec, NULL));
794 if (ec->has_references)
795 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
797 mono_gc_memmove_atomic (ea, value, esize);
802 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
804 MonoClass *klass = array->obj.vtable->klass;
805 guint32 size = mono_array_element_size (klass);
806 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
808 const char *field_data;
810 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
811 MonoException *exc = mono_get_exception_argument("array",
812 "Cannot initialize array of non-primitive type.");
813 mono_set_pending_exception (exc);
817 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
818 MonoException *exc = mono_get_exception_argument("field_handle",
819 "Field doesn't have an RVA");
820 mono_set_pending_exception (exc);
824 size *= array->max_length;
825 field_data = mono_field_get_data (field_handle);
827 if (size > mono_type_size (field_handle->type, &align)) {
828 MonoException *exc = mono_get_exception_argument("field_handle",
829 "Field not large enough to fill array");
830 mono_set_pending_exception (exc);
834 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
836 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
837 guint ## n *src = (guint ## n *) field_data; \
839 nEnt = (size / sizeof(guint ## n)); \
841 for (i = 0; i < nEnt; i++) { \
842 data[i] = read ## n (&src[i]); \
846 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
848 switch (type->type) {
865 memcpy (mono_array_addr (array, char, 0), field_data, size);
869 memcpy (mono_array_addr (array, char, 0), field_data, size);
874 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
876 return offsetof (MonoString, chars);
879 ICALL_EXPORT MonoObject *
880 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
882 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
886 MonoObject *ret = mono_object_clone_checked (obj, &error);
887 mono_error_set_pending_exception (&error);
894 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
900 MONO_CHECK_ARG_NULL (handle,);
902 klass = mono_class_from_mono_type (handle);
903 MONO_CHECK_ARG (handle, klass,);
905 if (klass->generic_container)
908 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
909 if (!is_ok (&error)) {
910 mono_error_set_pending_exception (&error);
914 /* This will call the type constructor */
915 if (!mono_runtime_class_init_full (vtable, &error))
916 mono_error_set_pending_exception (&error);
920 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
924 mono_image_check_for_module_cctor (image);
925 if (image->has_module_cctor) {
926 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
927 if (!mono_error_ok (&error)) {
928 mono_error_set_pending_exception (&error);
931 /*It's fine to raise the exception here*/
932 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
933 if (!is_ok (&error)) {
934 mono_error_set_pending_exception (&error);
937 if (!mono_runtime_class_init_full (vtable, &error))
938 mono_error_set_pending_exception (&error);
942 ICALL_EXPORT MonoBoolean
943 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
948 /* later make this configurable and per-arch */
949 int min_size = 4096 * 4 * sizeof (void*);
950 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
951 /* if we have no info we are optimistic and assume there is enough room */
955 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
959 current = (guint8 *)&stack_addr;
960 if (current > stack_addr) {
961 if ((current - stack_addr) < min_size)
964 if (current - (stack_addr - stack_size) < min_size)
970 ICALL_EXPORT MonoObject *
971 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
974 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
975 mono_error_set_pending_exception (&error);
981 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
984 MonoObject **values = NULL;
987 gint32 result = (int)(gsize)mono_defaults.int32_class;
988 MonoClassField* field;
991 klass = mono_object_class (this_obj);
993 if (mono_class_num_fields (klass) == 0)
997 * Compute the starting value of the hashcode for fields of primitive
998 * types, and return the remaining fields in an array to the managed side.
999 * This way, we can avoid costly reflection operations in managed code.
1002 while ((field = mono_class_get_fields (klass, &iter))) {
1003 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1005 if (mono_field_is_deleted (field))
1007 /* FIXME: Add more types */
1008 switch (field->type->type) {
1010 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1012 case MONO_TYPE_STRING: {
1014 s = *(MonoString**)((guint8*)this_obj + field->offset);
1016 result ^= mono_string_hash (s);
1021 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1022 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1023 values [count++] = o;
1029 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1030 for (i = 0; i < count; ++i)
1031 mono_array_setref (*fields, i, values [i]);
1038 ICALL_EXPORT MonoBoolean
1039 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1042 MonoObject **values = NULL;
1044 MonoClassField* field;
1048 MONO_CHECK_ARG_NULL (that, FALSE);
1050 if (this_obj->vtable != that->vtable)
1053 klass = mono_object_class (this_obj);
1055 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1056 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1059 * Do the comparison for fields of primitive type and return a result if
1060 * possible. Otherwise, return the remaining fields in an array to the
1061 * managed side. This way, we can avoid costly reflection operations in
1066 while ((field = mono_class_get_fields (klass, &iter))) {
1067 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1069 if (mono_field_is_deleted (field))
1071 /* FIXME: Add more types */
1072 switch (field->type->type) {
1075 case MONO_TYPE_BOOLEAN:
1076 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1081 case MONO_TYPE_CHAR:
1082 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1087 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1092 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1096 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1100 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1105 case MONO_TYPE_STRING: {
1106 MonoString *s1, *s2;
1107 guint32 s1len, s2len;
1108 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1109 s2 = *(MonoString**)((guint8*)that + field->offset);
1112 if ((s1 == NULL) || (s2 == NULL))
1114 s1len = mono_string_length (s1);
1115 s2len = mono_string_length (s2);
1119 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1125 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1126 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1127 values [count++] = o;
1128 o = mono_field_get_value_object (mono_object_domain (this_obj), field, that);
1129 values [count++] = o;
1132 if (klass->enumtype)
1133 /* enums only have one non-static field */
1139 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1140 for (i = 0; i < count; ++i)
1141 mono_array_setref_fast (*fields, i, values [i]);
1148 ICALL_EXPORT MonoReflectionType *
1149 ves_icall_System_Object_GetType (MonoObject *obj)
1152 MonoReflectionType *ret;
1153 #ifndef DISABLE_REMOTING
1154 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1155 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1158 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1160 mono_error_raise_exception (&error);
1166 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1168 mtype->type = &obj->vtable->klass->byval_arg;
1169 g_assert (mtype->type->type);
1173 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1175 MONO_CHECK_ARG_NULL (obj, 0);
1178 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1179 mono_error_raise_exception (&error);
1184 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1185 MonoReflectionMethod *method,
1186 MonoArray *opt_param_types)
1188 MONO_CHECK_ARG_NULL (method, 0);
1191 gint32 result = mono_image_create_method_token (
1192 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1193 mono_error_raise_exception (&error);
1198 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1201 mono_image_create_pefile (mb, file, &error);
1202 mono_error_raise_exception (&error);
1206 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1209 if (!mono_image_build_metadata (mb, &error))
1210 mono_error_raise_exception (&error);
1214 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1216 mono_image_register_token (mb->dynamic_image, token, obj);
1219 ICALL_EXPORT MonoObject*
1220 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1224 mono_loader_lock ();
1225 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1226 mono_loader_unlock ();
1232 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1234 MonoMethod **dest = (MonoMethod **)data;
1236 /* skip unmanaged frames */
1252 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1254 MonoMethod **dest = (MonoMethod **)data;
1256 /* skip unmanaged frames */
1261 if (!strcmp (m->klass->name_space, "System.Reflection"))
1270 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1272 MonoMethod **dest = (MonoMethod **)data;
1274 /* skip unmanaged frames */
1278 if (m->wrapper_type != MONO_WRAPPER_NONE)
1281 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1295 static MonoReflectionType *
1296 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1298 MonoMethod *m, *dest;
1300 MonoType *type = NULL;
1301 MonoAssembly *assembly = NULL;
1302 gboolean type_resolve = FALSE;
1304 mono_error_init (error);
1307 * We must compute the calling assembly as type loading must happen under a metadata context.
1308 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1309 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1311 m = mono_method_get_last_managed ();
1314 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1319 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1320 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1321 * to crash. This only seems to happen in some strange remoting
1322 * scenarios and I was unable to figure out what's happening there.
1323 * Dec 10, 2005 - Martin.
1327 assembly = dest->klass->image->assembly;
1328 type_resolve = TRUE;
1330 g_warning (G_STRLOC);
1333 if (info->assembly.name)
1334 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1338 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1339 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1342 if (!info->assembly.name && !type) /* try mscorlib */
1343 type = mono_reflection_get_type (NULL, info, ignoreCase, &type_resolve);
1345 if (assembly && !type && type_resolve) {
1346 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1347 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1353 return mono_type_get_object_checked (mono_domain_get (), type, error);
1356 ICALL_EXPORT MonoReflectionType*
1357 ves_icall_type_from_name (MonoString *name,
1358 MonoBoolean throwOnError,
1359 MonoBoolean ignoreCase)
1362 char *str = mono_string_to_utf8 (name);
1363 MonoTypeNameParse info;
1364 MonoReflectionType *type;
1367 parsedOk = mono_reflection_parse_type (str, &info);
1369 /* mono_reflection_parse_type() mangles the string */
1371 mono_reflection_free_type_info (&info);
1374 mono_set_pending_exception (mono_get_exception_argument("typeName", "failed parse"));
1379 type = type_from_parsed_name (&info, ignoreCase, &error);
1381 mono_reflection_free_type_info (&info);
1384 if (!mono_error_ok (&error)) {
1386 mono_error_set_pending_exception (&error);
1388 mono_error_cleanup (&error);
1393 MonoException *e = NULL;
1396 e = mono_get_exception_type_load (name, NULL);
1398 mono_loader_clear_error ();
1400 mono_set_pending_exception (e);
1409 ICALL_EXPORT MonoReflectionType*
1410 ves_icall_type_from_handle (MonoType *handle)
1413 MonoReflectionType *ret;
1414 MonoDomain *domain = mono_domain_get ();
1416 ret = mono_type_get_object_checked (domain, handle, &error);
1417 mono_error_raise_exception (&error);
1422 /* System.TypeCode */
1441 TYPECODE_STRING = 18
1444 ICALL_EXPORT guint32
1445 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1447 int t = type->type->type;
1449 if (type->type->byref)
1450 return TYPECODE_OBJECT;
1454 case MONO_TYPE_VOID:
1455 return TYPECODE_OBJECT;
1456 case MONO_TYPE_BOOLEAN:
1457 return TYPECODE_BOOLEAN;
1459 return TYPECODE_BYTE;
1461 return TYPECODE_SBYTE;
1463 return TYPECODE_UINT16;
1465 return TYPECODE_INT16;
1466 case MONO_TYPE_CHAR:
1467 return TYPECODE_CHAR;
1471 return TYPECODE_OBJECT;
1473 return TYPECODE_UINT32;
1475 return TYPECODE_INT32;
1477 return TYPECODE_UINT64;
1479 return TYPECODE_INT64;
1481 return TYPECODE_SINGLE;
1483 return TYPECODE_DOUBLE;
1484 case MONO_TYPE_VALUETYPE: {
1485 MonoClass *klass = type->type->data.klass;
1487 if (klass->enumtype) {
1488 t = mono_class_enum_basetype (klass)->type;
1490 } else if (mono_is_corlib_image (klass->image)) {
1491 if (strcmp (klass->name_space, "System") == 0) {
1492 if (strcmp (klass->name, "Decimal") == 0)
1493 return TYPECODE_DECIMAL;
1494 else if (strcmp (klass->name, "DateTime") == 0)
1495 return TYPECODE_DATETIME;
1498 return TYPECODE_OBJECT;
1500 case MONO_TYPE_STRING:
1501 return TYPECODE_STRING;
1502 case MONO_TYPE_SZARRAY:
1503 case MONO_TYPE_ARRAY:
1504 case MONO_TYPE_OBJECT:
1506 case MONO_TYPE_MVAR:
1507 case MONO_TYPE_TYPEDBYREF:
1508 return TYPECODE_OBJECT;
1509 case MONO_TYPE_CLASS:
1511 MonoClass *klass = type->type->data.klass;
1512 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1513 if (strcmp (klass->name, "DBNull") == 0)
1514 return TYPECODE_DBNULL;
1517 return TYPECODE_OBJECT;
1518 case MONO_TYPE_GENERICINST:
1519 return TYPECODE_OBJECT;
1521 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1527 mono_type_is_primitive (MonoType *type)
1529 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1530 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1534 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1536 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1537 return mono_class_enum_basetype (type->data.klass);
1538 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1539 return mono_class_enum_basetype (type->data.generic_class->container_class);
1543 ICALL_EXPORT guint32
1544 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1549 g_assert (type != NULL);
1551 klass = mono_class_from_mono_type (type->type);
1552 klassc = mono_class_from_mono_type (c->type);
1554 if (type->type->byref ^ c->type->byref)
1557 if (type->type->byref) {
1558 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1559 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1561 klass = mono_class_from_mono_type (t);
1562 klassc = mono_class_from_mono_type (ot);
1564 if (mono_type_is_primitive (t)) {
1565 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1566 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1567 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1568 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1569 return t->type == ot->type;
1571 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1574 if (klass->valuetype)
1575 return klass == klassc;
1576 return klass->valuetype == klassc->valuetype;
1579 return mono_class_is_assignable_from (klass, klassc);
1582 ICALL_EXPORT guint32
1583 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1585 MonoClass *klass = mono_class_from_mono_type (type->type);
1586 mono_class_init_or_throw (klass);
1587 return mono_object_isinst (obj, klass) != NULL;
1590 ICALL_EXPORT guint32
1591 ves_icall_get_attributes (MonoReflectionType *type)
1593 MonoClass *klass = mono_class_from_mono_type (type->type);
1594 return klass->flags;
1597 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1598 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1601 MonoClass *klass = field->field->parent;
1602 MonoMarshalType *info;
1606 if (klass->generic_container ||
1607 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1610 ftype = mono_field_get_type (field->field);
1611 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1614 info = mono_marshal_load_type_info (klass);
1616 for (i = 0; i < info->num_fields; ++i) {
1617 if (info->fields [i].field == field->field) {
1618 if (!info->fields [i].mspec)
1621 MonoReflectionMarshalAsAttribute* obj;
1622 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1623 if (!mono_error_ok (&error))
1624 mono_error_set_pending_exception (&error);
1633 ICALL_EXPORT MonoReflectionField*
1634 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1637 gboolean found = FALSE;
1644 klass = handle->parent;
1646 klass = mono_class_from_mono_type (type);
1648 /* Check that the field belongs to the class */
1649 for (k = klass; k; k = k->parent) {
1650 if (k == handle->parent) {
1657 /* The managed code will throw the exception */
1661 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1662 mono_error_raise_exception (&error);
1666 ICALL_EXPORT MonoArray*
1667 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1670 MonoType *type = mono_field_get_type_checked (field->field, &error);
1671 if (!mono_error_ok (&error)) {
1672 mono_error_set_pending_exception (&error);
1676 return type_array_from_modifiers (field->field->parent->image, type, optional);
1680 vell_icall_get_method_attributes (MonoMethod *method)
1682 return method->flags;
1686 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1689 MonoReflectionType *rt;
1690 MonoDomain *domain = mono_domain_get ();
1691 MonoMethodSignature* sig;
1693 sig = mono_method_signature_checked (method, &error);
1694 if (!mono_error_ok (&error)) {
1695 mono_error_set_pending_exception (&error);
1699 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1700 if (!mono_error_ok (&error)) {
1701 mono_error_set_pending_exception (&error);
1705 MONO_STRUCT_SETREF (info, parent, rt);
1707 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1708 if (!mono_error_ok (&error)) {
1709 mono_error_set_pending_exception (&error);
1713 MONO_STRUCT_SETREF (info, ret, rt);
1715 info->attrs = method->flags;
1716 info->implattrs = method->iflags;
1717 if (sig->call_convention == MONO_CALL_DEFAULT)
1718 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1720 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1725 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1728 ICALL_EXPORT MonoArray*
1729 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1731 MonoDomain *domain = mono_domain_get ();
1733 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1736 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1737 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1740 MonoDomain *domain = mono_domain_get ();
1741 MonoReflectionMarshalAsAttribute* res = NULL;
1742 MonoMarshalSpec **mspecs;
1745 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1746 mono_method_get_marshal_info (method, mspecs);
1749 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1750 if (!mono_error_ok (&error)) {
1751 mono_error_set_pending_exception (&error);
1756 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1758 mono_metadata_free_marshal_spec (mspecs [i]);
1765 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1767 MonoClass *parent = field->field->parent;
1768 if (!parent->size_inited)
1769 mono_class_init (parent);
1770 mono_class_setup_fields_locking (parent);
1772 return field->field->offset - sizeof (MonoObject);
1775 ICALL_EXPORT MonoReflectionType*
1776 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1779 MonoReflectionType *ret;
1782 parent = declaring? field->field->parent: field->klass;
1784 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1785 mono_error_raise_exception (&error);
1791 ICALL_EXPORT MonoObject *
1792 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1794 MonoClass *fklass = field->klass;
1795 MonoClassField *cf = field->field;
1796 MonoDomain *domain = mono_object_domain (field);
1798 if (fklass->image->assembly->ref_only) {
1799 mono_set_pending_exception (mono_get_exception_invalid_operation (
1800 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1804 if (mono_security_core_clr_enabled ())
1805 mono_security_core_clr_ensure_reflection_access_field (cf);
1807 return mono_field_get_value_object (domain, cf, obj);
1811 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1814 MonoClassField *cf = field->field;
1818 if (field->klass->image->assembly->ref_only) {
1819 mono_set_pending_exception (mono_get_exception_invalid_operation (
1820 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1824 if (mono_security_core_clr_enabled ())
1825 mono_security_core_clr_ensure_reflection_access_field (cf);
1827 type = mono_field_get_type_checked (cf, &error);
1828 if (!mono_error_ok (&error)) {
1829 mono_error_set_pending_exception (&error);
1833 v = (gchar *) value;
1835 switch (type->type) {
1838 case MONO_TYPE_BOOLEAN:
1841 case MONO_TYPE_CHAR:
1850 case MONO_TYPE_VALUETYPE:
1853 v += sizeof (MonoObject);
1855 case MONO_TYPE_STRING:
1856 case MONO_TYPE_OBJECT:
1857 case MONO_TYPE_CLASS:
1858 case MONO_TYPE_ARRAY:
1859 case MONO_TYPE_SZARRAY:
1862 case MONO_TYPE_GENERICINST: {
1863 MonoGenericClass *gclass = type->data.generic_class;
1864 g_assert (!gclass->context.class_inst->is_open);
1866 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1867 MonoClass *nklass = mono_class_from_mono_type (type);
1868 MonoObject *nullable;
1871 * Convert the boxed vtype into a Nullable structure.
1872 * This is complicated by the fact that Nullables have
1873 * a variable structure.
1875 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1876 if (!mono_error_ok (&error)) {
1877 mono_error_set_pending_exception (&error);
1881 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1883 v = (gchar *)mono_object_unbox (nullable);
1886 if (gclass->container_class->valuetype && (v != NULL))
1887 v += sizeof (MonoObject);
1891 g_error ("type 0x%x not handled in "
1892 "ves_icall_FieldInfo_SetValueInternal", type->type);
1897 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1898 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
1899 if (!is_ok (&error)) {
1900 mono_error_set_pending_exception (&error);
1903 if (!vtable->initialized) {
1904 if (!mono_runtime_class_init_full (vtable, &error)) {
1905 mono_error_set_pending_exception (&error);
1909 mono_field_static_set_value (vtable, cf, v);
1911 mono_field_set_value (obj, cf, v);
1916 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1925 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1926 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1930 if (MONO_TYPE_IS_REFERENCE (f->type))
1931 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1933 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1936 ICALL_EXPORT MonoObject *
1937 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1939 MonoObject *o = NULL;
1940 MonoClassField *field = rfield->field;
1942 MonoDomain *domain = mono_object_domain (rfield);
1944 MonoTypeEnum def_type;
1945 const char *def_value;
1949 mono_class_init (field->parent);
1951 t = mono_field_get_type_checked (field, &error);
1952 if (!mono_error_ok (&error)) {
1953 mono_error_set_pending_exception (&error);
1957 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
1958 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1962 if (image_is_dynamic (field->parent->image)) {
1963 MonoClass *klass = field->parent;
1964 int fidx = field - klass->fields;
1966 g_assert (fidx >= 0 && fidx < klass->field.count);
1967 g_assert (klass->ext);
1968 g_assert (klass->ext->field_def_values);
1969 def_type = klass->ext->field_def_values [fidx].def_type;
1970 def_value = klass->ext->field_def_values [fidx].data;
1971 if (def_type == MONO_TYPE_END) {
1972 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1976 def_value = mono_class_get_field_default_value (field, &def_type);
1977 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
1979 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1984 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1988 case MONO_TYPE_BOOLEAN:
1991 case MONO_TYPE_CHAR:
1999 case MONO_TYPE_R8: {
2002 /* boxed value type */
2003 t = g_new0 (MonoType, 1);
2005 klass = mono_class_from_mono_type (t);
2007 o = mono_object_new_checked (domain, klass, &error);
2008 if (!mono_error_ok (&error)) {
2009 mono_error_set_pending_exception (&error);
2012 v = ((gchar *) o) + sizeof (MonoObject);
2013 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2016 case MONO_TYPE_STRING:
2017 case MONO_TYPE_CLASS:
2018 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2021 g_assert_not_reached ();
2027 ICALL_EXPORT MonoReflectionType*
2028 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2031 MonoReflectionType *ret;
2034 type = mono_field_get_type_checked (ref_field->field, &error);
2035 if (!mono_error_ok (&error)) {
2036 mono_error_set_pending_exception (&error);
2040 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2041 if (!mono_error_ok (&error)) {
2042 mono_error_set_pending_exception (&error);
2049 /* From MonoProperty.cs */
2051 PInfo_Attributes = 1,
2052 PInfo_GetMethod = 1 << 1,
2053 PInfo_SetMethod = 1 << 2,
2054 PInfo_ReflectedType = 1 << 3,
2055 PInfo_DeclaringType = 1 << 4,
2060 ves_icall_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2063 MonoReflectionType *rt;
2064 MonoReflectionMethod *rm;
2065 MonoDomain *domain = mono_object_domain (property);
2066 const MonoProperty *pproperty = property->property;
2068 if ((req_info & PInfo_ReflectedType) != 0) {
2069 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2070 mono_error_raise_exception (&error);
2072 MONO_STRUCT_SETREF (info, parent, rt);
2074 if ((req_info & PInfo_DeclaringType) != 0) {
2075 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2076 mono_error_raise_exception (&error);
2078 MONO_STRUCT_SETREF (info, declaring_type, rt);
2081 if ((req_info & PInfo_Name) != 0)
2082 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2084 if ((req_info & PInfo_Attributes) != 0)
2085 info->attrs = pproperty->attrs;
2087 if ((req_info & PInfo_GetMethod) != 0) {
2088 if (pproperty->get &&
2089 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2090 pproperty->get->klass == property->klass)) {
2091 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2092 mono_error_raise_exception (&error);
2097 MONO_STRUCT_SETREF (info, get, rm);
2099 if ((req_info & PInfo_SetMethod) != 0) {
2100 if (pproperty->set &&
2101 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2102 pproperty->set->klass == property->klass)) {
2103 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2104 mono_error_raise_exception (&error);
2109 MONO_STRUCT_SETREF (info, set, rm);
2112 * There may be other methods defined for properties, though, it seems they are not exposed
2113 * in the reflection API
2118 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2121 MonoReflectionType *rt;
2122 MonoReflectionMethod *rm;
2123 MonoDomain *domain = mono_object_domain (event);
2125 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2126 mono_error_raise_exception (&error);
2128 MONO_STRUCT_SETREF (info, reflected_type, rt);
2130 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2131 mono_error_raise_exception (&error);
2133 MONO_STRUCT_SETREF (info, declaring_type, rt);
2135 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2136 info->attrs = event->event->attrs;
2138 if (event->event->add) {
2139 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2140 mono_error_raise_exception (&error);
2145 MONO_STRUCT_SETREF (info, add_method, rm);
2147 if (event->event->remove) {
2148 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2149 mono_error_raise_exception (&error);
2154 MONO_STRUCT_SETREF (info, remove_method, rm);
2156 if (event->event->raise) {
2157 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2158 mono_error_raise_exception (&error);
2163 MONO_STRUCT_SETREF (info, raise_method, rm);
2165 #ifndef MONO_SMALL_CONFIG
2166 if (event->event->other) {
2168 while (event->event->other [n])
2170 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2172 for (i = 0; i < n; i++) {
2173 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2174 mono_error_raise_exception (&error);
2175 mono_array_setref (info->other_methods, i, rm);
2182 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2187 mono_class_setup_interfaces (klass, error);
2188 if (!mono_error_ok (error))
2191 for (i = 0; i < klass->interface_count; i++) {
2192 ic = klass->interfaces [i];
2193 g_hash_table_insert (ifaces, ic, ic);
2195 collect_interfaces (ic, ifaces, error);
2196 if (!mono_error_ok (error))
2202 MonoArray *iface_array;
2203 MonoGenericContext *context;
2207 } FillIfaceArrayData;
2210 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2212 MonoReflectionType *rt;
2213 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2214 MonoClass *ic = (MonoClass *)key;
2215 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2217 if (!mono_error_ok (data->error))
2220 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2221 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2222 if (!mono_error_ok (data->error))
2226 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2227 if (!mono_error_ok (data->error))
2230 mono_array_setref (data->iface_array, data->next_idx++, rt);
2233 mono_metadata_free_type (inflated);
2237 get_interfaces_hash (gconstpointer v1)
2239 MonoClass *k = (MonoClass*)v1;
2241 return k->type_token;
2244 ICALL_EXPORT MonoArray*
2245 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2248 MonoClass *klass = mono_class_from_mono_type (type->type);
2250 FillIfaceArrayData data = { 0 };
2253 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2255 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2256 data.context = mono_class_get_context (klass);
2257 klass = klass->generic_class->container_class;
2260 for (parent = klass; parent; parent = parent->parent) {
2261 mono_class_setup_interfaces (parent, &error);
2262 if (!mono_error_ok (&error))
2264 collect_interfaces (parent, iface_hash, &error);
2265 if (!mono_error_ok (&error))
2269 data.error = &error;
2270 data.domain = mono_object_domain (type);
2272 len = g_hash_table_size (iface_hash);
2274 g_hash_table_destroy (iface_hash);
2275 if (!data.domain->empty_types)
2276 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2277 return data.domain->empty_types;
2280 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2281 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2282 if (!mono_error_ok (&error))
2285 g_hash_table_destroy (iface_hash);
2286 return data.iface_array;
2289 g_hash_table_destroy (iface_hash);
2290 mono_error_set_pending_exception (&error);
2295 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2297 gboolean variance_used;
2298 MonoClass *klass = mono_class_from_mono_type (type->type);
2299 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2300 MonoReflectionMethod *member;
2303 int i = 0, len, ioffset;
2307 mono_class_init_or_throw (klass);
2308 mono_class_init_or_throw (iclass);
2310 mono_class_setup_vtable (klass);
2312 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2316 len = mono_class_num_methods (iclass);
2317 domain = mono_object_domain (type);
2318 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2319 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2321 while ((method = mono_class_get_methods (iclass, &iter))) {
2322 member = mono_method_get_object_checked (domain, method, iclass, &error);
2323 mono_error_raise_exception (&error);
2324 mono_array_setref (*methods, i, member);
2325 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2326 mono_error_raise_exception (&error);
2327 mono_array_setref (*targets, i, member);
2334 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2336 MonoClass *klass = mono_class_from_mono_type (type->type);
2337 mono_class_init_or_throw (klass);
2339 if (image_is_dynamic (klass->image)) {
2340 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2341 *packing = tb->packing_size;
2342 *size = tb->class_size;
2344 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2348 ICALL_EXPORT MonoReflectionType*
2349 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2352 MonoReflectionType *ret;
2355 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2356 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2357 mono_error_raise_exception (&error);
2362 klass = mono_class_from_mono_type (type->type);
2363 mono_class_init_or_throw (klass);
2365 // GetElementType should only return a type for:
2366 // Array Pointer PassedByRef
2367 if (type->type->byref)
2368 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2369 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2370 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2371 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2372 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2376 mono_error_raise_exception (&error);
2381 ICALL_EXPORT MonoReflectionType*
2382 ves_icall_get_type_parent (MonoReflectionType *type)
2385 MonoReflectionType *ret;
2387 if (type->type->byref)
2390 MonoClass *klass = mono_class_from_mono_type (type->type);
2394 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2395 mono_error_raise_exception (&error);
2400 ICALL_EXPORT MonoBoolean
2401 ves_icall_type_ispointer (MonoReflectionType *type)
2403 return type->type->type == MONO_TYPE_PTR;
2406 ICALL_EXPORT MonoBoolean
2407 ves_icall_type_isprimitive (MonoReflectionType *type)
2409 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)));
2412 ICALL_EXPORT MonoBoolean
2413 ves_icall_type_isbyref (MonoReflectionType *type)
2415 return type->type->byref;
2418 ICALL_EXPORT MonoBoolean
2419 ves_icall_type_iscomobject (MonoReflectionType *type)
2421 MonoClass *klass = mono_class_from_mono_type (type->type);
2422 mono_class_init_or_throw (klass);
2424 return mono_class_is_com_object (klass);
2427 ICALL_EXPORT MonoReflectionModule*
2428 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2431 MonoReflectionModule *result = NULL;
2432 MonoClass *klass = mono_class_from_mono_type (type->type);
2433 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2434 if (!mono_error_ok (&error))
2435 mono_error_set_pending_exception (&error);
2439 ICALL_EXPORT MonoReflectionAssembly*
2440 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2443 MonoDomain *domain = mono_domain_get ();
2444 MonoClass *klass = mono_class_from_mono_type (type->type);
2445 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2447 mono_error_set_pending_exception (&error);
2451 ICALL_EXPORT MonoReflectionType*
2452 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2455 MonoReflectionType *ret;
2456 MonoDomain *domain = mono_domain_get ();
2459 if (type->type->byref)
2461 if (type->type->type == MONO_TYPE_VAR) {
2462 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2463 klass = param ? param->owner.klass : NULL;
2464 } else if (type->type->type == MONO_TYPE_MVAR) {
2465 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2466 klass = param ? param->owner.method->klass : NULL;
2468 klass = mono_class_from_mono_type (type->type)->nested_in;
2474 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2475 mono_error_raise_exception (&error);
2480 ICALL_EXPORT MonoString*
2481 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2483 MonoDomain *domain = mono_domain_get ();
2484 MonoClass *klass = mono_class_from_mono_type (type->type);
2486 if (type->type->byref) {
2487 char *n = g_strdup_printf ("%s&", klass->name);
2488 MonoString *res = mono_string_new (domain, n);
2494 return mono_string_new (domain, klass->name);
2498 ICALL_EXPORT MonoString*
2499 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2501 MonoDomain *domain = mono_domain_get ();
2502 MonoClass *klass = mono_class_from_mono_type (type->type);
2504 while (klass->nested_in)
2505 klass = klass->nested_in;
2507 if (klass->name_space [0] == '\0')
2510 return mono_string_new (domain, klass->name_space);
2514 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2518 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2519 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2523 klass = mono_class_from_mono_type (type->type);
2529 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2532 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2536 ICALL_EXPORT MonoArray*
2537 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2540 MonoReflectionType *rt;
2542 MonoClass *klass, *pklass;
2543 MonoDomain *domain = mono_object_domain (type);
2546 klass = mono_class_from_mono_type (type->type);
2548 if (klass->generic_container) {
2549 MonoGenericContainer *container = klass->generic_container;
2550 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2551 for (i = 0; i < container->type_argc; ++i) {
2552 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2554 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2555 mono_error_raise_exception (&error);
2557 mono_array_setref (res, i, rt);
2559 } else if (klass->generic_class) {
2560 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2561 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2562 for (i = 0; i < inst->type_argc; ++i) {
2563 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2564 mono_error_raise_exception (&error);
2566 mono_array_setref (res, i, rt);
2574 ICALL_EXPORT gboolean
2575 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2579 if (!IS_MONOTYPE (type))
2582 if (type->type->byref)
2585 klass = mono_class_from_mono_type (type->type);
2586 return klass->generic_container != NULL;
2589 ICALL_EXPORT MonoReflectionType*
2590 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2593 MonoReflectionType *ret;
2596 if (type->type->byref)
2599 klass = mono_class_from_mono_type (type->type);
2601 if (klass->generic_container) {
2602 return type; /* check this one */
2604 if (klass->generic_class) {
2605 MonoClass *generic_class = klass->generic_class->container_class;
2608 tb = mono_class_get_ref_info (generic_class);
2610 if (generic_class->wastypebuilder && tb)
2611 return (MonoReflectionType *)tb;
2613 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2614 mono_error_raise_exception (&error);
2622 ICALL_EXPORT MonoReflectionType*
2623 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2626 MonoReflectionType *ret;
2628 MonoType *geninst, **types;
2631 g_assert (IS_MONOTYPE (type));
2632 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2634 count = mono_array_length (type_array);
2635 types = g_new0 (MonoType *, count);
2637 for (i = 0; i < count; i++) {
2638 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2639 types [i] = t->type;
2642 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2647 klass = mono_class_from_mono_type (geninst);
2649 /*we might inflate to the GTD*/
2650 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2651 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2655 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2656 mono_error_raise_exception (&error);
2661 ICALL_EXPORT gboolean
2662 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2666 if (!IS_MONOTYPE (type))
2669 if (type->type->byref)
2672 klass = mono_class_from_mono_type (type->type);
2673 return klass->generic_class != NULL || klass->generic_container != NULL;
2677 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2679 if (!IS_MONOTYPE (type))
2682 if (is_generic_parameter (type->type))
2683 return mono_type_get_generic_param_num (type->type);
2687 ICALL_EXPORT GenericParameterAttributes
2688 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2690 g_assert (IS_MONOTYPE (type));
2691 g_assert (is_generic_parameter (type->type));
2692 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2695 ICALL_EXPORT MonoArray *
2696 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2699 MonoReflectionType *rt;
2700 MonoGenericParamInfo *param_info;
2706 g_assert (IS_MONOTYPE (type));
2708 domain = mono_object_domain (type);
2709 param_info = mono_generic_param_info (type->type->data.generic_param);
2710 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2713 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2714 for (i = 0; i < count; i++) {
2715 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2716 mono_error_raise_exception (&error);
2718 mono_array_setref (res, i, rt);
2725 ICALL_EXPORT MonoBoolean
2726 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2728 return is_generic_parameter (type->type);
2731 ICALL_EXPORT MonoBoolean
2732 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2734 return is_generic_parameter (tb->type.type);
2738 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2739 MonoReflectionType *t)
2741 enumtype->type = t->type;
2744 ICALL_EXPORT MonoReflectionMethod*
2745 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2746 MonoReflectionMethod* generic)
2753 MonoReflectionMethod *ret = NULL;
2755 domain = ((MonoObject *)type)->vtable->domain;
2757 klass = mono_class_from_mono_type (type->type);
2758 mono_class_init_or_throw (klass);
2761 while ((method = mono_class_get_methods (klass, &iter))) {
2762 if (method->token == generic->method->token) {
2763 ret = mono_method_get_object_checked (domain, method, klass, &error);
2764 mono_error_raise_exception (&error);
2771 ICALL_EXPORT MonoReflectionMethod *
2772 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2775 MonoType *type = ref_type->type;
2777 MonoReflectionMethod *ret = NULL;
2779 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2780 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2783 if (type->type == MONO_TYPE_VAR)
2786 method = mono_type_get_generic_param_owner (type)->owner.method;
2789 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2790 if (!mono_error_ok (&error))
2791 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2795 ICALL_EXPORT MonoBoolean
2796 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2798 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2802 ICALL_EXPORT MonoBoolean
2803 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2805 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2810 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2812 MonoDomain *domain = mono_domain_get ();
2813 MonoImage *image = method->method->klass->image;
2814 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2815 MonoTableInfo *tables = image->tables;
2816 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2817 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2818 guint32 im_cols [MONO_IMPLMAP_SIZE];
2819 guint32 scope_token;
2820 const char *import = NULL;
2821 const char *scope = NULL;
2823 if (image_is_dynamic (image)) {
2824 MonoReflectionMethodAux *method_aux =
2825 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2827 import = method_aux->dllentry;
2828 scope = method_aux->dll;
2831 if (!import || !scope) {
2832 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2837 if (piinfo->implmap_idx) {
2838 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2840 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2841 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2842 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2843 scope = mono_metadata_string_heap (image, scope_token);
2847 *flags = piinfo->piflags;
2848 *entry_point = mono_string_new (domain, import);
2849 *dll_name = mono_string_new (domain, scope);
2852 ICALL_EXPORT MonoReflectionMethod *
2853 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2855 MonoMethodInflated *imethod;
2857 MonoReflectionMethod *ret = NULL;
2860 if (method->method->is_generic)
2863 if (!method->method->is_inflated)
2866 imethod = (MonoMethodInflated *) method->method;
2868 result = imethod->declaring;
2869 /* Not a generic method. */
2870 if (!result->is_generic)
2873 if (image_is_dynamic (method->method->klass->image)) {
2874 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2875 MonoReflectionMethod *res;
2878 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2879 * the dynamic case as well ?
2881 mono_image_lock ((MonoImage*)image);
2882 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2883 mono_image_unlock ((MonoImage*)image);
2889 if (imethod->context.class_inst) {
2890 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2891 /*Generic methods gets the context of the GTD.*/
2892 if (mono_class_get_context (klass)) {
2893 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2894 if (!mono_error_ok (&error))
2899 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2901 if (!mono_error_ok (&error))
2902 mono_error_set_pending_exception (&error);
2906 ICALL_EXPORT gboolean
2907 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2909 return mono_method_signature (method->method)->generic_param_count != 0;
2912 ICALL_EXPORT gboolean
2913 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2915 return method->method->is_generic;
2918 ICALL_EXPORT MonoArray*
2919 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2922 MonoReflectionType *rt;
2927 domain = mono_object_domain (method);
2929 if (method->method->is_inflated) {
2930 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2933 count = inst->type_argc;
2934 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2936 for (i = 0; i < count; i++) {
2937 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2938 mono_error_raise_exception (&error);
2940 mono_array_setref (res, i, rt);
2947 count = mono_method_signature (method->method)->generic_param_count;
2948 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2950 for (i = 0; i < count; i++) {
2951 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2952 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2953 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
2955 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2956 mono_error_raise_exception (&error);
2958 mono_array_setref (res, i, rt);
2964 ICALL_EXPORT MonoObject *
2965 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
2969 * Invoke from reflection is supposed to always be a virtual call (the API
2970 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2971 * greater flexibility.
2973 MonoMethod *m = method->method;
2974 MonoMethodSignature *sig = mono_method_signature (m);
2977 void *obj = this_arg;
2981 if (mono_security_core_clr_enabled ())
2982 mono_security_core_clr_ensure_reflection_access_method (m);
2984 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2985 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
2986 mono_error_cleanup (&error); /* FIXME does this make sense? */
2987 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2992 if (!mono_object_isinst (this_arg, m->klass)) {
2993 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
2994 char *target_name = mono_type_get_full_name (m->klass);
2995 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2996 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2998 g_free (target_name);
3002 m = mono_object_get_virtual_method (this_arg, m);
3003 /* must pass the pointer to the value for valuetype methods */
3004 if (m->klass->valuetype)
3005 obj = mono_object_unbox (this_arg);
3006 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3007 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3012 if (sig->ret->byref) {
3013 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"));
3017 pcount = params? mono_array_length (params): 0;
3018 if (pcount != sig->param_count) {
3019 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3023 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3024 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."));
3028 image = m->klass->image;
3029 if (image->assembly->ref_only) {
3030 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."));
3034 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3035 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3039 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3043 intptr_t *lower_bounds;
3044 pcount = mono_array_length (params);
3045 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3046 /* Note: the synthetized array .ctors have int32 as argument type */
3047 for (i = 0; i < pcount; ++i)
3048 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3050 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3051 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3052 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3053 if (!mono_error_ok (&error)) {
3054 mono_error_set_pending_exception (&error);
3058 for (i = 0; i < mono_array_length (arr); ++i) {
3059 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3060 if (!mono_error_ok (&error)) {
3061 mono_error_set_pending_exception (&error);
3064 mono_array_setref_fast (arr, i, subarray);
3066 return (MonoObject*)arr;
3069 if (m->klass->rank == pcount) {
3070 /* Only lengths provided. */
3071 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3072 if (!mono_error_ok (&error)) {
3073 mono_error_set_pending_exception (&error);
3077 return (MonoObject*)arr;
3079 g_assert (pcount == (m->klass->rank * 2));
3080 /* The arguments are lower-bound-length pairs */
3081 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3083 for (i = 0; i < pcount / 2; ++i) {
3084 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3085 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3088 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3089 if (!mono_error_ok (&error)) {
3090 mono_error_set_pending_exception (&error);
3094 return (MonoObject*)arr;
3097 return mono_runtime_invoke_array (m, obj, params, NULL);
3100 #ifndef DISABLE_REMOTING
3101 ICALL_EXPORT MonoObject *
3102 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3104 MonoDomain *domain = mono_object_domain (method);
3105 MonoMethod *m = method->method;
3106 MonoMethodSignature *sig = mono_method_signature (m);
3107 MonoArray *out_args;
3109 int i, j, outarg_count = 0;
3111 if (m->klass == mono_defaults.object_class) {
3112 if (!strcmp (m->name, "FieldGetter")) {
3113 MonoClass *k = this_arg->vtable->klass;
3117 /* If this is a proxy, then it must be a CBO */
3118 if (k == mono_defaults.transparent_proxy_class) {
3119 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3120 this_arg = tp->rp->unwrapped_server;
3121 g_assert (this_arg);
3122 k = this_arg->vtable->klass;
3125 name = mono_array_get (params, MonoString *, 1);
3126 str = mono_string_to_utf8 (name);
3129 MonoClassField* field = mono_class_get_field_from_name (k, str);
3131 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3132 if (field_klass->valuetype)
3133 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
3135 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3137 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3138 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3139 mono_array_setref (out_args, 0, result);
3147 g_assert_not_reached ();
3149 } else if (!strcmp (m->name, "FieldSetter")) {
3150 MonoClass *k = this_arg->vtable->klass;
3156 /* If this is a proxy, then it must be a CBO */
3157 if (k == mono_defaults.transparent_proxy_class) {
3158 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3159 this_arg = tp->rp->unwrapped_server;
3160 g_assert (this_arg);
3161 k = this_arg->vtable->klass;
3164 name = mono_array_get (params, MonoString *, 1);
3165 str = mono_string_to_utf8 (name);
3168 MonoClassField* field = mono_class_get_field_from_name (k, str);
3170 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3171 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3173 if (field_klass->valuetype) {
3174 size = mono_type_size (field->type, &align);
3175 g_assert (size == mono_class_value_size (field_klass, NULL));
3176 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3178 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3181 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3182 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3192 g_assert_not_reached ();
3197 for (i = 0; i < mono_array_length (params); i++) {
3198 if (sig->params [i]->byref)
3202 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3204 /* handle constructors only for objects already allocated */
3205 if (!strcmp (method->method->name, ".ctor"))
3206 g_assert (this_arg);
3208 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3209 g_assert (!method->method->klass->valuetype);
3210 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3212 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3213 if (sig->params [i]->byref) {
3215 arg = mono_array_get (params, gpointer, i);
3216 mono_array_setref (out_args, j, arg);
3221 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3228 read_enum_value (const char *mem, int type)
3231 case MONO_TYPE_BOOLEAN:
3233 return *(guint8*)mem;
3235 return *(gint8*)mem;
3236 case MONO_TYPE_CHAR:
3238 return read16 (mem);
3240 return (gint16) read16 (mem);
3242 return read32 (mem);
3244 return (gint32) read32 (mem);
3247 return read64 (mem);
3249 g_assert_not_reached ();
3255 write_enum_value (char *mem, int type, guint64 value)
3259 case MONO_TYPE_I1: {
3260 guint8 *p = (guint8*)mem;
3265 case MONO_TYPE_I2: {
3266 guint16 *p = (guint16 *)mem;
3271 case MONO_TYPE_I4: {
3272 guint32 *p = (guint32 *)mem;
3277 case MONO_TYPE_I8: {
3278 guint64 *p = (guint64 *)mem;
3283 g_assert_not_reached ();
3288 ICALL_EXPORT MonoObject *
3289 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3297 domain = mono_object_domain (enumType);
3298 enumc = mono_class_from_mono_type (enumType->type);
3300 mono_class_init_or_throw (enumc);
3302 etype = mono_class_enum_basetype (enumc);
3304 res = mono_object_new_checked (domain, enumc, &error);
3305 mono_error_raise_exception (&error);
3306 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3311 ICALL_EXPORT MonoBoolean
3312 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3314 int size = mono_class_value_size (a->vtable->klass, NULL);
3315 guint64 a_val = 0, b_val = 0;
3317 memcpy (&a_val, mono_object_unbox (a), size);
3318 memcpy (&b_val, mono_object_unbox (b), size);
3320 return (a_val & b_val) == b_val;
3323 ICALL_EXPORT MonoObject *
3324 ves_icall_System_Enum_get_value (MonoObject *eobj)
3336 g_assert (eobj->vtable->klass->enumtype);
3338 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3339 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3340 mono_error_raise_exception (&error);
3341 dst = (char *)res + sizeof (MonoObject);
3342 src = (char *)eobj + sizeof (MonoObject);
3343 size = mono_class_value_size (enumc, NULL);
3345 memcpy (dst, src, size);
3350 ICALL_EXPORT MonoReflectionType *
3351 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3354 MonoReflectionType *ret;
3358 klass = mono_class_from_mono_type (type->type);
3359 mono_class_init_or_throw (klass);
3361 etype = mono_class_enum_basetype (klass);
3363 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3367 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3368 mono_error_raise_exception (&error);
3374 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3376 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3377 gpointer odata = (char *)other + sizeof (MonoObject);
3378 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3379 g_assert (basetype);
3384 if (eobj->vtable->klass != other->vtable->klass)
3387 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3388 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3389 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3392 return me > other ? 1 : -1; \
3395 switch (basetype->type) {
3397 COMPARE_ENUM_VALUES (guint8);
3399 COMPARE_ENUM_VALUES (gint8);
3400 case MONO_TYPE_CHAR:
3402 COMPARE_ENUM_VALUES (guint16);
3404 COMPARE_ENUM_VALUES (gint16);
3406 COMPARE_ENUM_VALUES (guint32);
3408 COMPARE_ENUM_VALUES (gint32);
3410 COMPARE_ENUM_VALUES (guint64);
3412 COMPARE_ENUM_VALUES (gint64);
3416 #undef COMPARE_ENUM_VALUES
3417 /* indicates that the enum was of an unsupported unerlying type */
3422 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3424 gpointer data = (char *)eobj + sizeof (MonoObject);
3425 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3426 g_assert (basetype);
3428 switch (basetype->type) {
3429 case MONO_TYPE_I1: {
3430 gint8 value = *((gint8*)data);
3431 return ((int)value ^ (int)value << 8);
3434 return *((guint8*)data);
3435 case MONO_TYPE_CHAR:
3437 return *((guint16*)data);
3439 case MONO_TYPE_I2: {
3440 gint16 value = *((gint16*)data);
3441 return ((int)(guint16)value | (((int)value) << 16));
3444 return *((guint32*)data);
3446 return *((gint32*)data);
3448 case MONO_TYPE_I8: {
3449 gint64 value = *((gint64*)data);
3450 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3453 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3458 ICALL_EXPORT MonoBoolean
3459 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3461 MonoDomain *domain = mono_object_domain (type);
3462 MonoClass *enumc = mono_class_from_mono_type (type->type);
3463 guint j = 0, nvalues;
3465 MonoClassField *field;
3467 guint64 field_value, previous_value = 0;
3468 gboolean sorted = TRUE;
3470 mono_class_init_or_throw (enumc);
3472 if (!enumc->enumtype) {
3473 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3477 base_type = mono_class_enum_basetype (enumc)->type;
3479 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3480 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3481 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3484 while ((field = mono_class_get_fields (enumc, &iter))) {
3486 MonoTypeEnum def_type;
3488 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3490 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3492 if (mono_field_is_deleted (field))
3494 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3496 p = mono_class_get_field_default_value (field, &def_type);
3497 /* len = */ mono_metadata_decode_blob_size (p, &p);
3499 field_value = read_enum_value (p, base_type);
3500 mono_array_set (*values, guint64, j, field_value);
3502 if (previous_value > field_value)
3505 previous_value = field_value;
3513 BFLAGS_IgnoreCase = 1,
3514 BFLAGS_DeclaredOnly = 2,
3515 BFLAGS_Instance = 4,
3517 BFLAGS_Public = 0x10,
3518 BFLAGS_NonPublic = 0x20,
3519 BFLAGS_FlattenHierarchy = 0x40,
3520 BFLAGS_InvokeMethod = 0x100,
3521 BFLAGS_CreateInstance = 0x200,
3522 BFLAGS_GetField = 0x400,
3523 BFLAGS_SetField = 0x800,
3524 BFLAGS_GetProperty = 0x1000,
3525 BFLAGS_SetProperty = 0x2000,
3526 BFLAGS_ExactBinding = 0x10000,
3527 BFLAGS_SuppressChangeType = 0x20000,
3528 BFLAGS_OptionalParamBinding = 0x40000
3531 ICALL_EXPORT MonoArray*
3532 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3536 MonoClass *startklass, *klass, *refklass;
3541 char *utf8_name = NULL;
3542 int (*compare_func) (const char *s1, const char *s2) = NULL;
3543 MonoClassField *field;
3544 MonoPtrArray tmp_array;
3546 domain = ((MonoObject *)type)->vtable->domain;
3547 if (type->type->byref)
3548 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3550 klass = startklass = mono_class_from_mono_type (type->type);
3551 refklass = mono_class_from_mono_type (reftype->type);
3553 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3556 if (mono_class_has_failure (klass)) {
3557 mono_ptr_array_destroy (tmp_array);
3558 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3563 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3564 guint32 flags = mono_field_get_flags (field);
3566 if (mono_field_is_deleted_with_flags (field, flags))
3568 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3569 if (bflags & BFLAGS_Public)
3571 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3572 if (bflags & BFLAGS_NonPublic) {
3579 if (flags & FIELD_ATTRIBUTE_STATIC) {
3580 if (bflags & BFLAGS_Static)
3581 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3584 if (bflags & BFLAGS_Instance)
3592 if (utf8_name == NULL) {
3593 utf8_name = mono_string_to_utf8 (name);
3594 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3597 if (compare_func (mono_field_get_name (field), utf8_name))
3601 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3602 if (!mono_error_ok (&error))
3604 mono_ptr_array_append (tmp_array, member);
3606 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3609 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3611 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3612 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3614 mono_ptr_array_destroy (tmp_array);
3616 if (utf8_name != NULL)
3621 mono_ptr_array_destroy (tmp_array);
3622 mono_error_raise_exception (&error);
3623 g_assert_not_reached ();
3627 method_nonpublic (MonoMethod* method, gboolean start_klass)
3629 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3630 case METHOD_ATTRIBUTE_ASSEM:
3631 return (start_klass || mono_defaults.generic_ilist_class);
3632 case METHOD_ATTRIBUTE_PRIVATE:
3634 case METHOD_ATTRIBUTE_PUBLIC:
3642 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3645 MonoClass *startklass;
3649 /*FIXME, use MonoBitSet*/
3650 guint32 method_slots_default [8];
3651 guint32 *method_slots = NULL;
3652 int (*compare_func) (const char *s1, const char *s2) = NULL;
3654 array = g_ptr_array_new ();
3659 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3661 /* An optimization for calls made from Delegate:CreateDelegate () */
3662 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3663 method = mono_get_delegate_invoke (klass);
3664 if (mono_loader_get_last_error ())
3667 g_ptr_array_add (array, method);
3671 mono_class_setup_methods (klass);
3672 mono_class_setup_vtable (klass);
3673 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3676 if (is_generic_parameter (&klass->byval_arg))
3677 nslots = mono_class_get_vtable_size (klass->parent);
3679 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3680 if (nslots >= sizeof (method_slots_default) * 8) {
3681 method_slots = g_new0 (guint32, nslots / 32 + 1);
3683 method_slots = method_slots_default;
3684 memset (method_slots, 0, sizeof (method_slots_default));
3687 mono_class_setup_methods (klass);
3688 mono_class_setup_vtable (klass);
3689 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3693 while ((method = mono_class_get_methods (klass, &iter))) {
3695 if (method->slot != -1) {
3696 g_assert (method->slot < nslots);
3697 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3699 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3700 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3703 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3705 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3706 if (bflags & BFLAGS_Public)
3708 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3714 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3715 if (bflags & BFLAGS_Static)
3716 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3719 if (bflags & BFLAGS_Instance)
3727 if (compare_func (name, method->name))
3732 g_ptr_array_add (array, method);
3734 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3736 if (method_slots != method_slots_default)
3737 g_free (method_slots);
3742 if (method_slots != method_slots_default)
3743 g_free (method_slots);
3744 g_ptr_array_free (array, TRUE);
3746 if (mono_class_has_failure (klass)) {
3747 *ex = mono_class_get_exception_for_failure (klass);
3749 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3750 mono_loader_clear_error ();
3755 ICALL_EXPORT MonoArray*
3756 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3758 static MonoClass *MethodInfo_array;
3762 MonoVTable *array_vtable;
3763 MonoException *ex = NULL;
3764 const char *mname = NULL;
3765 GPtrArray *method_array;
3766 MonoClass *klass, *refklass;
3769 mono_error_init (&error);
3771 if (!MethodInfo_array) {
3772 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3773 mono_memory_barrier ();
3774 MethodInfo_array = klass;
3777 klass = mono_class_from_mono_type (type->type);
3778 refklass = mono_class_from_mono_type (reftype->type);
3779 domain = ((MonoObject *)type)->vtable->domain;
3780 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3781 if (!is_ok (&error)) {
3782 mono_error_set_pending_exception (&error);
3785 if (type->type->byref) {
3786 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3787 mono_error_set_pending_exception (&error);
3793 mname = mono_string_to_utf8 (name);
3795 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3796 g_free ((char*)mname);
3798 mono_set_pending_exception (ex);
3802 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3803 if (!mono_error_ok (&error)) {
3804 mono_error_set_pending_exception (&error);
3808 for (i = 0; i < method_array->len; ++i) {
3809 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3810 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3811 if (!mono_error_ok (&error))
3813 mono_array_setref (res, i, rm);
3817 g_ptr_array_free (method_array, TRUE);
3818 if (!mono_error_ok (&error))
3819 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3823 ICALL_EXPORT MonoArray*
3824 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3827 MonoClass *startklass, *klass, *refklass;
3832 gpointer iter = NULL;
3833 MonoPtrArray tmp_array;
3836 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3838 domain = ((MonoObject *)type)->vtable->domain;
3839 if (type->type->byref)
3840 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3841 klass = startklass = mono_class_from_mono_type (type->type);
3842 refklass = mono_class_from_mono_type (reftype->type);
3844 mono_class_setup_methods (klass);
3845 if (mono_class_has_failure (klass)) {
3846 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3851 while ((method = mono_class_get_methods (klass, &iter))) {
3853 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3855 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3856 if (bflags & BFLAGS_Public)
3859 if (bflags & BFLAGS_NonPublic)
3865 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3866 if (bflags & BFLAGS_Static)
3867 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3870 if (bflags & BFLAGS_Instance)
3876 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3877 if (!mono_error_ok (&error)) {
3878 mono_error_set_pending_exception (&error);
3882 mono_ptr_array_append (tmp_array, member);
3885 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
3887 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3888 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3890 mono_ptr_array_destroy (tmp_array);
3896 property_hash (gconstpointer data)
3898 MonoProperty *prop = (MonoProperty*)data;
3900 return g_str_hash (prop->name);
3904 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3906 if (method1->is_inflated)
3907 method1 = ((MonoMethodInflated*) method1)->declaring;
3908 if (method2->is_inflated)
3909 method2 = ((MonoMethodInflated*) method2)->declaring;
3911 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3915 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3917 // Properties are hide-by-name-and-signature
3918 if (!g_str_equal (prop1->name, prop2->name))
3921 /* If we see a property in a generic method, we want to
3922 compare the generic signatures, not the inflated signatures
3923 because we might conflate two properties that were
3927 public T this[T t] { getter { return t; } } // method 1
3928 public U this[U u] { getter { return u; } } // method 2
3931 If we see int Foo<int,int>::Item[int] we need to know if
3932 the indexer came from method 1 or from method 2, and we
3933 shouldn't conflate them. (Bugzilla 36283)
3935 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
3938 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
3945 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3950 return method_nonpublic (accessor, start_klass);
3953 ICALL_EXPORT MonoArray*
3954 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3958 MonoClass *startklass, *klass;
3964 gchar *propname = NULL;
3965 int (*compare_func) (const char *s1, const char *s2) = NULL;
3967 GHashTable *properties = NULL;
3968 MonoPtrArray tmp_array;
3970 mono_error_init (&error);
3972 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
3974 domain = ((MonoObject *)type)->vtable->domain;
3975 if (type->type->byref)
3976 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
3977 klass = startklass = mono_class_from_mono_type (type->type);
3980 propname = mono_string_to_utf8 (name);
3981 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3984 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3986 mono_class_setup_methods (klass);
3987 mono_class_setup_vtable (klass);
3988 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3992 while ((prop = mono_class_get_properties (klass, &iter))) {
3998 flags = method->flags;
4001 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4002 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4003 if (bflags & BFLAGS_Public)
4005 } else if (bflags & BFLAGS_NonPublic) {
4006 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4007 property_accessor_nonpublic(prop->set, startklass == klass)) {
4014 if (flags & METHOD_ATTRIBUTE_STATIC) {
4015 if (bflags & BFLAGS_Static)
4016 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4019 if (bflags & BFLAGS_Instance)
4028 if (compare_func (propname, prop->name))
4032 if (g_hash_table_lookup (properties, prop))
4035 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4038 mono_ptr_array_append (tmp_array, pr);
4040 g_hash_table_insert (properties, prop, prop);
4042 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4045 g_hash_table_destroy (properties);
4048 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4049 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4050 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4052 mono_ptr_array_destroy (tmp_array);
4059 if (mono_class_has_failure (klass)) {
4060 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4062 mono_error_set_from_loader_error (&error);
4063 mono_loader_clear_error ();
4068 g_hash_table_destroy (properties);
4071 mono_ptr_array_destroy (tmp_array);
4073 mono_error_set_pending_exception (&error);
4079 event_hash (gconstpointer data)
4081 MonoEvent *event = (MonoEvent*)data;
4083 return g_str_hash (event->name);
4087 event_equal (MonoEvent *event1, MonoEvent *event2)
4089 // Events are hide-by-name
4090 return g_str_equal (event1->name, event2->name);
4093 ICALL_EXPORT MonoArray*
4094 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4098 MonoClass *startklass, *klass;
4104 char *utf8_name = NULL;
4105 int (*compare_func) (const char *s1, const char *s2) = NULL;
4106 GHashTable *events = NULL;
4107 MonoPtrArray tmp_array;
4109 mono_error_init (&error);
4111 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4113 domain = mono_object_domain (type);
4114 if (type->type->byref)
4115 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4116 klass = startklass = mono_class_from_mono_type (type->type);
4118 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4120 mono_class_setup_methods (klass);
4121 mono_class_setup_vtable (klass);
4122 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4126 while ((event = mono_class_get_events (klass, &iter))) {
4128 method = event->add;
4130 method = event->remove;
4132 method = event->raise;
4134 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4135 if (bflags & BFLAGS_Public)
4137 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4138 if (bflags & BFLAGS_NonPublic)
4143 if (bflags & BFLAGS_NonPublic)
4149 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4150 if (bflags & BFLAGS_Static)
4151 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4154 if (bflags & BFLAGS_Instance)
4159 if (bflags & BFLAGS_Instance)
4165 if (utf8_name == NULL) {
4166 utf8_name = mono_string_to_utf8 (name);
4167 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4170 if (compare_func (event->name, utf8_name))
4174 if (g_hash_table_lookup (events, event))
4177 MonoReflectionEvent *ev_obj;
4178 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4181 mono_ptr_array_append (tmp_array, ev_obj);
4183 g_hash_table_insert (events, event, event);
4185 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4188 g_hash_table_destroy (events);
4190 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4192 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4193 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4195 mono_ptr_array_destroy (tmp_array);
4197 if (utf8_name != NULL)
4203 if (mono_class_has_failure (klass)) {
4204 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4206 mono_error_set_from_loader_error (&error);
4207 mono_loader_clear_error ();
4213 g_hash_table_destroy (events);
4214 if (utf8_name != NULL)
4217 mono_ptr_array_destroy (tmp_array);
4219 mono_error_set_pending_exception (&error);
4223 ICALL_EXPORT MonoArray*
4224 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4227 MonoReflectionType *rt;
4235 MonoPtrArray tmp_array;
4237 domain = ((MonoObject *)type)->vtable->domain;
4238 if (type->type->byref)
4239 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4240 klass = mono_class_from_mono_type (type->type);
4243 * If a nested type is generic, return its generic type definition.
4244 * Note that this means that the return value is essentially the set
4245 * of nested types of the generic type definition of @klass.
4247 * A note in MSDN claims that a generic type definition can have
4248 * nested types that aren't generic. In any case, the container of that
4249 * nested type would be the generic type definition.
4251 if (klass->generic_class)
4252 klass = klass->generic_class->container_class;
4254 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4256 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4258 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4259 if (bflags & BFLAGS_Public)
4262 if (bflags & BFLAGS_NonPublic)
4270 str = mono_string_to_utf8 (name);
4271 mono_identifier_unescape_type_name_chars (str);
4274 if (strcmp (nested->name, str))
4278 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4279 mono_error_raise_exception (&error);
4281 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4284 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4286 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4287 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4289 mono_ptr_array_destroy (tmp_array);
4297 ICALL_EXPORT MonoReflectionType*
4298 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4301 MonoReflectionType *ret;
4303 MonoType *type = NULL;
4304 MonoTypeNameParse info;
4305 gboolean type_resolve;
4307 /* On MS.NET, this does not fire a TypeResolve event */
4308 type_resolve = TRUE;
4309 str = mono_string_to_utf8 (name);
4310 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4311 if (!mono_reflection_parse_type (str, &info)) {
4313 mono_reflection_free_type_info (&info);
4315 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4318 /*g_print ("failed parse\n");*/
4322 if (info.assembly.name) {
4324 mono_reflection_free_type_info (&info);
4326 /* 1.0 and 2.0 throw different exceptions */
4327 if (mono_defaults.generic_ilist_class)
4328 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4330 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4336 if (module != NULL) {
4338 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4343 if (assembly_is_dynamic (assembly->assembly)) {
4344 /* Enumerate all modules */
4345 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4349 if (abuilder->modules) {
4350 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4351 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4352 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4358 if (!type && abuilder->loaded_modules) {
4359 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4360 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4361 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4368 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4370 mono_reflection_free_type_info (&info);
4372 MonoException *e = NULL;
4375 e = mono_get_exception_type_load (name, NULL);
4377 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4378 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4380 mono_loader_clear_error ();
4383 mono_set_pending_exception (e);
4385 } else if (mono_loader_get_last_error ()) {
4387 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4390 mono_loader_clear_error ();
4393 if (type->type == MONO_TYPE_CLASS) {
4394 MonoClass *klass = mono_type_get_class (type);
4396 /* need to report exceptions ? */
4397 if (throwOnError && mono_class_has_failure (klass)) {
4398 /* report SecurityException (or others) that occured when loading the assembly */
4399 MonoException *exc = mono_class_get_exception_for_failure (klass);
4400 mono_loader_clear_error ();
4401 mono_set_pending_exception (exc);
4406 /* g_print ("got it\n"); */
4407 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4408 mono_error_raise_exception (&error);
4414 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4417 gchar *shadow_ini_file;
4420 /* Check for shadow-copied assembly */
4421 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4422 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4424 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4425 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4431 g_free (shadow_ini_file);
4432 if (content != NULL) {
4435 *filename = content;
4442 ICALL_EXPORT MonoString *
4443 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4445 MonoDomain *domain = mono_object_domain (assembly);
4446 MonoAssembly *mass = assembly->assembly;
4447 MonoString *res = NULL;
4452 if (g_path_is_absolute (mass->image->name)) {
4453 absolute = g_strdup (mass->image->name);
4454 dirname = g_path_get_dirname (absolute);
4456 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4457 dirname = g_strdup (mass->basedir);
4460 replace_shadow_path (domain, dirname, &absolute);
4465 for (i = strlen (absolute) - 1; i >= 0; i--)
4466 if (absolute [i] == '\\')
4471 uri = g_filename_to_uri (absolute, NULL, NULL);
4473 const char *prepend = "file://";
4475 if (*absolute == '/' && *(absolute + 1) == '/') {
4478 prepend = "file:///";
4481 uri = g_strconcat (prepend, absolute, NULL);
4485 res = mono_string_new (domain, uri);
4492 ICALL_EXPORT MonoBoolean
4493 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4495 MonoAssembly *mass = assembly->assembly;
4497 return mass->in_gac;
4500 ICALL_EXPORT MonoReflectionAssembly*
4501 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4506 MonoImageOpenStatus status;
4507 MonoReflectionAssembly* result = NULL;
4509 name = mono_string_to_utf8 (mname);
4510 res = mono_assembly_load_with_partial_name (name, &status);
4516 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4518 mono_error_set_pending_exception (&error);
4522 ICALL_EXPORT MonoString *
4523 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4525 MonoDomain *domain = mono_object_domain (assembly);
4528 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4533 ICALL_EXPORT MonoBoolean
4534 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4536 return assembly->assembly->ref_only;
4539 ICALL_EXPORT MonoString *
4540 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4542 MonoDomain *domain = mono_object_domain (assembly);
4544 return mono_string_new (domain, assembly->assembly->image->version);
4547 ICALL_EXPORT MonoReflectionMethod*
4548 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4551 MonoReflectionMethod *res = NULL;
4554 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4558 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4559 if (!mono_error_ok (&error))
4562 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4565 if (!mono_error_ok (&error))
4566 mono_error_set_pending_exception (&error);
4570 ICALL_EXPORT MonoReflectionModule*
4571 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4574 MonoReflectionModule *result = NULL;
4575 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4576 if (!mono_error_ok (&error))
4577 mono_error_set_pending_exception (&error);
4581 ICALL_EXPORT MonoArray*
4582 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4584 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4585 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4589 for (i = 0; i < table->rows; ++i) {
4590 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4591 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4597 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4599 static MonoMethod *create_version = NULL;
4603 mono_error_init (error);
4606 if (!create_version) {
4607 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4608 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4609 g_assert (create_version);
4610 mono_method_desc_free (desc);
4616 args [3] = &revision;
4617 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4618 return_val_if_nok (error, NULL);
4620 mono_runtime_invoke_checked (create_version, result, args, error);
4621 return_val_if_nok (error, NULL);
4626 ICALL_EXPORT MonoArray*
4627 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4631 MonoDomain *domain = mono_object_domain (assembly);
4633 static MonoMethod *create_culture = NULL;
4634 MonoImage *image = assembly->assembly->image;
4638 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4641 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4643 if (count > 0 && !create_culture) {
4644 MonoMethodDesc *desc = mono_method_desc_new (
4645 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4646 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4647 g_assert (create_culture);
4648 mono_method_desc_free (desc);
4651 for (i = 0; i < count; i++) {
4652 MonoObject *version;
4653 MonoReflectionAssemblyName *aname;
4654 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4656 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4658 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4659 domain, mono_class_get_assembly_name_class (), &error);
4660 mono_error_raise_exception (&error);
4662 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4664 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4665 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4666 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4667 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4668 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4669 aname->versioncompat = 1; /* SameMachine (default) */
4670 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4672 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4673 mono_error_raise_exception (&error);
4675 MONO_OBJECT_SETREF (aname, version, version);
4677 if (create_culture) {
4679 MonoBoolean assembly_ref = 1;
4680 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4681 args [1] = &assembly_ref;
4683 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4684 mono_error_raise_exception (&error);
4686 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4689 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4690 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4691 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4693 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4694 /* public key token isn't copied - the class library will
4695 automatically generate it from the public key if required */
4696 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4697 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4699 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4700 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4703 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4706 /* note: this function doesn't return the codebase on purpose (i.e. it can
4707 be used under partial trust as path information isn't present). */
4709 mono_array_setref (result, i, aname);
4714 /* move this in some file in mono/util/ */
4716 g_concat_dir_and_file (const char *dir, const char *file)
4718 g_return_val_if_fail (dir != NULL, NULL);
4719 g_return_val_if_fail (file != NULL, NULL);
4722 * If the directory name doesn't have a / on the end, we need
4723 * to add one so we get a proper path to the file
4725 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4726 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4728 return g_strconcat (dir, file, NULL);
4732 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4735 char *n = mono_string_to_utf8 (name);
4736 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4738 guint32 cols [MONO_MANIFEST_SIZE];
4739 guint32 impl, file_idx;
4743 for (i = 0; i < table->rows; ++i) {
4744 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4745 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4746 if (strcmp (val, n) == 0)
4750 if (i == table->rows)
4753 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4756 * this code should only be called after obtaining the
4757 * ResourceInfo and handling the other cases.
4759 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4760 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4762 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4767 module = assembly->assembly->image;
4770 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4771 mono_error_raise_exception (&error);
4772 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4774 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4777 ICALL_EXPORT gboolean
4778 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4781 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4783 guint32 cols [MONO_MANIFEST_SIZE];
4784 guint32 file_cols [MONO_FILE_SIZE];
4788 n = mono_string_to_utf8 (name);
4789 for (i = 0; i < table->rows; ++i) {
4790 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4791 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4792 if (strcmp (val, n) == 0)
4796 if (i == table->rows)
4799 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4800 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4803 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4804 case MONO_IMPLEMENTATION_FILE:
4805 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4806 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4807 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4808 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4809 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4810 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4813 info->location = RESOURCE_LOCATION_EMBEDDED;
4816 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4817 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4818 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4819 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4820 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4821 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4823 mono_set_pending_exception (ex);
4826 MonoReflectionAssembly *assm_obj;
4827 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4829 mono_error_set_pending_exception (&error);
4832 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4834 /* Obtain info recursively */
4835 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4836 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4839 case MONO_IMPLEMENTATION_EXP_TYPE:
4840 g_assert_not_reached ();
4848 ICALL_EXPORT MonoObject*
4849 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4851 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4852 MonoArray *result = NULL;
4857 /* check hash if needed */
4859 n = mono_string_to_utf8 (name);
4860 for (i = 0; i < table->rows; ++i) {
4861 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4862 if (strcmp (val, n) == 0) {
4865 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4866 fn = mono_string_new (mono_object_domain (assembly), n);
4868 return (MonoObject*)fn;
4876 for (i = 0; i < table->rows; ++i) {
4877 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4881 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4884 for (i = 0; i < table->rows; ++i) {
4885 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4886 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4887 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4888 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4893 return (MonoObject*)result;
4896 ICALL_EXPORT MonoArray*
4897 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4900 MonoDomain *domain = mono_domain_get();
4903 int i, j, file_count = 0;
4904 MonoImage **modules;
4905 guint32 module_count, real_module_count;
4906 MonoTableInfo *table;
4907 guint32 cols [MONO_FILE_SIZE];
4908 MonoImage *image = assembly->assembly->image;
4910 g_assert (image != NULL);
4911 g_assert (!assembly_is_dynamic (assembly->assembly));
4913 table = &image->tables [MONO_TABLE_FILE];
4914 file_count = table->rows;
4916 modules = image->modules;
4917 module_count = image->module_count;
4919 real_module_count = 0;
4920 for (i = 0; i < module_count; ++i)
4922 real_module_count ++;
4924 klass = mono_class_get_module_class ();
4925 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4927 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
4928 mono_error_raise_exception (&error);
4929 mono_array_setref (res, 0, image_obj);
4931 for (i = 0; i < module_count; ++i)
4933 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
4934 mono_error_raise_exception (&error);
4935 mono_array_setref (res, j, rm);
4939 for (i = 0; i < file_count; ++i, ++j) {
4940 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4941 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
4942 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
4943 mono_error_raise_exception (&error);
4944 mono_array_setref (res, j, rm);
4947 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4949 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4950 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
4953 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
4954 mono_error_raise_exception (&error);
4955 mono_array_setref (res, j, rm);
4962 ICALL_EXPORT MonoReflectionMethod*
4963 ves_icall_GetCurrentMethod (void)
4965 MonoReflectionMethod *res = NULL;
4968 MonoMethod *m = mono_method_get_last_managed ();
4971 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
4975 while (m->is_inflated)
4976 m = ((MonoMethodInflated*)m)->declaring;
4978 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
4979 mono_error_raise_exception (&error);
4985 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4988 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4991 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4992 //method is inflated, we should inflate it on the other class
4993 MonoGenericContext ctx;
4994 ctx.method_inst = inflated->context.method_inst;
4995 ctx.class_inst = inflated->context.class_inst;
4996 if (klass->generic_class)
4997 ctx.class_inst = klass->generic_class->context.class_inst;
4998 else if (klass->generic_container)
4999 ctx.class_inst = klass->generic_container->context.class_inst;
5000 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5001 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5005 mono_class_setup_methods (method->klass);
5006 if (mono_class_has_failure (method->klass))
5008 for (i = 0; i < method->klass->method.count; ++i) {
5009 if (method->klass->methods [i] == method) {
5014 mono_class_setup_methods (klass);
5015 if (mono_class_has_failure (klass))
5017 g_assert (offset >= 0 && offset < klass->method.count);
5018 return klass->methods [offset];
5021 ICALL_EXPORT MonoReflectionMethod*
5022 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5024 MonoReflectionMethod *res = NULL;
5028 klass = mono_class_from_mono_type (type);
5029 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5031 if (method->klass != klass) {
5032 method = mono_method_get_equivalent_method (method, klass);
5037 klass = method->klass;
5038 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5039 mono_error_raise_exception (&error);
5043 ICALL_EXPORT MonoReflectionMethodBody*
5044 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5046 return mono_method_body_get_object (mono_domain_get (), method);
5049 ICALL_EXPORT MonoReflectionAssembly*
5050 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5053 MonoReflectionAssembly *result;
5054 MonoMethod *dest = NULL;
5056 mono_stack_walk_no_il (get_executing, &dest);
5058 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5060 mono_error_set_pending_exception (&error);
5065 ICALL_EXPORT MonoReflectionAssembly*
5066 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5069 MonoReflectionAssembly *result;
5070 MonoDomain* domain = mono_domain_get ();
5072 if (!domain->entry_assembly)
5075 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5077 mono_error_set_pending_exception (&error);
5081 ICALL_EXPORT MonoReflectionAssembly*
5082 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5087 MonoReflectionAssembly *result;
5090 mono_stack_walk_no_il (get_executing, &dest);
5092 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5096 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5099 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5101 mono_error_set_pending_exception (&error);
5105 ICALL_EXPORT MonoString *
5106 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5107 gboolean assembly_qualified)
5109 MonoDomain *domain = mono_object_domain (object);
5110 MonoTypeNameFormat format;
5115 format = assembly_qualified ?
5116 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5117 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5119 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5121 name = mono_type_get_name_full (object->type, format);
5125 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5130 res = mono_string_new (domain, name);
5137 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5139 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5140 mono_class_init_or_throw (klass);
5141 return mono_security_core_clr_class_level (klass);
5145 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5147 MonoClassField *field = rfield->field;
5148 return mono_security_core_clr_field_level (field, TRUE);
5152 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5154 MonoMethod *method = rfield->method;
5155 return mono_security_core_clr_method_level (method, TRUE);
5159 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token, MonoError *error)
5161 static MonoMethod *create_culture = NULL;
5165 const char *pkey_ptr;
5167 MonoBoolean assembly_ref = 0;
5169 mono_error_init (error);
5171 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5172 aname->major = name->major;
5173 aname->minor = name->minor;
5174 aname->build = name->build;
5175 aname->flags = name->flags;
5176 aname->revision = name->revision;
5177 aname->hashalg = name->hash_alg;
5178 aname->versioncompat = 1; /* SameMachine (default) */
5179 aname->processor_architecture = name->arch;
5181 if (by_default_version) {
5182 MonoObject *version;
5184 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5185 return_if_nok (error);
5187 MONO_OBJECT_SETREF (aname, version, version);
5191 if (absolute != NULL && *absolute != '\0') {
5192 const gchar *prepend = "file://";
5195 codebase = g_strdup (absolute);
5200 for (i = strlen (codebase) - 1; i >= 0; i--)
5201 if (codebase [i] == '\\')
5204 if (*codebase == '/' && *(codebase + 1) == '/') {
5207 prepend = "file:///";
5211 result = g_strconcat (prepend, codebase, NULL);
5217 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5221 if (!create_culture) {
5222 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5223 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5224 g_assert (create_culture);
5225 mono_method_desc_free (desc);
5228 if (name->culture) {
5229 args [0] = mono_string_new (domain, name->culture);
5230 args [1] = &assembly_ref;
5232 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5233 return_if_nok (error);
5235 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5238 if (name->public_key) {
5239 pkey_ptr = (char*)name->public_key;
5240 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5242 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5243 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5244 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5245 } else if (default_publickey) {
5246 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5247 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5250 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5251 if (name->public_key_token [0]) {
5255 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5256 p = mono_array_addr (aname->keyToken, char, 0);
5258 for (i = 0, j = 0; i < 8; i++) {
5259 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5260 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5263 } else if (default_token) {
5264 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5268 ICALL_EXPORT MonoString *
5269 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5271 MonoDomain *domain = mono_object_domain (assembly);
5272 MonoAssembly *mass = assembly->assembly;
5276 name = mono_stringify_assembly_name (&mass->aname);
5277 res = mono_string_new (domain, name);
5284 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5288 MonoAssembly *mass = assembly->assembly;
5290 if (g_path_is_absolute (mass->image->name)) {
5291 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5292 mono_error_set_pending_exception (&error);
5295 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5297 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5298 mono_error_set_pending_exception (&error);
5304 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5308 MonoImageOpenStatus status = MONO_IMAGE_OK;
5311 MonoAssemblyName name;
5314 filename = mono_string_to_utf8 (fname);
5316 dirname = g_path_get_dirname (filename);
5317 replace_shadow_path (mono_domain_get (), dirname, &filename);
5320 image = mono_image_open (filename, &status);
5326 if (status == MONO_IMAGE_IMAGE_INVALID)
5327 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5329 exc = mono_get_exception_file_not_found2 (NULL, fname);
5330 mono_set_pending_exception (exc);
5334 res = mono_assembly_fill_assembly_name (image, &name);
5336 mono_image_close (image);
5338 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5342 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5343 mono_error_set_pending_exception (&error);
5345 mono_image_close (image);
5349 ICALL_EXPORT MonoBoolean
5350 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5351 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5353 MonoBoolean result = FALSE;
5354 MonoDeclSecurityEntry entry;
5356 /* SecurityAction.RequestMinimum */
5357 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5358 *minimum = entry.blob;
5359 *minLength = entry.size;
5362 /* SecurityAction.RequestOptional */
5363 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5364 *optional = entry.blob;
5365 *optLength = entry.size;
5368 /* SecurityAction.RequestRefuse */
5369 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5370 *refused = entry.blob;
5371 *refLength = entry.size;
5379 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5381 guint32 attrs, visibility;
5383 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5384 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5385 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5388 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5394 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5396 MonoReflectionType *rt;
5399 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5402 mono_error_init (error);
5404 /* we start the count from 1 because we skip the special type <Module> */
5407 for (i = 1; i < tdef->rows; ++i) {
5408 if (mono_module_type_is_visible (tdef, image, i + 1))
5412 count = tdef->rows - 1;
5414 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5415 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5417 for (i = 1; i < tdef->rows; ++i) {
5418 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5419 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5420 mono_loader_assert_no_error (); /* Plug any leaks */
5421 mono_error_assert_ok (error);
5424 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5425 return_val_if_nok (error, NULL);
5427 mono_array_setref (res, count, rt);
5429 MonoException *ex = mono_error_convert_to_exception (error);
5430 mono_array_setref (*exceptions, count, ex);
5439 ICALL_EXPORT MonoArray*
5440 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5443 MonoArray *res = NULL;
5444 MonoArray *exceptions = NULL;
5445 MonoImage *image = NULL;
5446 MonoTableInfo *table = NULL;
5449 int i, len, ex_count;
5451 domain = mono_object_domain (assembly);
5453 g_assert (!assembly_is_dynamic (assembly->assembly));
5454 image = assembly->assembly->image;
5455 table = &image->tables [MONO_TABLE_FILE];
5456 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5457 mono_error_raise_exception (&error);
5459 /* Append data from all modules in the assembly */
5460 for (i = 0; i < table->rows; ++i) {
5461 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5462 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5467 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5468 mono_error_raise_exception (&error);
5470 /* Append the new types to the end of the array */
5471 if (mono_array_length (res2) > 0) {
5473 MonoArray *res3, *ex3;
5475 len1 = mono_array_length (res);
5476 len2 = mono_array_length (res2);
5478 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5479 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5480 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5483 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5484 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5485 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5492 /* the ReflectionTypeLoadException must have all the types (Types property),
5493 * NULL replacing types which throws an exception. The LoaderException must
5494 * contain all exceptions for NULL items.
5497 len = mono_array_length (res);
5500 for (i = 0; i < len; i++) {
5501 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5505 klass = mono_type_get_class (t->type);
5506 if ((klass != NULL) && mono_class_has_failure (klass)) {
5507 /* keep the class in the list */
5508 list = g_list_append (list, klass);
5509 /* and replace Type with NULL */
5510 mono_array_setref (res, i, NULL);
5517 if (list || ex_count) {
5519 MonoException *exc = NULL;
5520 MonoArray *exl = NULL;
5521 int j, length = g_list_length (list) + ex_count;
5523 mono_loader_clear_error ();
5525 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5526 /* Types for which mono_class_get_checked () succeeded */
5527 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5528 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5529 mono_array_setref (exl, i, exc);
5531 /* Types for which it don't */
5532 for (j = 0; j < mono_array_length (exceptions); ++j) {
5533 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5535 g_assert (i < length);
5536 mono_array_setref (exl, i, exc);
5543 exc = mono_get_exception_reflection_type_load (res, exl);
5544 mono_loader_clear_error ();
5545 mono_set_pending_exception (exc);
5552 ICALL_EXPORT gboolean
5553 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5556 MonoAssemblyName aname;
5557 MonoDomain *domain = mono_object_domain (name);
5559 gboolean is_version_defined;
5560 gboolean is_token_defined;
5562 aname.public_key = NULL;
5563 val = mono_string_to_utf8 (assname);
5564 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5565 g_free ((guint8*) aname.public_key);
5570 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5571 mono_error_set_pending_exception (&error);
5573 mono_assembly_name_free (&aname);
5574 g_free ((guint8*) aname.public_key);
5580 ICALL_EXPORT MonoReflectionType*
5581 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5584 MonoReflectionType *ret;
5585 MonoDomain *domain = mono_object_domain (module);
5588 g_assert (module->image);
5590 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5591 /* These images do not have a global type */
5594 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5595 if (!mono_error_ok (&error)) {
5596 mono_error_set_pending_exception (&error);
5600 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5601 if (!mono_error_ok (&error)) {
5602 mono_error_set_pending_exception (&error);
5610 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5612 /*if (module->image)
5613 mono_image_close (module->image);*/
5616 ICALL_EXPORT MonoString*
5617 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5619 MonoDomain *domain = mono_object_domain (module);
5621 g_assert (module->image);
5622 return mono_string_new (domain, module->image->guid);
5625 ICALL_EXPORT gpointer
5626 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5629 if (module->image && module->image->is_module_handle)
5630 return module->image->raw_data;
5633 return (gpointer) (-1);
5637 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5639 if (image_is_dynamic (image)) {
5640 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5641 *pe_kind = dyn->pe_kind;
5642 *machine = dyn->machine;
5645 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5646 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5651 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5653 return (image->md_version_major << 16) | (image->md_version_minor);
5656 ICALL_EXPORT MonoArray*
5657 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5660 MonoArray *exceptions;
5664 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5668 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5669 mono_error_raise_exception (&error);
5671 for (i = 0; i < mono_array_length (exceptions); ++i) {
5672 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5674 mono_set_pending_exception (ex);
5683 mono_memberref_is_method (MonoImage *image, guint32 token)
5685 if (!image_is_dynamic (image)) {
5686 guint32 cols [MONO_MEMBERREF_SIZE];
5688 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5689 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5690 mono_metadata_decode_blob_size (sig, &sig);
5691 return (*sig != 0x6);
5693 MonoClass *handle_class;
5695 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5698 return mono_defaults.methodhandle_class == handle_class;
5703 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5706 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5707 mono_array_addr (type_args, MonoType*, 0));
5709 context->class_inst = NULL;
5711 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5712 mono_array_addr (method_args, MonoType*, 0));
5714 context->method_inst = NULL;
5717 ICALL_EXPORT MonoType*
5718 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5721 int table = mono_metadata_token_table (token);
5722 int index = mono_metadata_token_index (token);
5723 MonoGenericContext context;
5726 *resolve_error = ResolveTokenError_Other;
5728 /* Validate token */
5729 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5730 (table != MONO_TABLE_TYPESPEC)) {
5731 *resolve_error = ResolveTokenError_BadTable;
5735 if (image_is_dynamic (image)) {
5736 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5737 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5738 return klass ? &klass->byval_arg : NULL;
5741 init_generic_context_from_args (&context, type_args, method_args);
5742 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5743 return klass ? &klass->byval_arg : NULL;
5746 if ((index <= 0) || (index > image->tables [table].rows)) {
5747 *resolve_error = ResolveTokenError_OutOfRange;
5751 init_generic_context_from_args (&context, type_args, method_args);
5752 klass = mono_class_get_checked (image, token, &error);
5754 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5755 if (!mono_error_ok (&error)) {
5756 mono_error_set_pending_exception (&error);
5761 return &klass->byval_arg;
5766 ICALL_EXPORT MonoMethod*
5767 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5770 int table = mono_metadata_token_table (token);
5771 int index = mono_metadata_token_index (token);
5772 MonoGenericContext context;
5775 *resolve_error = ResolveTokenError_Other;
5777 /* Validate token */
5778 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5779 (table != MONO_TABLE_MEMBERREF)) {
5780 *resolve_error = ResolveTokenError_BadTable;
5784 if (image_is_dynamic (image)) {
5785 if (table == MONO_TABLE_METHOD)
5786 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5788 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5789 *resolve_error = ResolveTokenError_BadTable;
5793 init_generic_context_from_args (&context, type_args, method_args);
5794 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5797 if ((index <= 0) || (index > image->tables [table].rows)) {
5798 *resolve_error = ResolveTokenError_OutOfRange;
5801 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5802 *resolve_error = ResolveTokenError_BadTable;
5806 init_generic_context_from_args (&context, type_args, method_args);
5807 method = mono_get_method_checked (image, token, NULL, &context, &error);
5808 mono_error_set_pending_exception (&error);
5813 ICALL_EXPORT MonoString*
5814 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5816 int index = mono_metadata_token_index (token);
5818 *error = ResolveTokenError_Other;
5820 /* Validate token */
5821 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5822 *error = ResolveTokenError_BadTable;
5826 if (image_is_dynamic (image))
5827 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5829 if ((index <= 0) || (index >= image->heap_us.size)) {
5830 *error = ResolveTokenError_OutOfRange;
5834 /* FIXME: What to do if the index points into the middle of a string ? */
5836 return mono_ldstr (mono_domain_get (), image, index);
5839 ICALL_EXPORT MonoClassField*
5840 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5844 int table = mono_metadata_token_table (token);
5845 int index = mono_metadata_token_index (token);
5846 MonoGenericContext context;
5847 MonoClassField *field;
5849 *resolve_error = ResolveTokenError_Other;
5851 /* Validate token */
5852 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5853 *resolve_error = ResolveTokenError_BadTable;
5857 if (image_is_dynamic (image)) {
5858 if (table == MONO_TABLE_FIELD)
5859 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5861 if (mono_memberref_is_method (image, token)) {
5862 *resolve_error = ResolveTokenError_BadTable;
5866 init_generic_context_from_args (&context, type_args, method_args);
5867 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5870 if ((index <= 0) || (index > image->tables [table].rows)) {
5871 *resolve_error = ResolveTokenError_OutOfRange;
5874 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5875 *resolve_error = ResolveTokenError_BadTable;
5879 init_generic_context_from_args (&context, type_args, method_args);
5880 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5881 mono_error_set_pending_exception (&error);
5887 ICALL_EXPORT MonoObject*
5888 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5892 int table = mono_metadata_token_table (token);
5894 *error = ResolveTokenError_Other;
5897 case MONO_TABLE_TYPEDEF:
5898 case MONO_TABLE_TYPEREF:
5899 case MONO_TABLE_TYPESPEC: {
5900 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5902 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
5903 mono_error_raise_exception (&merror);
5910 case MONO_TABLE_METHOD:
5911 case MONO_TABLE_METHODSPEC: {
5912 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5914 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5915 mono_error_raise_exception (&merror);
5921 case MONO_TABLE_FIELD: {
5922 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5924 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5925 mono_error_raise_exception (&merror);
5931 case MONO_TABLE_MEMBERREF:
5932 if (mono_memberref_is_method (image, token)) {
5933 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5935 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5936 mono_error_raise_exception (&merror);
5943 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5945 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5946 mono_error_raise_exception (&merror);
5955 *error = ResolveTokenError_BadTable;
5961 ICALL_EXPORT MonoArray*
5962 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5964 int table = mono_metadata_token_table (token);
5965 int idx = mono_metadata_token_index (token);
5966 MonoTableInfo *tables = image->tables;
5971 *error = ResolveTokenError_OutOfRange;
5973 /* FIXME: Support other tables ? */
5974 if (table != MONO_TABLE_STANDALONESIG)
5977 if (image_is_dynamic (image))
5980 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5983 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5985 ptr = mono_metadata_blob_heap (image, sig);
5986 len = mono_metadata_decode_blob_size (ptr, &ptr);
5988 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5989 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5993 ICALL_EXPORT MonoReflectionType*
5994 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5997 MonoReflectionType *ret;
5999 int isbyref = 0, rank;
6000 char *str = mono_string_to_utf8 (smodifiers);
6003 klass = mono_class_from_mono_type (tb->type.type);
6005 /* logic taken from mono_reflection_parse_type(): keep in sync */
6009 if (isbyref) { /* only one level allowed by the spec */
6018 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6019 mono_error_raise_exception (&error);
6023 klass = mono_ptr_class_get (&klass->byval_arg);
6024 mono_class_init (klass);
6035 else if (*p != '*') { /* '*' means unknown lower bound */
6046 klass = mono_array_class_get (klass, rank);
6047 mono_class_init (klass);
6056 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6057 mono_error_raise_exception (&error);
6062 ICALL_EXPORT MonoBoolean
6063 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
6069 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6075 check_for_invalid_type (MonoClass *klass)
6079 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6082 name = mono_type_get_full_name (klass);
6083 str = mono_string_new (mono_domain_get (), name);
6085 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
6088 ICALL_EXPORT MonoReflectionType *
6089 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6092 MonoReflectionType *ret;
6093 MonoClass *klass, *aklass;
6095 klass = mono_class_from_mono_type (type->type);
6096 check_for_invalid_type (klass);
6098 if (rank == 0) //single dimentional array
6099 aklass = mono_array_class_get (klass, 1);
6101 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6103 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6104 mono_error_raise_exception (&error);
6109 ICALL_EXPORT MonoReflectionType *
6110 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6113 MonoReflectionType *ret;
6116 klass = mono_class_from_mono_type (type->type);
6117 mono_class_init_or_throw (klass);
6118 check_for_invalid_type (klass);
6120 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6121 mono_error_raise_exception (&error);
6126 ICALL_EXPORT MonoReflectionType *
6127 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6130 MonoReflectionType *ret;
6131 MonoClass *klass, *pklass;
6133 klass = mono_class_from_mono_type (type->type);
6134 mono_class_init_or_throw (klass);
6135 check_for_invalid_type (klass);
6137 pklass = mono_ptr_class_get (type->type);
6139 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6140 mono_error_raise_exception (&error);
6145 ICALL_EXPORT MonoObject *
6146 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6147 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6150 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6151 MonoObject *delegate;
6153 MonoMethod *method = info->method;
6155 mono_class_init_or_throw (delegate_class);
6157 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
6159 if (mono_security_core_clr_enabled ()) {
6160 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6164 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6165 mono_error_raise_exception (&error);
6167 if (method_is_dynamic (method)) {
6168 /* Creating a trampoline would leak memory */
6169 func = mono_compile_method (method);
6171 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6172 method = mono_object_get_virtual_method (target, method);
6173 func = mono_create_ftnptr (mono_domain_get (),
6174 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6177 mono_delegate_ctor_with_method (delegate, target, func, method);
6182 ICALL_EXPORT MonoMulticastDelegate *
6183 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6186 MonoMulticastDelegate *ret;
6188 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6190 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6191 mono_error_raise_exception (&error);
6192 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6197 ICALL_EXPORT MonoReflectionMethod*
6198 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6200 MonoReflectionMethod *ret = NULL;
6202 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6203 mono_error_raise_exception (&error);
6209 static inline gint32
6210 mono_array_get_byte_length (MonoArray *array)
6216 klass = array->obj.vtable->klass;
6218 if (array->bounds == NULL)
6219 length = array->max_length;
6222 for (i = 0; i < klass->rank; ++ i)
6223 length *= array->bounds [i].length;
6226 switch (klass->element_class->byval_arg.type) {
6229 case MONO_TYPE_BOOLEAN:
6233 case MONO_TYPE_CHAR:
6241 return length * sizeof (gpointer);
6252 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6254 return mono_array_get_byte_length (array);
6258 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6260 return mono_array_get (array, gint8, idx);
6264 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6266 mono_array_set (array, gint8, idx, value);
6269 ICALL_EXPORT MonoBoolean
6270 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6272 guint8 *src_buf, *dest_buf;
6275 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6279 g_assert (count >= 0);
6281 /* This is called directly from the class libraries without going through the managed wrapper */
6282 MONO_CHECK_ARG_NULL (src, FALSE);
6283 MONO_CHECK_ARG_NULL (dest, FALSE);
6285 /* watch out for integer overflow */
6286 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6289 src_buf = (guint8 *)src->vector + src_offset;
6290 dest_buf = (guint8 *)dest->vector + dest_offset;
6293 memcpy (dest_buf, src_buf, count);
6295 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6300 #ifndef DISABLE_REMOTING
6301 ICALL_EXPORT MonoObject *
6302 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6305 MonoDomain *domain = mono_object_domain (this_obj);
6307 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6308 MonoTransparentProxy *tp;
6312 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6313 mono_error_raise_exception (&error);
6314 tp = (MonoTransparentProxy*) res;
6316 MONO_OBJECT_SETREF (tp, rp, rp);
6317 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6318 klass = mono_class_from_mono_type (type);
6320 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6321 mono_class_setup_vtable (klass);
6322 if (mono_class_has_failure (klass)) {
6323 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6327 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
6328 tp->remote_class = mono_remote_class (domain, class_name, klass);
6330 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6334 ICALL_EXPORT MonoReflectionType *
6335 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6338 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6339 mono_error_raise_exception (&error);
6345 /* System.Environment */
6348 ves_icall_System_Environment_get_UserName (void)
6350 /* using glib is more portable */
6351 return mono_string_new (mono_domain_get (), g_get_user_name ());
6355 ICALL_EXPORT MonoString *
6356 ves_icall_System_Environment_get_MachineName (void)
6358 #if defined (HOST_WIN32)
6363 len = MAX_COMPUTERNAME_LENGTH + 1;
6364 buf = g_new (gunichar2, len);
6367 if (GetComputerName (buf, (PDWORD) &len)) {
6369 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6370 mono_error_raise_exception (&error);
6375 #elif !defined(DISABLE_SOCKETS)
6379 #if defined _SC_HOST_NAME_MAX
6380 n = sysconf (_SC_HOST_NAME_MAX);
6384 buf = g_malloc (n+1);
6386 if (gethostname (buf, n) == 0){
6388 result = mono_string_new (mono_domain_get (), buf);
6395 return mono_string_new (mono_domain_get (), "mono");
6400 ves_icall_System_Environment_get_Platform (void)
6402 #if defined (TARGET_WIN32)
6405 #elif defined(__MACH__)
6408 // Notice that the value is hidden from user code, and only exposed
6409 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6410 // define and making assumptions based on Unix/128/4 values before there
6411 // was a MacOS define. Lots of code would assume that not-Unix meant
6412 // Windows, but in this case, it would be OSX.
6421 ICALL_EXPORT MonoString *
6422 ves_icall_System_Environment_get_NewLine (void)
6424 #if defined (HOST_WIN32)
6425 return mono_string_new (mono_domain_get (), "\r\n");
6427 return mono_string_new (mono_domain_get (), "\n");
6431 ICALL_EXPORT MonoBoolean
6432 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6434 #if SIZEOF_VOID_P == 8
6438 gboolean isWow64Process = FALSE;
6439 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6440 return (MonoBoolean)isWow64Process;
6442 #elif defined(HAVE_SYS_UTSNAME_H)
6443 struct utsname name;
6445 if (uname (&name) >= 0) {
6446 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6453 ICALL_EXPORT MonoString *
6454 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6462 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6463 value = g_getenv (utf8_name);
6470 return mono_string_new (mono_domain_get (), value);
6474 * There is no standard way to get at environ.
6477 #ifndef __MINGW32_VERSION
6478 #if defined(__APPLE__)
6479 #if defined (TARGET_OSX)
6480 /* Apple defines this in crt_externs.h but doesn't provide that header for
6481 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6482 * in fact exist on all implementations (so far)
6484 gchar ***_NSGetEnviron(void);
6485 #define environ (*_NSGetEnviron())
6487 static char *mono_environ[1] = { NULL };
6488 #define environ mono_environ
6489 #endif /* defined (TARGET_OSX) */
6497 ICALL_EXPORT MonoArray *
6498 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6509 env_strings = GetEnvironmentStrings();
6512 env_string = env_strings;
6513 while (*env_string != '\0') {
6514 /* weird case that MS seems to skip */
6515 if (*env_string != '=')
6517 while (*env_string != '\0')
6523 domain = mono_domain_get ();
6524 names = mono_array_new (domain, mono_defaults.string_class, n);
6528 env_string = env_strings;
6529 while (*env_string != '\0') {
6530 /* weird case that MS seems to skip */
6531 if (*env_string != '=') {
6532 equal_str = wcschr(env_string, '=');
6533 g_assert(equal_str);
6535 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6536 mono_error_raise_exception (&error);
6537 mono_array_setref (names, n, str);
6540 while (*env_string != '\0')
6545 FreeEnvironmentStrings (env_strings);
6558 for (e = environ; *e != 0; ++ e)
6561 domain = mono_domain_get ();
6562 names = mono_array_new (domain, mono_defaults.string_class, n);
6565 for (e = environ; *e != 0; ++ e) {
6566 parts = g_strsplit (*e, "=", 2);
6568 str = mono_string_new (domain, *parts);
6569 mono_array_setref (names, n, str);
6582 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6584 #if !GLIB_CHECK_VERSION(2,4,0)
6585 #define g_setenv(a,b,c) setenv(a,b,c)
6586 #define g_unsetenv(a) unsetenv(a)
6590 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6593 gunichar2 *utf16_name, *utf16_value;
6595 gchar *utf8_name, *utf8_value;
6600 utf16_name = mono_string_to_utf16 (name);
6601 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6602 SetEnvironmentVariable (utf16_name, NULL);
6603 g_free (utf16_name);
6607 utf16_value = mono_string_to_utf16 (value);
6609 SetEnvironmentVariable (utf16_name, utf16_value);
6611 g_free (utf16_name);
6612 g_free (utf16_value);
6614 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6616 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6617 g_unsetenv (utf8_name);
6622 utf8_value = mono_string_to_utf8_checked (value, &error);
6623 if (!mono_error_ok (&error)) {
6625 mono_error_set_pending_exception (&error);
6628 g_setenv (utf8_name, utf8_value, TRUE);
6631 g_free (utf8_value);
6636 ves_icall_System_Environment_Exit (int result)
6638 mono_environment_exitcode_set (result);
6640 /* FIXME: There are some cleanup hangs that should be worked out, but
6641 * if the program is going to exit, everything will be cleaned up when
6642 * NaCl exits anyway.
6644 #ifndef __native_client__
6645 if (!mono_runtime_try_shutdown ())
6646 mono_thread_exit ();
6648 /* Suspend all managed threads since the runtime is going away */
6649 mono_thread_suspend_all_other_threads ();
6651 mono_runtime_quit ();
6654 /* we may need to do some cleanup here... */
6658 ICALL_EXPORT MonoString*
6659 ves_icall_System_Environment_GetGacPath (void)
6661 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6664 ICALL_EXPORT MonoString*
6665 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6667 #if defined (HOST_WIN32)
6668 #ifndef CSIDL_FLAG_CREATE
6669 #define CSIDL_FLAG_CREATE 0x8000
6672 WCHAR path [MAX_PATH];
6673 /* Create directory if no existing */
6674 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6679 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6680 mono_error_raise_exception (&error);
6684 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6686 return mono_string_new (mono_domain_get (), "");
6689 ICALL_EXPORT MonoArray *
6690 ves_icall_System_Environment_GetLogicalDrives (void)
6693 gunichar2 buf [256], *ptr, *dname;
6695 guint initial_size = 127, size = 128;
6698 MonoString *drivestr;
6699 MonoDomain *domain = mono_domain_get ();
6705 while (size > initial_size) {
6706 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6707 if (size > initial_size) {
6710 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6711 initial_size = size;
6725 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6730 while (*u16) { u16++; len ++; }
6731 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6732 mono_error_raise_exception (&error);
6733 mono_array_setref (result, ndrives++, drivestr);
6743 ICALL_EXPORT MonoString *
6744 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6746 gunichar2 volume_name [MAX_PATH + 1];
6748 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6750 return mono_string_from_utf16 (volume_name);
6753 ICALL_EXPORT MonoString *
6754 ves_icall_System_Environment_InternalGetHome (void)
6756 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6759 static const char *encodings [] = {
6761 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6762 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6763 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6765 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6766 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6767 "x_unicode_2_0_utf_7",
6769 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6770 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6772 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6775 "unicodefffe", "utf_16be",
6782 * Returns the internal codepage, if the value of "int_code_page" is
6783 * 1 at entry, and we can not compute a suitable code page number,
6784 * returns the code page as a string
6786 ICALL_EXPORT MonoString*
6787 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6792 char *codepage = NULL;
6794 int want_name = *int_code_page;
6797 *int_code_page = -1;
6799 g_get_charset (&cset);
6800 c = codepage = strdup (cset);
6801 for (c = codepage; *c; c++){
6802 if (isascii (*c) && isalpha (*c))
6807 /* g_print ("charset: %s\n", cset); */
6809 /* handle some common aliases */
6812 for (i = 0; p != 0; ){
6815 p = encodings [++i];
6818 if (strcmp (p, codepage) == 0){
6819 *int_code_page = code;
6822 p = encodings [++i];
6825 if (strstr (codepage, "utf_8") != NULL)
6826 *int_code_page |= 0x10000000;
6829 if (want_name && *int_code_page == -1)
6830 return mono_string_new (mono_domain_get (), cset);
6835 ICALL_EXPORT MonoBoolean
6836 ves_icall_System_Environment_get_HasShutdownStarted (void)
6838 if (mono_runtime_is_shutting_down ())
6841 if (mono_domain_is_unloading (mono_domain_get ()))
6848 ves_icall_System_Environment_BroadcastSettingChange (void)
6851 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6856 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6862 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6863 MonoReflectionMethod *method,
6864 MonoArray *out_args)
6866 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6869 #ifndef DISABLE_REMOTING
6870 ICALL_EXPORT MonoBoolean
6871 ves_icall_IsTransparentProxy (MonoObject *proxy)
6876 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6882 ICALL_EXPORT MonoReflectionMethod *
6883 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6884 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6886 MonoReflectionMethod *ret = NULL;
6891 MonoMethod **vtable;
6892 MonoMethod *res = NULL;
6894 MONO_CHECK_ARG_NULL (rtype, NULL);
6895 MONO_CHECK_ARG_NULL (rmethod, NULL);
6897 method = rmethod->method;
6898 klass = mono_class_from_mono_type (rtype->type);
6899 mono_class_init_or_throw (klass);
6901 if (MONO_CLASS_IS_INTERFACE (klass))
6904 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6907 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6908 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6914 mono_class_setup_vtable (klass);
6915 vtable = klass->vtable;
6917 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6918 gboolean variance_used = FALSE;
6919 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6920 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6922 res = vtable [offs + method->slot];
6924 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6927 if (method->slot != -1)
6928 res = vtable [method->slot];
6934 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
6935 mono_error_raise_exception (&error);
6940 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6946 klass = mono_class_from_mono_type (type->type);
6947 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
6948 if (!is_ok (&error)) {
6949 mono_error_set_pending_exception (&error);
6953 mono_vtable_set_is_remote (vtable, enable);
6956 #else /* DISABLE_REMOTING */
6959 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6961 g_assert_not_reached ();
6966 ICALL_EXPORT MonoObject *
6967 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6974 domain = mono_object_domain (type);
6975 klass = mono_class_from_mono_type (type->type);
6976 mono_class_init_or_throw (klass);
6978 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
6979 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6983 if (klass->rank >= 1) {
6984 g_assert (klass->rank == 1);
6985 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6987 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
6988 if (!is_ok (&error)) {
6989 mono_error_set_pending_exception (&error);
6992 /* Bypass remoting object creation check */
6993 ret = mono_object_new_alloc_specific_checked (vtable, &error);
6994 mono_error_set_pending_exception (&error);
7000 ICALL_EXPORT MonoString *
7001 ves_icall_System_IO_get_temp_path (void)
7003 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7006 #ifndef PLATFORM_NO_DRIVEINFO
7007 ICALL_EXPORT MonoBoolean
7008 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7009 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7013 ULARGE_INTEGER wapi_free_bytes_avail;
7014 ULARGE_INTEGER wapi_total_number_of_bytes;
7015 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7017 *error = ERROR_SUCCESS;
7018 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7019 &wapi_total_number_of_free_bytes);
7022 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7023 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7024 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7026 *free_bytes_avail = 0;
7027 *total_number_of_bytes = 0;
7028 *total_number_of_free_bytes = 0;
7029 *error = GetLastError ();
7035 ICALL_EXPORT guint32
7036 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7038 return GetDriveType (mono_string_chars (root_path_name));
7042 ICALL_EXPORT gpointer
7043 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
7045 return mono_compile_method (method);
7048 ICALL_EXPORT MonoString *
7049 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7054 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7056 #if defined (HOST_WIN32)
7057 /* Avoid mixing '/' and '\\' */
7060 for (i = strlen (path) - 1; i >= 0; i--)
7061 if (path [i] == '/')
7065 mcpath = mono_string_new (mono_domain_get (), path);
7072 get_bundled_app_config (void)
7074 const gchar *app_config;
7077 gchar *config_file_name, *config_file_path;
7078 gsize len, config_file_path_length, config_ext_length;
7081 domain = mono_domain_get ();
7082 file = domain->setup->configuration_file;
7083 if (!file || file->length == 0)
7086 // Retrieve config file and remove the extension
7087 config_file_name = mono_string_to_utf8 (file);
7088 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7089 if (!config_file_path)
7090 config_file_path = config_file_name;
7092 config_file_path_length = strlen (config_file_path);
7093 config_ext_length = strlen (".config");
7094 if (config_file_path_length <= config_ext_length)
7097 len = config_file_path_length - config_ext_length;
7098 module = (gchar *)g_malloc0 (len + 1);
7099 memcpy (module, config_file_path, len);
7100 // Get the config file from the module name
7101 app_config = mono_config_string_for_assembly_file (module);
7104 if (config_file_name != config_file_path)
7105 g_free (config_file_name);
7106 g_free (config_file_path);
7111 return mono_string_new (mono_domain_get (), app_config);
7115 get_bundled_machine_config (void)
7117 const gchar *machine_config;
7119 machine_config = mono_get_machine_config ();
7121 if (!machine_config)
7124 return mono_string_new (mono_domain_get (), machine_config);
7127 ICALL_EXPORT MonoString *
7128 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7133 path = g_path_get_dirname (mono_get_config_dir ());
7135 #if defined (HOST_WIN32)
7136 /* Avoid mixing '/' and '\\' */
7139 for (i = strlen (path) - 1; i >= 0; i--)
7140 if (path [i] == '/')
7144 ipath = mono_string_new (mono_domain_get (), path);
7150 ICALL_EXPORT gboolean
7151 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7153 MonoPEResourceDataEntry *entry;
7156 if (!assembly || !result || !size)
7161 image = assembly->assembly->image;
7162 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7166 *result = mono_image_rva_map (image, entry->rde_data_offset);
7171 *size = entry->rde_size;
7176 ICALL_EXPORT MonoBoolean
7177 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7179 return mono_is_debugger_attached ();
7182 ICALL_EXPORT MonoBoolean
7183 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7185 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7186 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7192 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7194 if (mono_get_runtime_callbacks ()->debug_log)
7195 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7199 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7201 #if defined (HOST_WIN32)
7202 OutputDebugString (mono_string_chars (message));
7204 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7208 /* Only used for value types */
7209 ICALL_EXPORT MonoObject *
7210 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7217 domain = mono_object_domain (type);
7218 klass = mono_class_from_mono_type (type->type);
7219 mono_class_init_or_throw (klass);
7221 if (mono_class_is_nullable (klass))
7222 /* No arguments -> null */
7225 result = mono_object_new_checked (domain, klass, &error);
7226 mono_error_raise_exception (&error);
7230 ICALL_EXPORT MonoReflectionMethod *
7231 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7233 MonoReflectionMethod *ret = NULL;
7236 MonoClass *klass, *parent;
7237 MonoGenericContext *generic_inst = NULL;
7238 MonoMethod *method = m->method;
7239 MonoMethod *result = NULL;
7242 if (method->klass == NULL)
7245 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7246 MONO_CLASS_IS_INTERFACE (method->klass) ||
7247 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7250 slot = mono_method_get_vtable_slot (method);
7254 klass = method->klass;
7255 if (klass->generic_class) {
7256 generic_inst = mono_class_get_context (klass);
7257 klass = klass->generic_class->container_class;
7261 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7262 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7263 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7264 or klass is the generic container class and generic_inst is the instantiation.
7266 when we go to the parent, if the parent is an open constructed type, we need to
7267 replace the type parameters by the definitions from the generic_inst, and then take it
7268 apart again into the klass and the generic_inst.
7270 For cases like this:
7271 class C<T> : B<T, int> {
7272 public override void Foo () { ... }
7274 class B<U,V> : A<HashMap<U,V>> {
7275 public override void Foo () { ... }
7278 public virtual void Foo () { ... }
7281 if at each iteration the parent isn't open, we can skip inflating it. if at some
7282 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7285 MonoGenericContext *parent_inst = NULL;
7286 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7288 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7289 if (!mono_error_ok (&error)) {
7290 mono_error_set_pending_exception (&error);
7294 if (parent->generic_class) {
7295 parent_inst = mono_class_get_context (parent);
7296 parent = parent->generic_class->container_class;
7299 mono_class_setup_vtable (parent);
7300 if (parent->vtable_size <= slot)
7303 generic_inst = parent_inst;
7306 klass = klass->parent;
7309 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7310 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7311 if (!mono_error_ok (&error)) {
7312 mono_error_set_pending_exception (&error);
7316 generic_inst = NULL;
7318 if (klass->generic_class) {
7319 generic_inst = mono_class_get_context (klass);
7320 klass = klass->generic_class->container_class;
7326 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7327 if (!mono_error_ok (&error)) {
7328 mono_error_set_pending_exception (&error);
7333 if (klass == method->klass)
7336 /*This is possible if definition == FALSE.
7337 * Do it here to be really sure we don't read invalid memory.
7339 if (slot >= klass->vtable_size)
7342 mono_class_setup_vtable (klass);
7344 result = klass->vtable [slot];
7345 if (result == NULL) {
7346 /* It is an abstract method */
7347 gpointer iter = NULL;
7348 while ((result = mono_class_get_methods (klass, &iter)))
7349 if (result->slot == slot)
7356 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7357 mono_error_raise_exception (&error);
7361 ICALL_EXPORT MonoString*
7362 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7364 MonoMethod *method = m->method;
7366 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7371 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7373 iter->sig = *(MonoMethodSignature**)argsp;
7375 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7376 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7379 /* FIXME: it's not documented what start is exactly... */
7383 iter->args = argsp + sizeof (gpointer);
7385 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7387 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7390 ICALL_EXPORT MonoTypedRef
7391 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7393 guint32 i, arg_size;
7397 i = iter->sig->sentinelpos + iter->next_arg;
7399 g_assert (i < iter->sig->param_count);
7401 res.type = iter->sig->params [i];
7402 res.klass = mono_class_from_mono_type (res.type);
7403 arg_size = mono_type_stack_size (res.type, &align);
7404 #if defined(__arm__) || defined(__mips__)
7405 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7407 res.value = iter->args;
7408 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7409 /* Values are stored as 8 byte register sized objects, but 'value'
7410 * is dereferenced as a pointer in other routines.
7412 res.value = (char*)res.value + 4;
7414 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7415 if (arg_size <= sizeof (gpointer)) {
7417 int padding = arg_size - mono_type_size (res.type, &dummy);
7418 res.value = (guint8*)res.value + padding;
7421 iter->args = (char*)iter->args + arg_size;
7424 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7429 ICALL_EXPORT MonoTypedRef
7430 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7432 guint32 i, arg_size;
7436 i = iter->sig->sentinelpos + iter->next_arg;
7438 g_assert (i < iter->sig->param_count);
7440 while (i < iter->sig->param_count) {
7441 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7443 res.type = iter->sig->params [i];
7444 res.klass = mono_class_from_mono_type (res.type);
7445 /* FIXME: endianess issue... */
7446 arg_size = mono_type_stack_size (res.type, &align);
7447 #if defined(__arm__) || defined(__mips__)
7448 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7450 res.value = iter->args;
7451 iter->args = (char*)iter->args + arg_size;
7453 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7456 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7464 ICALL_EXPORT MonoType*
7465 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7469 i = iter->sig->sentinelpos + iter->next_arg;
7471 g_assert (i < iter->sig->param_count);
7473 return iter->sig->params [i];
7476 ICALL_EXPORT MonoObject*
7477 mono_TypedReference_ToObject (MonoTypedRef* tref)
7479 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7480 MonoObject** objp = (MonoObject **)tref->value;
7484 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
7487 ICALL_EXPORT MonoTypedRef
7488 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7491 MonoReflectionField *f;
7493 MonoType *ftype = NULL;
7497 memset (&res, 0, sizeof (res));
7500 g_assert (mono_array_length (fields) > 0);
7502 klass = target->vtable->klass;
7504 for (i = 0; i < mono_array_length (fields); ++i) {
7505 f = mono_array_get (fields, MonoReflectionField*, i);
7507 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7510 if (f->field->parent != klass) {
7511 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7515 p = (guint8*)target + f->field->offset;
7517 p += f->field->offset - sizeof (MonoObject);
7518 klass = mono_class_from_mono_type (f->field->type);
7519 ftype = f->field->type;
7523 res.klass = mono_class_from_mono_type (ftype);
7530 prelink_method (MonoMethod *method)
7532 const char *exc_class, *exc_arg;
7533 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7535 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7537 mono_raise_exception(
7538 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7540 /* create the wrapper, too? */
7544 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7546 prelink_method (method->method);
7550 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7552 MonoClass *klass = mono_class_from_mono_type (type->type);
7554 gpointer iter = NULL;
7556 mono_class_init_or_throw (klass);
7558 while ((m = mono_class_get_methods (klass, &iter)))
7562 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7564 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7565 gint32 const **exponents,
7566 gunichar2 const **digitLowerTable,
7567 gunichar2 const **digitUpperTable,
7568 gint64 const **tenPowersList,
7569 gint32 const **decHexDigits)
7571 *mantissas = Formatter_MantissaBitsTable;
7572 *exponents = Formatter_TensExponentTable;
7573 *digitLowerTable = Formatter_DigitLowerTable;
7574 *digitUpperTable = Formatter_DigitUpperTable;
7575 *tenPowersList = Formatter_TenPowersList;
7576 *decHexDigits = Formatter_DecHexDigits;
7580 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7581 * and avoid useless allocations.
7586 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7589 MonoReflectionType *rt;
7592 for (i = 0; i < type->num_mods; ++i) {
7593 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7598 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7600 for (i = 0; i < type->num_mods; ++i) {
7601 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7602 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
7603 mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */
7605 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, &error);
7606 mono_error_raise_exception (&error);
7608 mono_array_setref (res, count, rt);
7615 ICALL_EXPORT MonoArray*
7616 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7618 MonoType *type = param->ClassImpl->type;
7619 MonoClass *member_class = mono_object_class (param->MemberImpl);
7620 MonoMethod *method = NULL;
7623 MonoMethodSignature *sig;
7625 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7626 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7627 method = rmethod->method;
7628 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7629 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7630 if (!(method = prop->property->get))
7631 method = prop->property->set;
7634 char *type_name = mono_type_get_full_name (member_class);
7635 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7636 MonoException *ex = mono_get_exception_not_supported (msg);
7639 mono_set_pending_exception (ex);
7643 image = method->klass->image;
7644 pos = param->PositionImpl;
7645 sig = mono_method_signature (method);
7649 type = sig->params [pos];
7651 return type_array_from_modifiers (image, type, optional);
7655 get_property_type (MonoProperty *prop)
7657 MonoMethodSignature *sig;
7659 sig = mono_method_signature (prop->get);
7661 } else if (prop->set) {
7662 sig = mono_method_signature (prop->set);
7663 return sig->params [sig->param_count - 1];
7668 ICALL_EXPORT MonoArray*
7669 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7671 MonoType *type = get_property_type (property->property);
7672 MonoImage *image = property->klass->image;
7676 return type_array_from_modifiers (image, type, optional);
7680 *Construct a MonoType suited to be used to decode a constant blob object.
7682 * @type is the target type which will be constructed
7683 * @blob_type is the blob type, for example, that comes from the constant table
7684 * @real_type is the expected constructed type.
7687 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7689 type->type = blob_type;
7690 type->data.klass = NULL;
7691 if (blob_type == MONO_TYPE_CLASS)
7692 type->data.klass = mono_defaults.object_class;
7693 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7694 /* For enums, we need to use the base type */
7695 type->type = MONO_TYPE_VALUETYPE;
7696 type->data.klass = mono_class_from_mono_type (real_type);
7698 type->data.klass = mono_class_from_mono_type (real_type);
7701 ICALL_EXPORT MonoObject*
7702 property_info_get_default_value (MonoReflectionProperty *property)
7705 MonoProperty *prop = property->property;
7706 MonoType *type = get_property_type (prop);
7707 MonoDomain *domain = mono_object_domain (property);
7708 MonoTypeEnum def_type;
7709 const char *def_value;
7712 mono_class_init (prop->parent);
7714 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7715 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7719 def_value = mono_class_get_property_default_value (prop, &def_type);
7721 mono_type_from_blob_type (&blob_type, def_type, type);
7722 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7727 ICALL_EXPORT MonoBoolean
7728 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7731 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7732 MonoCustomAttrInfo *cinfo;
7735 mono_class_init_or_throw (attr_class);
7737 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7738 if (!is_ok (&error)) {
7739 mono_error_set_pending_exception (&error);
7744 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7746 mono_custom_attrs_free (cinfo);
7750 ICALL_EXPORT MonoArray*
7751 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7753 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7758 mono_class_init_or_throw (attr_class);
7760 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7761 if (!mono_error_ok (&error)) {
7762 mono_error_set_pending_exception (&error);
7766 if (mono_loader_get_last_error ()) {
7767 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7774 ICALL_EXPORT MonoArray*
7775 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7779 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7780 mono_error_set_pending_exception (&error);
7785 ICALL_EXPORT MonoString*
7786 ves_icall_Mono_Runtime_GetDisplayName (void)
7789 MonoString *display_name;
7791 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7792 display_name = mono_string_new (mono_domain_get (), info);
7794 return display_name;
7797 ICALL_EXPORT MonoString*
7798 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7801 MonoString *message;
7805 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7806 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7809 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7811 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7812 mono_error_raise_exception (&error);
7819 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7822 char *path_str = mono_string_to_utf8 (path);
7824 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7832 ICALL_EXPORT gpointer
7833 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
7835 return GetCurrentProcess ();
7838 ICALL_EXPORT MonoBoolean
7839 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
7841 return GetExitCodeProcess (handle, (guint32*) exitcode);
7844 ICALL_EXPORT MonoBoolean
7845 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
7847 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
7848 return CloseHandle (handle);
7850 return CloseProcess (handle);
7854 ICALL_EXPORT MonoBoolean
7855 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
7857 return TerminateProcess (handle, exitcode);
7861 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
7863 return WaitForInputIdle (handle, milliseconds);
7866 ICALL_EXPORT MonoBoolean
7867 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
7869 return GetProcessWorkingSetSize (handle, min, max);
7872 ICALL_EXPORT MonoBoolean
7873 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
7875 return SetProcessWorkingSetSize (handle, min, max);
7878 ICALL_EXPORT MonoBoolean
7879 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
7881 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
7885 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
7887 return mono_process_current_pid ();
7891 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
7893 return GetPriorityClass (handle);
7896 ICALL_EXPORT MonoBoolean
7897 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
7899 return SetPriorityClass (handle, priorityClass);
7902 #ifndef DISABLE_ICALL_TABLES
7904 #define ICALL_TYPE(id,name,first)
7905 #define ICALL(id,name,func) Icall_ ## id,
7908 #include "metadata/icall-def.h"
7914 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7915 #define ICALL(id,name,func)
7917 #include "metadata/icall-def.h"
7923 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7924 #define ICALL(id,name,func)
7926 guint16 first_icall;
7929 static const IcallTypeDesc
7930 icall_type_descs [] = {
7931 #include "metadata/icall-def.h"
7935 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7938 #define ICALL_TYPE(id,name,first)
7941 #ifdef HAVE_ARRAY_ELEM_INIT
7942 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7943 #define MSGSTRFIELD1(line) str##line
7945 static const struct msgstrtn_t {
7946 #define ICALL(id,name,func)
7948 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7949 #include "metadata/icall-def.h"
7951 } icall_type_names_str = {
7952 #define ICALL_TYPE(id,name,first) (name),
7953 #include "metadata/icall-def.h"
7956 static const guint16 icall_type_names_idx [] = {
7957 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7958 #include "metadata/icall-def.h"
7961 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7963 static const struct msgstr_t {
7965 #define ICALL_TYPE(id,name,first)
7966 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7967 #include "metadata/icall-def.h"
7969 } icall_names_str = {
7970 #define ICALL(id,name,func) (name),
7971 #include "metadata/icall-def.h"
7974 static const guint16 icall_names_idx [] = {
7975 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7976 #include "metadata/icall-def.h"
7979 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7985 #define ICALL_TYPE(id,name,first) name,
7986 #define ICALL(id,name,func)
7987 static const char* const
7988 icall_type_names [] = {
7989 #include "metadata/icall-def.h"
7993 #define icall_type_name_get(id) (icall_type_names [(id)])
7997 #define ICALL_TYPE(id,name,first)
7998 #define ICALL(id,name,func) name,
7999 static const char* const
8001 #include "metadata/icall-def.h"
8004 #define icall_name_get(id) icall_names [(id)]
8006 #endif /* !HAVE_ARRAY_ELEM_INIT */
8010 #define ICALL_TYPE(id,name,first)
8011 #define ICALL(id,name,func) func,
8012 static const gconstpointer
8013 icall_functions [] = {
8014 #include "metadata/icall-def.h"
8018 #ifdef ENABLE_ICALL_SYMBOL_MAP
8021 #define ICALL_TYPE(id,name,first)
8022 #define ICALL(id,name,func) #func,
8023 static const gconstpointer
8024 icall_symbols [] = {
8025 #include "metadata/icall-def.h"
8030 #endif /* DISABLE_ICALL_TABLES */
8032 static mono_mutex_t icall_mutex;
8033 static GHashTable *icall_hash = NULL;
8034 static GHashTable *jit_icall_hash_name = NULL;
8035 static GHashTable *jit_icall_hash_addr = NULL;
8038 mono_icall_init (void)
8040 #ifndef DISABLE_ICALL_TABLES
8043 /* check that tables are sorted: disable in release */
8046 const char *prev_class = NULL;
8047 const char *prev_method;
8049 for (i = 0; i < Icall_type_num; ++i) {
8050 const IcallTypeDesc *desc;
8053 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8054 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8055 prev_class = icall_type_name_get (i);
8056 desc = &icall_type_descs [i];
8057 num_icalls = icall_desc_num_icalls (desc);
8058 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8059 for (j = 0; j < num_icalls; ++j) {
8060 const char *methodn = icall_name_get (desc->first_icall + j);
8061 if (prev_method && strcmp (prev_method, methodn) >= 0)
8062 g_print ("method %s should come before method %s\n", methodn, prev_method);
8063 prev_method = methodn;
8069 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8070 mono_os_mutex_init (&icall_mutex);
8074 mono_icall_lock (void)
8076 mono_locks_os_acquire (&icall_mutex, IcallLock);
8080 mono_icall_unlock (void)
8082 mono_locks_os_release (&icall_mutex, IcallLock);
8086 mono_icall_cleanup (void)
8088 g_hash_table_destroy (icall_hash);
8089 g_hash_table_destroy (jit_icall_hash_name);
8090 g_hash_table_destroy (jit_icall_hash_addr);
8091 mono_os_mutex_destroy (&icall_mutex);
8095 * mono_add_internal_call:
8096 * @name: method specification to surface to the managed world
8097 * @method: pointer to a C method to invoke when the method is called
8099 * This method surfaces the C function pointed by @method as a method
8100 * that has been surfaced in managed code with the method specified in
8101 * @name as an internal call.
8103 * Internal calls are surfaced to all app domains loaded and they are
8104 * accessibly by a type with the specified name.
8106 * You must provide a fully qualified type name, that is namespaces
8107 * and type name, followed by a colon and the method name, with an
8108 * optional signature to bind.
8110 * For example, the following are all valid declarations:
8112 * "MyApp.Services.ScriptService:Accelerate"
8113 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8115 * You use method parameters in cases where there might be more than
8116 * one surface method to managed code. That way you can register different
8117 * internal calls for different method overloads.
8119 * The internal calls are invoked with no marshalling. This means that .NET
8120 * types like System.String are exposed as `MonoString *` parameters. This is
8121 * different than the way that strings are surfaced in P/Invoke.
8123 * For more information on how the parameters are marshalled, see the
8124 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8127 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8128 * reference for more information on the format of method descriptions.
8131 mono_add_internal_call (const char *name, gconstpointer method)
8135 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8137 mono_icall_unlock ();
8140 #ifndef DISABLE_ICALL_TABLES
8142 #ifdef HAVE_ARRAY_ELEM_INIT
8144 compare_method_imap (const void *key, const void *elem)
8146 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8147 return strcmp (key, method_name);
8151 find_method_icall (const IcallTypeDesc *imap, const char *name)
8153 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);
8156 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8160 compare_class_imap (const void *key, const void *elem)
8162 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8163 return strcmp (key, class_name);
8166 static const IcallTypeDesc*
8167 find_class_icalls (const char *name)
8169 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);
8172 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8175 #else /* HAVE_ARRAY_ELEM_INIT */
8178 compare_method_imap (const void *key, const void *elem)
8180 const char** method_name = (const char**)elem;
8181 return strcmp (key, *method_name);
8185 find_method_icall (const IcallTypeDesc *imap, const char *name)
8187 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8190 return (gpointer)icall_functions [(nameslot - icall_names)];
8194 compare_class_imap (const void *key, const void *elem)
8196 const char** class_name = (const char**)elem;
8197 return strcmp (key, *class_name);
8200 static const IcallTypeDesc*
8201 find_class_icalls (const char *name)
8203 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8206 return &icall_type_descs [nameslot - icall_type_names];
8209 #endif /* HAVE_ARRAY_ELEM_INIT */
8211 #endif /* DISABLE_ICALL_TABLES */
8214 * we should probably export this as an helper (handle nested types).
8215 * Returns the number of chars written in buf.
8218 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8220 int nspacelen, cnamelen;
8221 nspacelen = strlen (klass->name_space);
8222 cnamelen = strlen (klass->name);
8223 if (nspacelen + cnamelen + 2 > bufsize)
8226 memcpy (buf, klass->name_space, nspacelen);
8227 buf [nspacelen ++] = '.';
8229 memcpy (buf + nspacelen, klass->name, cnamelen);
8230 buf [nspacelen + cnamelen] = 0;
8231 return nspacelen + cnamelen;
8234 #ifdef DISABLE_ICALL_TABLES
8236 no_icall_table (void)
8238 g_assert_not_reached ();
8243 mono_lookup_internal_call (MonoMethod *method)
8248 int typelen = 0, mlen, siglen;
8250 #ifndef DISABLE_ICALL_TABLES
8251 const IcallTypeDesc *imap = NULL;
8254 g_assert (method != NULL);
8256 if (method->is_inflated)
8257 method = ((MonoMethodInflated *) method)->declaring;
8259 if (method->klass->nested_in) {
8260 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8264 mname [pos++] = '/';
8267 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8273 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8278 #ifndef DISABLE_ICALL_TABLES
8279 imap = find_class_icalls (mname);
8282 mname [typelen] = ':';
8283 mname [typelen + 1] = ':';
8285 mlen = strlen (method->name);
8286 memcpy (mname + typelen + 2, method->name, mlen);
8287 sigstart = mname + typelen + 2 + mlen;
8290 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8291 siglen = strlen (tmpsig);
8292 if (typelen + mlen + siglen + 6 > sizeof (mname))
8295 memcpy (sigstart + 1, tmpsig, siglen);
8296 sigstart [siglen + 1] = ')';
8297 sigstart [siglen + 2] = 0;
8302 res = g_hash_table_lookup (icall_hash, mname);
8304 mono_icall_unlock ();;
8307 /* try without signature */
8309 res = g_hash_table_lookup (icall_hash, mname);
8311 mono_icall_unlock ();
8315 #ifdef DISABLE_ICALL_TABLES
8316 mono_icall_unlock ();
8317 /* Fail only when the result is actually used */
8318 /* mono_marshal_get_native_wrapper () depends on this */
8319 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8320 return ves_icall_System_String_ctor_RedirectToCreateString;
8322 return no_icall_table;
8324 /* it wasn't found in the static call tables */
8326 mono_icall_unlock ();
8329 res = find_method_icall (imap, sigstart - mlen);
8331 mono_icall_unlock ();
8334 /* try _with_ signature */
8336 res = find_method_icall (imap, sigstart - mlen);
8338 mono_icall_unlock ();
8342 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8343 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8344 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8345 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8346 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");
8347 g_print ("If you see other errors or faults after this message they are probably related\n");
8348 g_print ("and you need to fix your mono install first.\n");
8350 mono_icall_unlock ();
8356 #ifdef ENABLE_ICALL_SYMBOL_MAP
8358 func_cmp (gconstpointer key, gconstpointer p)
8360 return (gsize)key - (gsize)*(gsize*)p;
8365 * mono_lookup_icall_symbol:
8367 * Given the icall METHOD, returns its C symbol.
8370 mono_lookup_icall_symbol (MonoMethod *m)
8372 #ifdef DISABLE_ICALL_TABLES
8373 g_assert_not_reached ();
8376 #ifdef ENABLE_ICALL_SYMBOL_MAP
8380 static gconstpointer *functions_sorted;
8381 static const char**symbols_sorted;
8382 static gboolean inited;
8387 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8388 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8389 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8390 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8391 /* Bubble sort the two arrays */
8395 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8396 if (functions_sorted [i] > functions_sorted [i + 1]) {
8399 tmp = functions_sorted [i];
8400 functions_sorted [i] = functions_sorted [i + 1];
8401 functions_sorted [i + 1] = tmp;
8402 tmp = symbols_sorted [i];
8403 symbols_sorted [i] = symbols_sorted [i + 1];
8404 symbols_sorted [i + 1] = tmp;
8411 func = mono_lookup_internal_call (m);
8414 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8418 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8420 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8421 g_assert_not_reached ();
8428 type_from_typename (char *type_name)
8430 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8432 if (!strcmp (type_name, "int"))
8433 klass = mono_defaults.int_class;
8434 else if (!strcmp (type_name, "ptr"))
8435 klass = mono_defaults.int_class;
8436 else if (!strcmp (type_name, "void"))
8437 klass = mono_defaults.void_class;
8438 else if (!strcmp (type_name, "int32"))
8439 klass = mono_defaults.int32_class;
8440 else if (!strcmp (type_name, "uint32"))
8441 klass = mono_defaults.uint32_class;
8442 else if (!strcmp (type_name, "int8"))
8443 klass = mono_defaults.sbyte_class;
8444 else if (!strcmp (type_name, "uint8"))
8445 klass = mono_defaults.byte_class;
8446 else if (!strcmp (type_name, "int16"))
8447 klass = mono_defaults.int16_class;
8448 else if (!strcmp (type_name, "uint16"))
8449 klass = mono_defaults.uint16_class;
8450 else if (!strcmp (type_name, "long"))
8451 klass = mono_defaults.int64_class;
8452 else if (!strcmp (type_name, "ulong"))
8453 klass = mono_defaults.uint64_class;
8454 else if (!strcmp (type_name, "float"))
8455 klass = mono_defaults.single_class;
8456 else if (!strcmp (type_name, "double"))
8457 klass = mono_defaults.double_class;
8458 else if (!strcmp (type_name, "object"))
8459 klass = mono_defaults.object_class;
8460 else if (!strcmp (type_name, "obj"))
8461 klass = mono_defaults.object_class;
8462 else if (!strcmp (type_name, "string"))
8463 klass = mono_defaults.string_class;
8464 else if (!strcmp (type_name, "bool"))
8465 klass = mono_defaults.boolean_class;
8466 else if (!strcmp (type_name, "boolean"))
8467 klass = mono_defaults.boolean_class;
8469 g_error ("%s", type_name);
8470 g_assert_not_reached ();
8472 return &klass->byval_arg;
8476 * LOCKING: Take the corlib image lock.
8478 MonoMethodSignature*
8479 mono_create_icall_signature (const char *sigstr)
8484 MonoMethodSignature *res, *res2;
8485 MonoImage *corlib = mono_defaults.corlib;
8487 mono_image_lock (corlib);
8488 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8489 mono_image_unlock (corlib);
8494 parts = g_strsplit (sigstr, " ", 256);
8503 res = mono_metadata_signature_alloc (corlib, len - 1);
8508 * Under windows, the default pinvoke calling convention is STDCALL but
8511 res->call_convention = MONO_CALL_C;
8514 res->ret = type_from_typename (parts [0]);
8515 for (i = 1; i < len; ++i) {
8516 res->params [i - 1] = type_from_typename (parts [i]);
8521 mono_image_lock (corlib);
8522 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8524 res = res2; /*Value is allocated in the image pool*/
8526 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8527 mono_image_unlock (corlib);
8533 mono_find_jit_icall_by_name (const char *name)
8535 MonoJitICallInfo *info;
8536 g_assert (jit_icall_hash_name);
8539 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8540 mono_icall_unlock ();
8545 mono_find_jit_icall_by_addr (gconstpointer addr)
8547 MonoJitICallInfo *info;
8548 g_assert (jit_icall_hash_addr);
8551 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8552 mono_icall_unlock ();
8558 * mono_get_jit_icall_info:
8560 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8561 * caller should access it while holding the icall lock.
8564 mono_get_jit_icall_info (void)
8566 return jit_icall_hash_name;
8570 * mono_lookup_jit_icall_symbol:
8572 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8575 mono_lookup_jit_icall_symbol (const char *name)
8577 MonoJitICallInfo *info;
8578 const char *res = NULL;
8581 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8583 res = info->c_symbol;
8584 mono_icall_unlock ();
8589 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8592 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8593 mono_icall_unlock ();
8597 * 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
8598 * icalls without wrappers in some cases.
8601 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8603 MonoJitICallInfo *info;
8610 if (!jit_icall_hash_name) {
8611 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8612 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8615 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8616 g_warning ("jit icall already defined \"%s\"\n", name);
8617 g_assert_not_reached ();
8620 info = g_new0 (MonoJitICallInfo, 1);
8625 info->c_symbol = c_symbol;
8626 info->no_raise = no_raise;
8629 info->wrapper = func;
8631 info->wrapper = NULL;
8634 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8635 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8637 mono_icall_unlock ();
8642 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8644 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);