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)
1732 MonoDomain *domain = mono_domain_get ();
1734 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1735 mono_error_set_pending_exception (&error);
1739 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1740 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1743 MonoDomain *domain = mono_domain_get ();
1744 MonoReflectionMarshalAsAttribute* res = NULL;
1745 MonoMarshalSpec **mspecs;
1748 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1749 mono_method_get_marshal_info (method, mspecs);
1752 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1753 if (!mono_error_ok (&error)) {
1754 mono_error_set_pending_exception (&error);
1759 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1761 mono_metadata_free_marshal_spec (mspecs [i]);
1768 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1770 MonoClass *parent = field->field->parent;
1771 if (!parent->size_inited)
1772 mono_class_init (parent);
1773 mono_class_setup_fields_locking (parent);
1775 return field->field->offset - sizeof (MonoObject);
1778 ICALL_EXPORT MonoReflectionType*
1779 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1782 MonoReflectionType *ret;
1785 parent = declaring? field->field->parent: field->klass;
1787 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1788 mono_error_raise_exception (&error);
1794 ICALL_EXPORT MonoObject *
1795 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1797 MonoClass *fklass = field->klass;
1798 MonoClassField *cf = field->field;
1799 MonoDomain *domain = mono_object_domain (field);
1801 if (fklass->image->assembly->ref_only) {
1802 mono_set_pending_exception (mono_get_exception_invalid_operation (
1803 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1807 if (mono_security_core_clr_enabled ())
1808 mono_security_core_clr_ensure_reflection_access_field (cf);
1810 return mono_field_get_value_object (domain, cf, obj);
1814 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1817 MonoClassField *cf = field->field;
1821 if (field->klass->image->assembly->ref_only) {
1822 mono_set_pending_exception (mono_get_exception_invalid_operation (
1823 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1827 if (mono_security_core_clr_enabled ())
1828 mono_security_core_clr_ensure_reflection_access_field (cf);
1830 type = mono_field_get_type_checked (cf, &error);
1831 if (!mono_error_ok (&error)) {
1832 mono_error_set_pending_exception (&error);
1836 v = (gchar *) value;
1838 switch (type->type) {
1841 case MONO_TYPE_BOOLEAN:
1844 case MONO_TYPE_CHAR:
1853 case MONO_TYPE_VALUETYPE:
1856 v += sizeof (MonoObject);
1858 case MONO_TYPE_STRING:
1859 case MONO_TYPE_OBJECT:
1860 case MONO_TYPE_CLASS:
1861 case MONO_TYPE_ARRAY:
1862 case MONO_TYPE_SZARRAY:
1865 case MONO_TYPE_GENERICINST: {
1866 MonoGenericClass *gclass = type->data.generic_class;
1867 g_assert (!gclass->context.class_inst->is_open);
1869 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1870 MonoClass *nklass = mono_class_from_mono_type (type);
1871 MonoObject *nullable;
1874 * Convert the boxed vtype into a Nullable structure.
1875 * This is complicated by the fact that Nullables have
1876 * a variable structure.
1878 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1879 if (!mono_error_ok (&error)) {
1880 mono_error_set_pending_exception (&error);
1884 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1886 v = (gchar *)mono_object_unbox (nullable);
1889 if (gclass->container_class->valuetype && (v != NULL))
1890 v += sizeof (MonoObject);
1894 g_error ("type 0x%x not handled in "
1895 "ves_icall_FieldInfo_SetValueInternal", type->type);
1900 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1901 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
1902 if (!is_ok (&error)) {
1903 mono_error_set_pending_exception (&error);
1906 if (!vtable->initialized) {
1907 if (!mono_runtime_class_init_full (vtable, &error)) {
1908 mono_error_set_pending_exception (&error);
1912 mono_field_static_set_value (vtable, cf, v);
1914 mono_field_set_value (obj, cf, v);
1919 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1928 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1929 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1933 if (MONO_TYPE_IS_REFERENCE (f->type))
1934 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1936 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1939 ICALL_EXPORT MonoObject *
1940 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1942 MonoObject *o = NULL;
1943 MonoClassField *field = rfield->field;
1945 MonoDomain *domain = mono_object_domain (rfield);
1947 MonoTypeEnum def_type;
1948 const char *def_value;
1952 mono_class_init (field->parent);
1954 t = mono_field_get_type_checked (field, &error);
1955 if (!mono_error_ok (&error)) {
1956 mono_error_set_pending_exception (&error);
1960 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
1961 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1965 if (image_is_dynamic (field->parent->image)) {
1966 MonoClass *klass = field->parent;
1967 int fidx = field - klass->fields;
1969 g_assert (fidx >= 0 && fidx < klass->field.count);
1970 g_assert (klass->ext);
1971 g_assert (klass->ext->field_def_values);
1972 def_type = klass->ext->field_def_values [fidx].def_type;
1973 def_value = klass->ext->field_def_values [fidx].data;
1974 if (def_type == MONO_TYPE_END) {
1975 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1979 def_value = mono_class_get_field_default_value (field, &def_type);
1980 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
1982 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1987 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1991 case MONO_TYPE_BOOLEAN:
1994 case MONO_TYPE_CHAR:
2002 case MONO_TYPE_R8: {
2005 /* boxed value type */
2006 t = g_new0 (MonoType, 1);
2008 klass = mono_class_from_mono_type (t);
2010 o = mono_object_new_checked (domain, klass, &error);
2011 if (!mono_error_ok (&error)) {
2012 mono_error_set_pending_exception (&error);
2015 v = ((gchar *) o) + sizeof (MonoObject);
2016 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2019 case MONO_TYPE_STRING:
2020 case MONO_TYPE_CLASS:
2021 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2024 g_assert_not_reached ();
2030 ICALL_EXPORT MonoReflectionType*
2031 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2034 MonoReflectionType *ret;
2037 type = mono_field_get_type_checked (ref_field->field, &error);
2038 if (!mono_error_ok (&error)) {
2039 mono_error_set_pending_exception (&error);
2043 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2044 if (!mono_error_ok (&error)) {
2045 mono_error_set_pending_exception (&error);
2052 /* From MonoProperty.cs */
2054 PInfo_Attributes = 1,
2055 PInfo_GetMethod = 1 << 1,
2056 PInfo_SetMethod = 1 << 2,
2057 PInfo_ReflectedType = 1 << 3,
2058 PInfo_DeclaringType = 1 << 4,
2063 ves_icall_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2066 MonoReflectionType *rt;
2067 MonoReflectionMethod *rm;
2068 MonoDomain *domain = mono_object_domain (property);
2069 const MonoProperty *pproperty = property->property;
2071 if ((req_info & PInfo_ReflectedType) != 0) {
2072 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2073 mono_error_raise_exception (&error);
2075 MONO_STRUCT_SETREF (info, parent, rt);
2077 if ((req_info & PInfo_DeclaringType) != 0) {
2078 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2079 mono_error_raise_exception (&error);
2081 MONO_STRUCT_SETREF (info, declaring_type, rt);
2084 if ((req_info & PInfo_Name) != 0)
2085 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2087 if ((req_info & PInfo_Attributes) != 0)
2088 info->attrs = pproperty->attrs;
2090 if ((req_info & PInfo_GetMethod) != 0) {
2091 if (pproperty->get &&
2092 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2093 pproperty->get->klass == property->klass)) {
2094 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2095 mono_error_raise_exception (&error);
2100 MONO_STRUCT_SETREF (info, get, rm);
2102 if ((req_info & PInfo_SetMethod) != 0) {
2103 if (pproperty->set &&
2104 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2105 pproperty->set->klass == property->klass)) {
2106 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2107 mono_error_raise_exception (&error);
2112 MONO_STRUCT_SETREF (info, set, rm);
2115 * There may be other methods defined for properties, though, it seems they are not exposed
2116 * in the reflection API
2121 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2124 MonoReflectionType *rt;
2125 MonoReflectionMethod *rm;
2126 MonoDomain *domain = mono_object_domain (event);
2128 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2129 mono_error_raise_exception (&error);
2131 MONO_STRUCT_SETREF (info, reflected_type, rt);
2133 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2134 mono_error_raise_exception (&error);
2136 MONO_STRUCT_SETREF (info, declaring_type, rt);
2138 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2139 info->attrs = event->event->attrs;
2141 if (event->event->add) {
2142 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2143 mono_error_raise_exception (&error);
2148 MONO_STRUCT_SETREF (info, add_method, rm);
2150 if (event->event->remove) {
2151 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2152 mono_error_raise_exception (&error);
2157 MONO_STRUCT_SETREF (info, remove_method, rm);
2159 if (event->event->raise) {
2160 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2161 mono_error_raise_exception (&error);
2166 MONO_STRUCT_SETREF (info, raise_method, rm);
2168 #ifndef MONO_SMALL_CONFIG
2169 if (event->event->other) {
2171 while (event->event->other [n])
2173 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2175 for (i = 0; i < n; i++) {
2176 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2177 mono_error_raise_exception (&error);
2178 mono_array_setref (info->other_methods, i, rm);
2185 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2190 mono_class_setup_interfaces (klass, error);
2191 if (!mono_error_ok (error))
2194 for (i = 0; i < klass->interface_count; i++) {
2195 ic = klass->interfaces [i];
2196 g_hash_table_insert (ifaces, ic, ic);
2198 collect_interfaces (ic, ifaces, error);
2199 if (!mono_error_ok (error))
2205 MonoArray *iface_array;
2206 MonoGenericContext *context;
2210 } FillIfaceArrayData;
2213 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2215 MonoReflectionType *rt;
2216 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2217 MonoClass *ic = (MonoClass *)key;
2218 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2220 if (!mono_error_ok (data->error))
2223 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2224 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2225 if (!mono_error_ok (data->error))
2229 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2230 if (!mono_error_ok (data->error))
2233 mono_array_setref (data->iface_array, data->next_idx++, rt);
2236 mono_metadata_free_type (inflated);
2240 get_interfaces_hash (gconstpointer v1)
2242 MonoClass *k = (MonoClass*)v1;
2244 return k->type_token;
2247 ICALL_EXPORT MonoArray*
2248 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2251 MonoClass *klass = mono_class_from_mono_type (type->type);
2253 FillIfaceArrayData data = { 0 };
2256 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2258 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2259 data.context = mono_class_get_context (klass);
2260 klass = klass->generic_class->container_class;
2263 for (parent = klass; parent; parent = parent->parent) {
2264 mono_class_setup_interfaces (parent, &error);
2265 if (!mono_error_ok (&error))
2267 collect_interfaces (parent, iface_hash, &error);
2268 if (!mono_error_ok (&error))
2272 data.error = &error;
2273 data.domain = mono_object_domain (type);
2275 len = g_hash_table_size (iface_hash);
2277 g_hash_table_destroy (iface_hash);
2278 if (!data.domain->empty_types)
2279 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2280 return data.domain->empty_types;
2283 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2284 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2285 if (!mono_error_ok (&error))
2288 g_hash_table_destroy (iface_hash);
2289 return data.iface_array;
2292 g_hash_table_destroy (iface_hash);
2293 mono_error_set_pending_exception (&error);
2298 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2300 gboolean variance_used;
2301 MonoClass *klass = mono_class_from_mono_type (type->type);
2302 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2303 MonoReflectionMethod *member;
2306 int i = 0, len, ioffset;
2310 mono_class_init_or_throw (klass);
2311 mono_class_init_or_throw (iclass);
2313 mono_class_setup_vtable (klass);
2315 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2319 len = mono_class_num_methods (iclass);
2320 domain = mono_object_domain (type);
2321 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2322 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2324 while ((method = mono_class_get_methods (iclass, &iter))) {
2325 member = mono_method_get_object_checked (domain, method, iclass, &error);
2326 mono_error_raise_exception (&error);
2327 mono_array_setref (*methods, i, member);
2328 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2329 mono_error_raise_exception (&error);
2330 mono_array_setref (*targets, i, member);
2337 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2339 MonoClass *klass = mono_class_from_mono_type (type->type);
2340 mono_class_init_or_throw (klass);
2342 if (image_is_dynamic (klass->image)) {
2343 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2344 *packing = tb->packing_size;
2345 *size = tb->class_size;
2347 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2351 ICALL_EXPORT MonoReflectionType*
2352 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2355 MonoReflectionType *ret;
2358 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2359 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2360 mono_error_raise_exception (&error);
2365 klass = mono_class_from_mono_type (type->type);
2366 mono_class_init_or_throw (klass);
2368 // GetElementType should only return a type for:
2369 // Array Pointer PassedByRef
2370 if (type->type->byref)
2371 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2372 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2373 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2374 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2375 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2379 mono_error_raise_exception (&error);
2384 ICALL_EXPORT MonoReflectionType*
2385 ves_icall_get_type_parent (MonoReflectionType *type)
2388 MonoReflectionType *ret;
2390 if (type->type->byref)
2393 MonoClass *klass = mono_class_from_mono_type (type->type);
2397 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2398 mono_error_raise_exception (&error);
2403 ICALL_EXPORT MonoBoolean
2404 ves_icall_type_ispointer (MonoReflectionType *type)
2406 return type->type->type == MONO_TYPE_PTR;
2409 ICALL_EXPORT MonoBoolean
2410 ves_icall_type_isprimitive (MonoReflectionType *type)
2412 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)));
2415 ICALL_EXPORT MonoBoolean
2416 ves_icall_type_isbyref (MonoReflectionType *type)
2418 return type->type->byref;
2421 ICALL_EXPORT MonoBoolean
2422 ves_icall_type_iscomobject (MonoReflectionType *type)
2424 MonoClass *klass = mono_class_from_mono_type (type->type);
2425 mono_class_init_or_throw (klass);
2427 return mono_class_is_com_object (klass);
2430 ICALL_EXPORT MonoReflectionModule*
2431 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2434 MonoReflectionModule *result = NULL;
2435 MonoClass *klass = mono_class_from_mono_type (type->type);
2436 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2437 if (!mono_error_ok (&error))
2438 mono_error_set_pending_exception (&error);
2442 ICALL_EXPORT MonoReflectionAssembly*
2443 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2446 MonoDomain *domain = mono_domain_get ();
2447 MonoClass *klass = mono_class_from_mono_type (type->type);
2448 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2450 mono_error_set_pending_exception (&error);
2454 ICALL_EXPORT MonoReflectionType*
2455 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2458 MonoReflectionType *ret;
2459 MonoDomain *domain = mono_domain_get ();
2462 if (type->type->byref)
2464 if (type->type->type == MONO_TYPE_VAR) {
2465 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2466 klass = param ? param->owner.klass : NULL;
2467 } else if (type->type->type == MONO_TYPE_MVAR) {
2468 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2469 klass = param ? param->owner.method->klass : NULL;
2471 klass = mono_class_from_mono_type (type->type)->nested_in;
2477 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2478 mono_error_raise_exception (&error);
2483 ICALL_EXPORT MonoString*
2484 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2486 MonoDomain *domain = mono_domain_get ();
2487 MonoClass *klass = mono_class_from_mono_type (type->type);
2489 if (type->type->byref) {
2490 char *n = g_strdup_printf ("%s&", klass->name);
2491 MonoString *res = mono_string_new (domain, n);
2497 return mono_string_new (domain, klass->name);
2501 ICALL_EXPORT MonoString*
2502 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2504 MonoDomain *domain = mono_domain_get ();
2505 MonoClass *klass = mono_class_from_mono_type (type->type);
2507 while (klass->nested_in)
2508 klass = klass->nested_in;
2510 if (klass->name_space [0] == '\0')
2513 return mono_string_new (domain, klass->name_space);
2517 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2521 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2522 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2526 klass = mono_class_from_mono_type (type->type);
2532 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2535 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2539 ICALL_EXPORT MonoArray*
2540 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2543 MonoReflectionType *rt;
2545 MonoClass *klass, *pklass;
2546 MonoDomain *domain = mono_object_domain (type);
2549 klass = mono_class_from_mono_type (type->type);
2551 if (klass->generic_container) {
2552 MonoGenericContainer *container = klass->generic_container;
2553 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2554 for (i = 0; i < container->type_argc; ++i) {
2555 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2557 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2558 mono_error_raise_exception (&error);
2560 mono_array_setref (res, i, rt);
2562 } else if (klass->generic_class) {
2563 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2564 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2565 for (i = 0; i < inst->type_argc; ++i) {
2566 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2567 mono_error_raise_exception (&error);
2569 mono_array_setref (res, i, rt);
2577 ICALL_EXPORT gboolean
2578 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2582 if (!IS_MONOTYPE (type))
2585 if (type->type->byref)
2588 klass = mono_class_from_mono_type (type->type);
2589 return klass->generic_container != NULL;
2592 ICALL_EXPORT MonoReflectionType*
2593 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2596 MonoReflectionType *ret;
2599 if (type->type->byref)
2602 klass = mono_class_from_mono_type (type->type);
2604 if (klass->generic_container) {
2605 return type; /* check this one */
2607 if (klass->generic_class) {
2608 MonoClass *generic_class = klass->generic_class->container_class;
2611 tb = mono_class_get_ref_info (generic_class);
2613 if (generic_class->wastypebuilder && tb)
2614 return (MonoReflectionType *)tb;
2616 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2617 mono_error_raise_exception (&error);
2625 ICALL_EXPORT MonoReflectionType*
2626 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2629 MonoReflectionType *ret;
2631 MonoType *geninst, **types;
2634 g_assert (IS_MONOTYPE (type));
2635 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2637 count = mono_array_length (type_array);
2638 types = g_new0 (MonoType *, count);
2640 for (i = 0; i < count; i++) {
2641 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2642 types [i] = t->type;
2645 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2650 klass = mono_class_from_mono_type (geninst);
2652 /*we might inflate to the GTD*/
2653 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2654 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2658 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2659 mono_error_raise_exception (&error);
2664 ICALL_EXPORT gboolean
2665 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2669 if (!IS_MONOTYPE (type))
2672 if (type->type->byref)
2675 klass = mono_class_from_mono_type (type->type);
2676 return klass->generic_class != NULL || klass->generic_container != NULL;
2680 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2682 if (!IS_MONOTYPE (type))
2685 if (is_generic_parameter (type->type))
2686 return mono_type_get_generic_param_num (type->type);
2690 ICALL_EXPORT GenericParameterAttributes
2691 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2693 g_assert (IS_MONOTYPE (type));
2694 g_assert (is_generic_parameter (type->type));
2695 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2698 ICALL_EXPORT MonoArray *
2699 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2702 MonoReflectionType *rt;
2703 MonoGenericParamInfo *param_info;
2709 g_assert (IS_MONOTYPE (type));
2711 domain = mono_object_domain (type);
2712 param_info = mono_generic_param_info (type->type->data.generic_param);
2713 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2716 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2717 for (i = 0; i < count; i++) {
2718 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2719 mono_error_raise_exception (&error);
2721 mono_array_setref (res, i, rt);
2728 ICALL_EXPORT MonoBoolean
2729 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2731 return is_generic_parameter (type->type);
2734 ICALL_EXPORT MonoBoolean
2735 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2737 return is_generic_parameter (tb->type.type);
2741 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2742 MonoReflectionType *t)
2744 enumtype->type = t->type;
2747 ICALL_EXPORT MonoReflectionMethod*
2748 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2749 MonoReflectionMethod* generic)
2756 MonoReflectionMethod *ret = NULL;
2758 domain = ((MonoObject *)type)->vtable->domain;
2760 klass = mono_class_from_mono_type (type->type);
2761 mono_class_init_or_throw (klass);
2764 while ((method = mono_class_get_methods (klass, &iter))) {
2765 if (method->token == generic->method->token) {
2766 ret = mono_method_get_object_checked (domain, method, klass, &error);
2767 mono_error_raise_exception (&error);
2774 ICALL_EXPORT MonoReflectionMethod *
2775 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2778 MonoType *type = ref_type->type;
2780 MonoReflectionMethod *ret = NULL;
2782 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2783 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2786 if (type->type == MONO_TYPE_VAR)
2789 method = mono_type_get_generic_param_owner (type)->owner.method;
2792 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2793 if (!mono_error_ok (&error))
2794 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2798 ICALL_EXPORT MonoBoolean
2799 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2801 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2805 ICALL_EXPORT MonoBoolean
2806 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2808 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2813 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2815 MonoDomain *domain = mono_domain_get ();
2816 MonoImage *image = method->method->klass->image;
2817 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2818 MonoTableInfo *tables = image->tables;
2819 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2820 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2821 guint32 im_cols [MONO_IMPLMAP_SIZE];
2822 guint32 scope_token;
2823 const char *import = NULL;
2824 const char *scope = NULL;
2826 if (image_is_dynamic (image)) {
2827 MonoReflectionMethodAux *method_aux =
2828 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2830 import = method_aux->dllentry;
2831 scope = method_aux->dll;
2834 if (!import || !scope) {
2835 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2840 if (piinfo->implmap_idx) {
2841 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2843 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2844 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2845 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2846 scope = mono_metadata_string_heap (image, scope_token);
2850 *flags = piinfo->piflags;
2851 *entry_point = mono_string_new (domain, import);
2852 *dll_name = mono_string_new (domain, scope);
2855 ICALL_EXPORT MonoReflectionMethod *
2856 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2858 MonoMethodInflated *imethod;
2860 MonoReflectionMethod *ret = NULL;
2863 if (method->method->is_generic)
2866 if (!method->method->is_inflated)
2869 imethod = (MonoMethodInflated *) method->method;
2871 result = imethod->declaring;
2872 /* Not a generic method. */
2873 if (!result->is_generic)
2876 if (image_is_dynamic (method->method->klass->image)) {
2877 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2878 MonoReflectionMethod *res;
2881 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2882 * the dynamic case as well ?
2884 mono_image_lock ((MonoImage*)image);
2885 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2886 mono_image_unlock ((MonoImage*)image);
2892 if (imethod->context.class_inst) {
2893 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2894 /*Generic methods gets the context of the GTD.*/
2895 if (mono_class_get_context (klass)) {
2896 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2897 if (!mono_error_ok (&error))
2902 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2904 if (!mono_error_ok (&error))
2905 mono_error_set_pending_exception (&error);
2909 ICALL_EXPORT gboolean
2910 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2912 return mono_method_signature (method->method)->generic_param_count != 0;
2915 ICALL_EXPORT gboolean
2916 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2918 return method->method->is_generic;
2921 ICALL_EXPORT MonoArray*
2922 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2925 MonoReflectionType *rt;
2930 domain = mono_object_domain (method);
2932 if (method->method->is_inflated) {
2933 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2936 count = inst->type_argc;
2937 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2939 for (i = 0; i < count; i++) {
2940 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2941 mono_error_raise_exception (&error);
2943 mono_array_setref (res, i, rt);
2950 count = mono_method_signature (method->method)->generic_param_count;
2951 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2953 for (i = 0; i < count; i++) {
2954 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2955 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2956 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
2958 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2959 mono_error_raise_exception (&error);
2961 mono_array_setref (res, i, rt);
2967 ICALL_EXPORT MonoObject *
2968 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
2972 * Invoke from reflection is supposed to always be a virtual call (the API
2973 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2974 * greater flexibility.
2976 MonoMethod *m = method->method;
2977 MonoMethodSignature *sig = mono_method_signature (m);
2980 void *obj = this_arg;
2984 if (mono_security_core_clr_enabled ())
2985 mono_security_core_clr_ensure_reflection_access_method (m);
2987 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2988 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
2989 mono_error_cleanup (&error); /* FIXME does this make sense? */
2990 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2995 if (!mono_object_isinst (this_arg, m->klass)) {
2996 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
2997 char *target_name = mono_type_get_full_name (m->klass);
2998 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2999 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3001 g_free (target_name);
3005 m = mono_object_get_virtual_method (this_arg, m);
3006 /* must pass the pointer to the value for valuetype methods */
3007 if (m->klass->valuetype)
3008 obj = mono_object_unbox (this_arg);
3009 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3010 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3015 if (sig->ret->byref) {
3016 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"));
3020 pcount = params? mono_array_length (params): 0;
3021 if (pcount != sig->param_count) {
3022 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3026 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3027 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."));
3031 image = m->klass->image;
3032 if (image->assembly->ref_only) {
3033 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."));
3037 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3038 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3042 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3046 intptr_t *lower_bounds;
3047 pcount = mono_array_length (params);
3048 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3049 /* Note: the synthetized array .ctors have int32 as argument type */
3050 for (i = 0; i < pcount; ++i)
3051 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3053 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3054 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3055 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3056 if (!mono_error_ok (&error)) {
3057 mono_error_set_pending_exception (&error);
3061 for (i = 0; i < mono_array_length (arr); ++i) {
3062 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3063 if (!mono_error_ok (&error)) {
3064 mono_error_set_pending_exception (&error);
3067 mono_array_setref_fast (arr, i, subarray);
3069 return (MonoObject*)arr;
3072 if (m->klass->rank == pcount) {
3073 /* Only lengths provided. */
3074 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3075 if (!mono_error_ok (&error)) {
3076 mono_error_set_pending_exception (&error);
3080 return (MonoObject*)arr;
3082 g_assert (pcount == (m->klass->rank * 2));
3083 /* The arguments are lower-bound-length pairs */
3084 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3086 for (i = 0; i < pcount / 2; ++i) {
3087 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3088 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3091 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3092 if (!mono_error_ok (&error)) {
3093 mono_error_set_pending_exception (&error);
3097 return (MonoObject*)arr;
3100 return mono_runtime_invoke_array (m, obj, params, NULL);
3103 #ifndef DISABLE_REMOTING
3104 ICALL_EXPORT MonoObject *
3105 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3107 MonoDomain *domain = mono_object_domain (method);
3108 MonoMethod *m = method->method;
3109 MonoMethodSignature *sig = mono_method_signature (m);
3110 MonoArray *out_args;
3112 int i, j, outarg_count = 0;
3114 if (m->klass == mono_defaults.object_class) {
3115 if (!strcmp (m->name, "FieldGetter")) {
3116 MonoClass *k = this_arg->vtable->klass;
3120 /* If this is a proxy, then it must be a CBO */
3121 if (k == mono_defaults.transparent_proxy_class) {
3122 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3123 this_arg = tp->rp->unwrapped_server;
3124 g_assert (this_arg);
3125 k = this_arg->vtable->klass;
3128 name = mono_array_get (params, MonoString *, 1);
3129 str = mono_string_to_utf8 (name);
3132 MonoClassField* field = mono_class_get_field_from_name (k, str);
3134 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3135 if (field_klass->valuetype)
3136 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
3138 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3140 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3141 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3142 mono_array_setref (out_args, 0, result);
3150 g_assert_not_reached ();
3152 } else if (!strcmp (m->name, "FieldSetter")) {
3153 MonoClass *k = this_arg->vtable->klass;
3159 /* If this is a proxy, then it must be a CBO */
3160 if (k == mono_defaults.transparent_proxy_class) {
3161 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3162 this_arg = tp->rp->unwrapped_server;
3163 g_assert (this_arg);
3164 k = this_arg->vtable->klass;
3167 name = mono_array_get (params, MonoString *, 1);
3168 str = mono_string_to_utf8 (name);
3171 MonoClassField* field = mono_class_get_field_from_name (k, str);
3173 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3174 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3176 if (field_klass->valuetype) {
3177 size = mono_type_size (field->type, &align);
3178 g_assert (size == mono_class_value_size (field_klass, NULL));
3179 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3181 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3184 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3185 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3195 g_assert_not_reached ();
3200 for (i = 0; i < mono_array_length (params); i++) {
3201 if (sig->params [i]->byref)
3205 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3207 /* handle constructors only for objects already allocated */
3208 if (!strcmp (method->method->name, ".ctor"))
3209 g_assert (this_arg);
3211 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3212 g_assert (!method->method->klass->valuetype);
3213 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3215 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3216 if (sig->params [i]->byref) {
3218 arg = mono_array_get (params, gpointer, i);
3219 mono_array_setref (out_args, j, arg);
3224 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3231 read_enum_value (const char *mem, int type)
3234 case MONO_TYPE_BOOLEAN:
3236 return *(guint8*)mem;
3238 return *(gint8*)mem;
3239 case MONO_TYPE_CHAR:
3241 return read16 (mem);
3243 return (gint16) read16 (mem);
3245 return read32 (mem);
3247 return (gint32) read32 (mem);
3250 return read64 (mem);
3252 g_assert_not_reached ();
3258 write_enum_value (char *mem, int type, guint64 value)
3262 case MONO_TYPE_I1: {
3263 guint8 *p = (guint8*)mem;
3268 case MONO_TYPE_I2: {
3269 guint16 *p = (guint16 *)mem;
3274 case MONO_TYPE_I4: {
3275 guint32 *p = (guint32 *)mem;
3280 case MONO_TYPE_I8: {
3281 guint64 *p = (guint64 *)mem;
3286 g_assert_not_reached ();
3291 ICALL_EXPORT MonoObject *
3292 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3300 domain = mono_object_domain (enumType);
3301 enumc = mono_class_from_mono_type (enumType->type);
3303 mono_class_init_or_throw (enumc);
3305 etype = mono_class_enum_basetype (enumc);
3307 res = mono_object_new_checked (domain, enumc, &error);
3308 mono_error_raise_exception (&error);
3309 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3314 ICALL_EXPORT MonoBoolean
3315 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3317 int size = mono_class_value_size (a->vtable->klass, NULL);
3318 guint64 a_val = 0, b_val = 0;
3320 memcpy (&a_val, mono_object_unbox (a), size);
3321 memcpy (&b_val, mono_object_unbox (b), size);
3323 return (a_val & b_val) == b_val;
3326 ICALL_EXPORT MonoObject *
3327 ves_icall_System_Enum_get_value (MonoObject *eobj)
3339 g_assert (eobj->vtable->klass->enumtype);
3341 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3342 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3343 mono_error_raise_exception (&error);
3344 dst = (char *)res + sizeof (MonoObject);
3345 src = (char *)eobj + sizeof (MonoObject);
3346 size = mono_class_value_size (enumc, NULL);
3348 memcpy (dst, src, size);
3353 ICALL_EXPORT MonoReflectionType *
3354 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3357 MonoReflectionType *ret;
3361 klass = mono_class_from_mono_type (type->type);
3362 mono_class_init_or_throw (klass);
3364 etype = mono_class_enum_basetype (klass);
3366 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3370 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3371 mono_error_raise_exception (&error);
3377 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3379 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3380 gpointer odata = (char *)other + sizeof (MonoObject);
3381 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3382 g_assert (basetype);
3387 if (eobj->vtable->klass != other->vtable->klass)
3390 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3391 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3392 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3395 return me > other ? 1 : -1; \
3398 switch (basetype->type) {
3400 COMPARE_ENUM_VALUES (guint8);
3402 COMPARE_ENUM_VALUES (gint8);
3403 case MONO_TYPE_CHAR:
3405 COMPARE_ENUM_VALUES (guint16);
3407 COMPARE_ENUM_VALUES (gint16);
3409 COMPARE_ENUM_VALUES (guint32);
3411 COMPARE_ENUM_VALUES (gint32);
3413 COMPARE_ENUM_VALUES (guint64);
3415 COMPARE_ENUM_VALUES (gint64);
3419 #undef COMPARE_ENUM_VALUES
3420 /* indicates that the enum was of an unsupported unerlying type */
3425 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3427 gpointer data = (char *)eobj + sizeof (MonoObject);
3428 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3429 g_assert (basetype);
3431 switch (basetype->type) {
3432 case MONO_TYPE_I1: {
3433 gint8 value = *((gint8*)data);
3434 return ((int)value ^ (int)value << 8);
3437 return *((guint8*)data);
3438 case MONO_TYPE_CHAR:
3440 return *((guint16*)data);
3442 case MONO_TYPE_I2: {
3443 gint16 value = *((gint16*)data);
3444 return ((int)(guint16)value | (((int)value) << 16));
3447 return *((guint32*)data);
3449 return *((gint32*)data);
3451 case MONO_TYPE_I8: {
3452 gint64 value = *((gint64*)data);
3453 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3456 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3461 ICALL_EXPORT MonoBoolean
3462 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3464 MonoDomain *domain = mono_object_domain (type);
3465 MonoClass *enumc = mono_class_from_mono_type (type->type);
3466 guint j = 0, nvalues;
3468 MonoClassField *field;
3470 guint64 field_value, previous_value = 0;
3471 gboolean sorted = TRUE;
3473 mono_class_init_or_throw (enumc);
3475 if (!enumc->enumtype) {
3476 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3480 base_type = mono_class_enum_basetype (enumc)->type;
3482 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3483 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3484 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3487 while ((field = mono_class_get_fields (enumc, &iter))) {
3489 MonoTypeEnum def_type;
3491 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3493 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3495 if (mono_field_is_deleted (field))
3497 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3499 p = mono_class_get_field_default_value (field, &def_type);
3500 /* len = */ mono_metadata_decode_blob_size (p, &p);
3502 field_value = read_enum_value (p, base_type);
3503 mono_array_set (*values, guint64, j, field_value);
3505 if (previous_value > field_value)
3508 previous_value = field_value;
3516 BFLAGS_IgnoreCase = 1,
3517 BFLAGS_DeclaredOnly = 2,
3518 BFLAGS_Instance = 4,
3520 BFLAGS_Public = 0x10,
3521 BFLAGS_NonPublic = 0x20,
3522 BFLAGS_FlattenHierarchy = 0x40,
3523 BFLAGS_InvokeMethod = 0x100,
3524 BFLAGS_CreateInstance = 0x200,
3525 BFLAGS_GetField = 0x400,
3526 BFLAGS_SetField = 0x800,
3527 BFLAGS_GetProperty = 0x1000,
3528 BFLAGS_SetProperty = 0x2000,
3529 BFLAGS_ExactBinding = 0x10000,
3530 BFLAGS_SuppressChangeType = 0x20000,
3531 BFLAGS_OptionalParamBinding = 0x40000
3534 ICALL_EXPORT MonoArray*
3535 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3539 MonoClass *startklass, *klass, *refklass;
3544 char *utf8_name = NULL;
3545 int (*compare_func) (const char *s1, const char *s2) = NULL;
3546 MonoClassField *field;
3547 MonoPtrArray tmp_array;
3549 domain = ((MonoObject *)type)->vtable->domain;
3550 if (type->type->byref)
3551 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3553 klass = startklass = mono_class_from_mono_type (type->type);
3554 refklass = mono_class_from_mono_type (reftype->type);
3556 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3559 if (mono_class_has_failure (klass)) {
3560 mono_ptr_array_destroy (tmp_array);
3561 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3566 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3567 guint32 flags = mono_field_get_flags (field);
3569 if (mono_field_is_deleted_with_flags (field, flags))
3571 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3572 if (bflags & BFLAGS_Public)
3574 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3575 if (bflags & BFLAGS_NonPublic) {
3582 if (flags & FIELD_ATTRIBUTE_STATIC) {
3583 if (bflags & BFLAGS_Static)
3584 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3587 if (bflags & BFLAGS_Instance)
3595 if (utf8_name == NULL) {
3596 utf8_name = mono_string_to_utf8 (name);
3597 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3600 if (compare_func (mono_field_get_name (field), utf8_name))
3604 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3605 if (!mono_error_ok (&error))
3607 mono_ptr_array_append (tmp_array, member);
3609 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3612 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3614 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3615 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3617 mono_ptr_array_destroy (tmp_array);
3619 if (utf8_name != NULL)
3624 mono_ptr_array_destroy (tmp_array);
3625 mono_error_raise_exception (&error);
3626 g_assert_not_reached ();
3630 method_nonpublic (MonoMethod* method, gboolean start_klass)
3632 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3633 case METHOD_ATTRIBUTE_ASSEM:
3634 return (start_klass || mono_defaults.generic_ilist_class);
3635 case METHOD_ATTRIBUTE_PRIVATE:
3637 case METHOD_ATTRIBUTE_PUBLIC:
3645 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3648 MonoClass *startklass;
3652 /*FIXME, use MonoBitSet*/
3653 guint32 method_slots_default [8];
3654 guint32 *method_slots = NULL;
3655 int (*compare_func) (const char *s1, const char *s2) = NULL;
3657 array = g_ptr_array_new ();
3662 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3664 /* An optimization for calls made from Delegate:CreateDelegate () */
3665 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3666 method = mono_get_delegate_invoke (klass);
3667 if (mono_loader_get_last_error ())
3670 g_ptr_array_add (array, method);
3674 mono_class_setup_methods (klass);
3675 mono_class_setup_vtable (klass);
3676 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3679 if (is_generic_parameter (&klass->byval_arg))
3680 nslots = mono_class_get_vtable_size (klass->parent);
3682 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3683 if (nslots >= sizeof (method_slots_default) * 8) {
3684 method_slots = g_new0 (guint32, nslots / 32 + 1);
3686 method_slots = method_slots_default;
3687 memset (method_slots, 0, sizeof (method_slots_default));
3690 mono_class_setup_methods (klass);
3691 mono_class_setup_vtable (klass);
3692 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3696 while ((method = mono_class_get_methods (klass, &iter))) {
3698 if (method->slot != -1) {
3699 g_assert (method->slot < nslots);
3700 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3702 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3703 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3706 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3708 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3709 if (bflags & BFLAGS_Public)
3711 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3717 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3718 if (bflags & BFLAGS_Static)
3719 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3722 if (bflags & BFLAGS_Instance)
3730 if (compare_func (name, method->name))
3735 g_ptr_array_add (array, method);
3737 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3739 if (method_slots != method_slots_default)
3740 g_free (method_slots);
3745 if (method_slots != method_slots_default)
3746 g_free (method_slots);
3747 g_ptr_array_free (array, TRUE);
3749 if (mono_class_has_failure (klass)) {
3750 *ex = mono_class_get_exception_for_failure (klass);
3752 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3753 mono_loader_clear_error ();
3758 ICALL_EXPORT MonoArray*
3759 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3761 static MonoClass *MethodInfo_array;
3765 MonoVTable *array_vtable;
3766 MonoException *ex = NULL;
3767 const char *mname = NULL;
3768 GPtrArray *method_array;
3769 MonoClass *klass, *refklass;
3772 mono_error_init (&error);
3774 if (!MethodInfo_array) {
3775 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3776 mono_memory_barrier ();
3777 MethodInfo_array = klass;
3780 klass = mono_class_from_mono_type (type->type);
3781 refklass = mono_class_from_mono_type (reftype->type);
3782 domain = ((MonoObject *)type)->vtable->domain;
3783 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3784 if (!is_ok (&error)) {
3785 mono_error_set_pending_exception (&error);
3788 if (type->type->byref) {
3789 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3790 mono_error_set_pending_exception (&error);
3796 mname = mono_string_to_utf8 (name);
3798 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3799 g_free ((char*)mname);
3801 mono_set_pending_exception (ex);
3805 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3806 if (!mono_error_ok (&error)) {
3807 mono_error_set_pending_exception (&error);
3811 for (i = 0; i < method_array->len; ++i) {
3812 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3813 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3814 if (!mono_error_ok (&error))
3816 mono_array_setref (res, i, rm);
3820 g_ptr_array_free (method_array, TRUE);
3821 if (!mono_error_ok (&error))
3822 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3826 ICALL_EXPORT MonoArray*
3827 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3830 MonoClass *startklass, *klass, *refklass;
3835 gpointer iter = NULL;
3836 MonoPtrArray tmp_array;
3839 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3841 domain = ((MonoObject *)type)->vtable->domain;
3842 if (type->type->byref)
3843 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3844 klass = startklass = mono_class_from_mono_type (type->type);
3845 refklass = mono_class_from_mono_type (reftype->type);
3847 mono_class_setup_methods (klass);
3848 if (mono_class_has_failure (klass)) {
3849 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3854 while ((method = mono_class_get_methods (klass, &iter))) {
3856 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3858 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3859 if (bflags & BFLAGS_Public)
3862 if (bflags & BFLAGS_NonPublic)
3868 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3869 if (bflags & BFLAGS_Static)
3870 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3873 if (bflags & BFLAGS_Instance)
3879 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3880 if (!mono_error_ok (&error)) {
3881 mono_error_set_pending_exception (&error);
3885 mono_ptr_array_append (tmp_array, member);
3888 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
3890 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3891 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3893 mono_ptr_array_destroy (tmp_array);
3899 property_hash (gconstpointer data)
3901 MonoProperty *prop = (MonoProperty*)data;
3903 return g_str_hash (prop->name);
3907 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3909 if (method1->is_inflated)
3910 method1 = ((MonoMethodInflated*) method1)->declaring;
3911 if (method2->is_inflated)
3912 method2 = ((MonoMethodInflated*) method2)->declaring;
3914 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3918 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3920 // Properties are hide-by-name-and-signature
3921 if (!g_str_equal (prop1->name, prop2->name))
3924 /* If we see a property in a generic method, we want to
3925 compare the generic signatures, not the inflated signatures
3926 because we might conflate two properties that were
3930 public T this[T t] { getter { return t; } } // method 1
3931 public U this[U u] { getter { return u; } } // method 2
3934 If we see int Foo<int,int>::Item[int] we need to know if
3935 the indexer came from method 1 or from method 2, and we
3936 shouldn't conflate them. (Bugzilla 36283)
3938 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
3941 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
3948 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3953 return method_nonpublic (accessor, start_klass);
3956 ICALL_EXPORT MonoArray*
3957 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3961 MonoClass *startklass, *klass;
3967 gchar *propname = NULL;
3968 int (*compare_func) (const char *s1, const char *s2) = NULL;
3970 GHashTable *properties = NULL;
3971 MonoPtrArray tmp_array;
3973 mono_error_init (&error);
3975 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
3977 domain = ((MonoObject *)type)->vtable->domain;
3978 if (type->type->byref)
3979 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
3980 klass = startklass = mono_class_from_mono_type (type->type);
3983 propname = mono_string_to_utf8 (name);
3984 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3987 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3989 mono_class_setup_methods (klass);
3990 mono_class_setup_vtable (klass);
3991 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3995 while ((prop = mono_class_get_properties (klass, &iter))) {
4001 flags = method->flags;
4004 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4005 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4006 if (bflags & BFLAGS_Public)
4008 } else if (bflags & BFLAGS_NonPublic) {
4009 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4010 property_accessor_nonpublic(prop->set, startklass == klass)) {
4017 if (flags & METHOD_ATTRIBUTE_STATIC) {
4018 if (bflags & BFLAGS_Static)
4019 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4022 if (bflags & BFLAGS_Instance)
4031 if (compare_func (propname, prop->name))
4035 if (g_hash_table_lookup (properties, prop))
4038 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4041 mono_ptr_array_append (tmp_array, pr);
4043 g_hash_table_insert (properties, prop, prop);
4045 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4048 g_hash_table_destroy (properties);
4051 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4052 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4053 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4055 mono_ptr_array_destroy (tmp_array);
4062 if (mono_class_has_failure (klass)) {
4063 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4065 mono_error_set_from_loader_error (&error);
4066 mono_loader_clear_error ();
4071 g_hash_table_destroy (properties);
4074 mono_ptr_array_destroy (tmp_array);
4076 mono_error_set_pending_exception (&error);
4082 event_hash (gconstpointer data)
4084 MonoEvent *event = (MonoEvent*)data;
4086 return g_str_hash (event->name);
4090 event_equal (MonoEvent *event1, MonoEvent *event2)
4092 // Events are hide-by-name
4093 return g_str_equal (event1->name, event2->name);
4096 ICALL_EXPORT MonoArray*
4097 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4101 MonoClass *startklass, *klass;
4107 char *utf8_name = NULL;
4108 int (*compare_func) (const char *s1, const char *s2) = NULL;
4109 GHashTable *events = NULL;
4110 MonoPtrArray tmp_array;
4112 mono_error_init (&error);
4114 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4116 domain = mono_object_domain (type);
4117 if (type->type->byref)
4118 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4119 klass = startklass = mono_class_from_mono_type (type->type);
4121 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4123 mono_class_setup_methods (klass);
4124 mono_class_setup_vtable (klass);
4125 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4129 while ((event = mono_class_get_events (klass, &iter))) {
4131 method = event->add;
4133 method = event->remove;
4135 method = event->raise;
4137 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4138 if (bflags & BFLAGS_Public)
4140 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4141 if (bflags & BFLAGS_NonPublic)
4146 if (bflags & BFLAGS_NonPublic)
4152 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4153 if (bflags & BFLAGS_Static)
4154 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4157 if (bflags & BFLAGS_Instance)
4162 if (bflags & BFLAGS_Instance)
4168 if (utf8_name == NULL) {
4169 utf8_name = mono_string_to_utf8 (name);
4170 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4173 if (compare_func (event->name, utf8_name))
4177 if (g_hash_table_lookup (events, event))
4180 MonoReflectionEvent *ev_obj;
4181 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4184 mono_ptr_array_append (tmp_array, ev_obj);
4186 g_hash_table_insert (events, event, event);
4188 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4191 g_hash_table_destroy (events);
4193 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4195 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4196 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4198 mono_ptr_array_destroy (tmp_array);
4200 if (utf8_name != NULL)
4206 if (mono_class_has_failure (klass)) {
4207 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4209 mono_error_set_from_loader_error (&error);
4210 mono_loader_clear_error ();
4216 g_hash_table_destroy (events);
4217 if (utf8_name != NULL)
4220 mono_ptr_array_destroy (tmp_array);
4222 mono_error_set_pending_exception (&error);
4226 ICALL_EXPORT MonoArray*
4227 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4230 MonoReflectionType *rt;
4238 MonoPtrArray tmp_array;
4240 domain = ((MonoObject *)type)->vtable->domain;
4241 if (type->type->byref)
4242 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4243 klass = mono_class_from_mono_type (type->type);
4246 * If a nested type is generic, return its generic type definition.
4247 * Note that this means that the return value is essentially the set
4248 * of nested types of the generic type definition of @klass.
4250 * A note in MSDN claims that a generic type definition can have
4251 * nested types that aren't generic. In any case, the container of that
4252 * nested type would be the generic type definition.
4254 if (klass->generic_class)
4255 klass = klass->generic_class->container_class;
4257 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4259 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4261 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4262 if (bflags & BFLAGS_Public)
4265 if (bflags & BFLAGS_NonPublic)
4273 str = mono_string_to_utf8 (name);
4274 mono_identifier_unescape_type_name_chars (str);
4277 if (strcmp (nested->name, str))
4281 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4282 mono_error_raise_exception (&error);
4284 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4287 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4289 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4290 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4292 mono_ptr_array_destroy (tmp_array);
4300 ICALL_EXPORT MonoReflectionType*
4301 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4304 MonoReflectionType *ret;
4306 MonoType *type = NULL;
4307 MonoTypeNameParse info;
4308 gboolean type_resolve;
4310 /* On MS.NET, this does not fire a TypeResolve event */
4311 type_resolve = TRUE;
4312 str = mono_string_to_utf8 (name);
4313 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4314 if (!mono_reflection_parse_type (str, &info)) {
4316 mono_reflection_free_type_info (&info);
4318 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4321 /*g_print ("failed parse\n");*/
4325 if (info.assembly.name) {
4327 mono_reflection_free_type_info (&info);
4329 /* 1.0 and 2.0 throw different exceptions */
4330 if (mono_defaults.generic_ilist_class)
4331 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4333 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4339 if (module != NULL) {
4341 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4346 if (assembly_is_dynamic (assembly->assembly)) {
4347 /* Enumerate all modules */
4348 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4352 if (abuilder->modules) {
4353 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4354 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4355 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4361 if (!type && abuilder->loaded_modules) {
4362 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4363 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4364 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4371 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4373 mono_reflection_free_type_info (&info);
4375 MonoException *e = NULL;
4378 e = mono_get_exception_type_load (name, NULL);
4380 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4381 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4383 mono_loader_clear_error ();
4386 mono_set_pending_exception (e);
4388 } else if (mono_loader_get_last_error ()) {
4390 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4393 mono_loader_clear_error ();
4396 if (type->type == MONO_TYPE_CLASS) {
4397 MonoClass *klass = mono_type_get_class (type);
4399 /* need to report exceptions ? */
4400 if (throwOnError && mono_class_has_failure (klass)) {
4401 /* report SecurityException (or others) that occured when loading the assembly */
4402 MonoException *exc = mono_class_get_exception_for_failure (klass);
4403 mono_loader_clear_error ();
4404 mono_set_pending_exception (exc);
4409 /* g_print ("got it\n"); */
4410 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4411 mono_error_raise_exception (&error);
4417 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4420 gchar *shadow_ini_file;
4423 /* Check for shadow-copied assembly */
4424 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4425 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4427 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4428 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4434 g_free (shadow_ini_file);
4435 if (content != NULL) {
4438 *filename = content;
4445 ICALL_EXPORT MonoString *
4446 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4448 MonoDomain *domain = mono_object_domain (assembly);
4449 MonoAssembly *mass = assembly->assembly;
4450 MonoString *res = NULL;
4455 if (g_path_is_absolute (mass->image->name)) {
4456 absolute = g_strdup (mass->image->name);
4457 dirname = g_path_get_dirname (absolute);
4459 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4460 dirname = g_strdup (mass->basedir);
4463 replace_shadow_path (domain, dirname, &absolute);
4468 for (i = strlen (absolute) - 1; i >= 0; i--)
4469 if (absolute [i] == '\\')
4474 uri = g_filename_to_uri (absolute, NULL, NULL);
4476 const char *prepend = "file://";
4478 if (*absolute == '/' && *(absolute + 1) == '/') {
4481 prepend = "file:///";
4484 uri = g_strconcat (prepend, absolute, NULL);
4488 res = mono_string_new (domain, uri);
4495 ICALL_EXPORT MonoBoolean
4496 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4498 MonoAssembly *mass = assembly->assembly;
4500 return mass->in_gac;
4503 ICALL_EXPORT MonoReflectionAssembly*
4504 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4509 MonoImageOpenStatus status;
4510 MonoReflectionAssembly* result = NULL;
4512 name = mono_string_to_utf8 (mname);
4513 res = mono_assembly_load_with_partial_name (name, &status);
4519 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4521 mono_error_set_pending_exception (&error);
4525 ICALL_EXPORT MonoString *
4526 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4528 MonoDomain *domain = mono_object_domain (assembly);
4531 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4536 ICALL_EXPORT MonoBoolean
4537 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4539 return assembly->assembly->ref_only;
4542 ICALL_EXPORT MonoString *
4543 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4545 MonoDomain *domain = mono_object_domain (assembly);
4547 return mono_string_new (domain, assembly->assembly->image->version);
4550 ICALL_EXPORT MonoReflectionMethod*
4551 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4554 MonoReflectionMethod *res = NULL;
4557 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4561 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4562 if (!mono_error_ok (&error))
4565 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4568 if (!mono_error_ok (&error))
4569 mono_error_set_pending_exception (&error);
4573 ICALL_EXPORT MonoReflectionModule*
4574 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4577 MonoReflectionModule *result = NULL;
4578 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4579 if (!mono_error_ok (&error))
4580 mono_error_set_pending_exception (&error);
4584 ICALL_EXPORT MonoArray*
4585 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4587 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4588 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4592 for (i = 0; i < table->rows; ++i) {
4593 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4594 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4600 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4602 static MonoMethod *create_version = NULL;
4606 mono_error_init (error);
4609 if (!create_version) {
4610 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4611 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4612 g_assert (create_version);
4613 mono_method_desc_free (desc);
4619 args [3] = &revision;
4620 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4621 return_val_if_nok (error, NULL);
4623 mono_runtime_invoke_checked (create_version, result, args, error);
4624 return_val_if_nok (error, NULL);
4629 ICALL_EXPORT MonoArray*
4630 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4634 MonoDomain *domain = mono_object_domain (assembly);
4636 static MonoMethod *create_culture = NULL;
4637 MonoImage *image = assembly->assembly->image;
4641 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4644 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4646 if (count > 0 && !create_culture) {
4647 MonoMethodDesc *desc = mono_method_desc_new (
4648 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4649 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4650 g_assert (create_culture);
4651 mono_method_desc_free (desc);
4654 for (i = 0; i < count; i++) {
4655 MonoObject *version;
4656 MonoReflectionAssemblyName *aname;
4657 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4659 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4661 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4662 domain, mono_class_get_assembly_name_class (), &error);
4663 mono_error_raise_exception (&error);
4665 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4667 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4668 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4669 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4670 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4671 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4672 aname->versioncompat = 1; /* SameMachine (default) */
4673 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4675 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4676 mono_error_raise_exception (&error);
4678 MONO_OBJECT_SETREF (aname, version, version);
4680 if (create_culture) {
4682 MonoBoolean assembly_ref = 1;
4683 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4684 args [1] = &assembly_ref;
4686 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4687 mono_error_raise_exception (&error);
4689 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4692 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4693 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4694 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4696 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4697 /* public key token isn't copied - the class library will
4698 automatically generate it from the public key if required */
4699 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4700 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4702 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4703 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4706 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4709 /* note: this function doesn't return the codebase on purpose (i.e. it can
4710 be used under partial trust as path information isn't present). */
4712 mono_array_setref (result, i, aname);
4717 /* move this in some file in mono/util/ */
4719 g_concat_dir_and_file (const char *dir, const char *file)
4721 g_return_val_if_fail (dir != NULL, NULL);
4722 g_return_val_if_fail (file != NULL, NULL);
4725 * If the directory name doesn't have a / on the end, we need
4726 * to add one so we get a proper path to the file
4728 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4729 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4731 return g_strconcat (dir, file, NULL);
4735 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4738 char *n = mono_string_to_utf8 (name);
4739 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4741 guint32 cols [MONO_MANIFEST_SIZE];
4742 guint32 impl, file_idx;
4746 for (i = 0; i < table->rows; ++i) {
4747 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4748 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4749 if (strcmp (val, n) == 0)
4753 if (i == table->rows)
4756 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4759 * this code should only be called after obtaining the
4760 * ResourceInfo and handling the other cases.
4762 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4763 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4765 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4770 module = assembly->assembly->image;
4773 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4774 mono_error_raise_exception (&error);
4775 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4777 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4780 ICALL_EXPORT gboolean
4781 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4784 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4786 guint32 cols [MONO_MANIFEST_SIZE];
4787 guint32 file_cols [MONO_FILE_SIZE];
4791 n = mono_string_to_utf8 (name);
4792 for (i = 0; i < table->rows; ++i) {
4793 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4794 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4795 if (strcmp (val, n) == 0)
4799 if (i == table->rows)
4802 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4803 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4806 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4807 case MONO_IMPLEMENTATION_FILE:
4808 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4809 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4810 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4811 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4812 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4813 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4816 info->location = RESOURCE_LOCATION_EMBEDDED;
4819 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4820 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4821 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4822 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4823 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4824 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4826 mono_set_pending_exception (ex);
4829 MonoReflectionAssembly *assm_obj;
4830 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4832 mono_error_set_pending_exception (&error);
4835 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4837 /* Obtain info recursively */
4838 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4839 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4842 case MONO_IMPLEMENTATION_EXP_TYPE:
4843 g_assert_not_reached ();
4851 ICALL_EXPORT MonoObject*
4852 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4854 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4855 MonoArray *result = NULL;
4860 /* check hash if needed */
4862 n = mono_string_to_utf8 (name);
4863 for (i = 0; i < table->rows; ++i) {
4864 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4865 if (strcmp (val, n) == 0) {
4868 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4869 fn = mono_string_new (mono_object_domain (assembly), n);
4871 return (MonoObject*)fn;
4879 for (i = 0; i < table->rows; ++i) {
4880 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4884 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4887 for (i = 0; i < table->rows; ++i) {
4888 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4889 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4890 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4891 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4896 return (MonoObject*)result;
4899 ICALL_EXPORT MonoArray*
4900 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4903 MonoDomain *domain = mono_domain_get();
4906 int i, j, file_count = 0;
4907 MonoImage **modules;
4908 guint32 module_count, real_module_count;
4909 MonoTableInfo *table;
4910 guint32 cols [MONO_FILE_SIZE];
4911 MonoImage *image = assembly->assembly->image;
4913 g_assert (image != NULL);
4914 g_assert (!assembly_is_dynamic (assembly->assembly));
4916 table = &image->tables [MONO_TABLE_FILE];
4917 file_count = table->rows;
4919 modules = image->modules;
4920 module_count = image->module_count;
4922 real_module_count = 0;
4923 for (i = 0; i < module_count; ++i)
4925 real_module_count ++;
4927 klass = mono_class_get_module_class ();
4928 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4930 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
4931 mono_error_raise_exception (&error);
4932 mono_array_setref (res, 0, image_obj);
4934 for (i = 0; i < module_count; ++i)
4936 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
4937 mono_error_raise_exception (&error);
4938 mono_array_setref (res, j, rm);
4942 for (i = 0; i < file_count; ++i, ++j) {
4943 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4944 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
4945 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
4946 mono_error_raise_exception (&error);
4947 mono_array_setref (res, j, rm);
4950 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4952 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4953 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
4956 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
4957 mono_error_raise_exception (&error);
4958 mono_array_setref (res, j, rm);
4965 ICALL_EXPORT MonoReflectionMethod*
4966 ves_icall_GetCurrentMethod (void)
4968 MonoReflectionMethod *res = NULL;
4971 MonoMethod *m = mono_method_get_last_managed ();
4974 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
4978 while (m->is_inflated)
4979 m = ((MonoMethodInflated*)m)->declaring;
4981 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
4982 mono_error_raise_exception (&error);
4988 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4991 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4994 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4995 //method is inflated, we should inflate it on the other class
4996 MonoGenericContext ctx;
4997 ctx.method_inst = inflated->context.method_inst;
4998 ctx.class_inst = inflated->context.class_inst;
4999 if (klass->generic_class)
5000 ctx.class_inst = klass->generic_class->context.class_inst;
5001 else if (klass->generic_container)
5002 ctx.class_inst = klass->generic_container->context.class_inst;
5003 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5004 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5008 mono_class_setup_methods (method->klass);
5009 if (mono_class_has_failure (method->klass))
5011 for (i = 0; i < method->klass->method.count; ++i) {
5012 if (method->klass->methods [i] == method) {
5017 mono_class_setup_methods (klass);
5018 if (mono_class_has_failure (klass))
5020 g_assert (offset >= 0 && offset < klass->method.count);
5021 return klass->methods [offset];
5024 ICALL_EXPORT MonoReflectionMethod*
5025 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5027 MonoReflectionMethod *res = NULL;
5031 klass = mono_class_from_mono_type (type);
5032 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5034 if (method->klass != klass) {
5035 method = mono_method_get_equivalent_method (method, klass);
5040 klass = method->klass;
5041 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5042 mono_error_raise_exception (&error);
5046 ICALL_EXPORT MonoReflectionMethodBody*
5047 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5049 return mono_method_body_get_object (mono_domain_get (), method);
5052 ICALL_EXPORT MonoReflectionAssembly*
5053 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5056 MonoReflectionAssembly *result;
5057 MonoMethod *dest = NULL;
5059 mono_stack_walk_no_il (get_executing, &dest);
5061 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5063 mono_error_set_pending_exception (&error);
5068 ICALL_EXPORT MonoReflectionAssembly*
5069 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5072 MonoReflectionAssembly *result;
5073 MonoDomain* domain = mono_domain_get ();
5075 if (!domain->entry_assembly)
5078 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5080 mono_error_set_pending_exception (&error);
5084 ICALL_EXPORT MonoReflectionAssembly*
5085 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5090 MonoReflectionAssembly *result;
5093 mono_stack_walk_no_il (get_executing, &dest);
5095 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5099 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5102 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5104 mono_error_set_pending_exception (&error);
5108 ICALL_EXPORT MonoString *
5109 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5110 gboolean assembly_qualified)
5112 MonoDomain *domain = mono_object_domain (object);
5113 MonoTypeNameFormat format;
5118 format = assembly_qualified ?
5119 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5120 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5122 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5124 name = mono_type_get_name_full (object->type, format);
5128 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5133 res = mono_string_new (domain, name);
5140 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5142 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5143 mono_class_init_or_throw (klass);
5144 return mono_security_core_clr_class_level (klass);
5148 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5150 MonoClassField *field = rfield->field;
5151 return mono_security_core_clr_field_level (field, TRUE);
5155 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5157 MonoMethod *method = rfield->method;
5158 return mono_security_core_clr_method_level (method, TRUE);
5162 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)
5164 static MonoMethod *create_culture = NULL;
5168 const char *pkey_ptr;
5170 MonoBoolean assembly_ref = 0;
5172 mono_error_init (error);
5174 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5175 aname->major = name->major;
5176 aname->minor = name->minor;
5177 aname->build = name->build;
5178 aname->flags = name->flags;
5179 aname->revision = name->revision;
5180 aname->hashalg = name->hash_alg;
5181 aname->versioncompat = 1; /* SameMachine (default) */
5182 aname->processor_architecture = name->arch;
5184 if (by_default_version) {
5185 MonoObject *version;
5187 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5188 return_if_nok (error);
5190 MONO_OBJECT_SETREF (aname, version, version);
5194 if (absolute != NULL && *absolute != '\0') {
5195 const gchar *prepend = "file://";
5198 codebase = g_strdup (absolute);
5203 for (i = strlen (codebase) - 1; i >= 0; i--)
5204 if (codebase [i] == '\\')
5207 if (*codebase == '/' && *(codebase + 1) == '/') {
5210 prepend = "file:///";
5214 result = g_strconcat (prepend, codebase, NULL);
5220 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5224 if (!create_culture) {
5225 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5226 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5227 g_assert (create_culture);
5228 mono_method_desc_free (desc);
5231 if (name->culture) {
5232 args [0] = mono_string_new (domain, name->culture);
5233 args [1] = &assembly_ref;
5235 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5236 return_if_nok (error);
5238 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5241 if (name->public_key) {
5242 pkey_ptr = (char*)name->public_key;
5243 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5245 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5246 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5247 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5248 } else if (default_publickey) {
5249 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5250 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5253 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5254 if (name->public_key_token [0]) {
5258 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5259 p = mono_array_addr (aname->keyToken, char, 0);
5261 for (i = 0, j = 0; i < 8; i++) {
5262 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5263 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5266 } else if (default_token) {
5267 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5271 ICALL_EXPORT MonoString *
5272 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5274 MonoDomain *domain = mono_object_domain (assembly);
5275 MonoAssembly *mass = assembly->assembly;
5279 name = mono_stringify_assembly_name (&mass->aname);
5280 res = mono_string_new (domain, name);
5287 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5291 MonoAssembly *mass = assembly->assembly;
5293 if (g_path_is_absolute (mass->image->name)) {
5294 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5295 mono_error_set_pending_exception (&error);
5298 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5300 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5301 mono_error_set_pending_exception (&error);
5307 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5311 MonoImageOpenStatus status = MONO_IMAGE_OK;
5314 MonoAssemblyName name;
5317 filename = mono_string_to_utf8 (fname);
5319 dirname = g_path_get_dirname (filename);
5320 replace_shadow_path (mono_domain_get (), dirname, &filename);
5323 image = mono_image_open (filename, &status);
5329 if (status == MONO_IMAGE_IMAGE_INVALID)
5330 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5332 exc = mono_get_exception_file_not_found2 (NULL, fname);
5333 mono_set_pending_exception (exc);
5337 res = mono_assembly_fill_assembly_name (image, &name);
5339 mono_image_close (image);
5341 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5345 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5346 mono_error_set_pending_exception (&error);
5348 mono_image_close (image);
5352 ICALL_EXPORT MonoBoolean
5353 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5354 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5356 MonoBoolean result = FALSE;
5357 MonoDeclSecurityEntry entry;
5359 /* SecurityAction.RequestMinimum */
5360 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5361 *minimum = entry.blob;
5362 *minLength = entry.size;
5365 /* SecurityAction.RequestOptional */
5366 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5367 *optional = entry.blob;
5368 *optLength = entry.size;
5371 /* SecurityAction.RequestRefuse */
5372 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5373 *refused = entry.blob;
5374 *refLength = entry.size;
5382 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5384 guint32 attrs, visibility;
5386 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5387 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5388 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5391 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5397 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5399 MonoReflectionType *rt;
5402 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5405 mono_error_init (error);
5407 /* we start the count from 1 because we skip the special type <Module> */
5410 for (i = 1; i < tdef->rows; ++i) {
5411 if (mono_module_type_is_visible (tdef, image, i + 1))
5415 count = tdef->rows - 1;
5417 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5418 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5420 for (i = 1; i < tdef->rows; ++i) {
5421 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5422 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5423 mono_loader_assert_no_error (); /* Plug any leaks */
5424 mono_error_assert_ok (error);
5427 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5428 return_val_if_nok (error, NULL);
5430 mono_array_setref (res, count, rt);
5432 MonoException *ex = mono_error_convert_to_exception (error);
5433 mono_array_setref (*exceptions, count, ex);
5442 ICALL_EXPORT MonoArray*
5443 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5446 MonoArray *res = NULL;
5447 MonoArray *exceptions = NULL;
5448 MonoImage *image = NULL;
5449 MonoTableInfo *table = NULL;
5452 int i, len, ex_count;
5454 domain = mono_object_domain (assembly);
5456 g_assert (!assembly_is_dynamic (assembly->assembly));
5457 image = assembly->assembly->image;
5458 table = &image->tables [MONO_TABLE_FILE];
5459 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5460 mono_error_raise_exception (&error);
5462 /* Append data from all modules in the assembly */
5463 for (i = 0; i < table->rows; ++i) {
5464 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5465 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5470 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5471 mono_error_raise_exception (&error);
5473 /* Append the new types to the end of the array */
5474 if (mono_array_length (res2) > 0) {
5476 MonoArray *res3, *ex3;
5478 len1 = mono_array_length (res);
5479 len2 = mono_array_length (res2);
5481 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5482 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5483 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5486 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5487 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5488 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5495 /* the ReflectionTypeLoadException must have all the types (Types property),
5496 * NULL replacing types which throws an exception. The LoaderException must
5497 * contain all exceptions for NULL items.
5500 len = mono_array_length (res);
5503 for (i = 0; i < len; i++) {
5504 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5508 klass = mono_type_get_class (t->type);
5509 if ((klass != NULL) && mono_class_has_failure (klass)) {
5510 /* keep the class in the list */
5511 list = g_list_append (list, klass);
5512 /* and replace Type with NULL */
5513 mono_array_setref (res, i, NULL);
5520 if (list || ex_count) {
5522 MonoException *exc = NULL;
5523 MonoArray *exl = NULL;
5524 int j, length = g_list_length (list) + ex_count;
5526 mono_loader_clear_error ();
5528 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5529 /* Types for which mono_class_get_checked () succeeded */
5530 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5531 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5532 mono_array_setref (exl, i, exc);
5534 /* Types for which it don't */
5535 for (j = 0; j < mono_array_length (exceptions); ++j) {
5536 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5538 g_assert (i < length);
5539 mono_array_setref (exl, i, exc);
5546 exc = mono_get_exception_reflection_type_load (res, exl);
5547 mono_loader_clear_error ();
5548 mono_set_pending_exception (exc);
5555 ICALL_EXPORT gboolean
5556 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5559 MonoAssemblyName aname;
5560 MonoDomain *domain = mono_object_domain (name);
5562 gboolean is_version_defined;
5563 gboolean is_token_defined;
5565 aname.public_key = NULL;
5566 val = mono_string_to_utf8 (assname);
5567 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5568 g_free ((guint8*) aname.public_key);
5573 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5574 mono_error_set_pending_exception (&error);
5576 mono_assembly_name_free (&aname);
5577 g_free ((guint8*) aname.public_key);
5583 ICALL_EXPORT MonoReflectionType*
5584 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5587 MonoReflectionType *ret;
5588 MonoDomain *domain = mono_object_domain (module);
5591 g_assert (module->image);
5593 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5594 /* These images do not have a global type */
5597 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5598 if (!mono_error_ok (&error)) {
5599 mono_error_set_pending_exception (&error);
5603 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5604 if (!mono_error_ok (&error)) {
5605 mono_error_set_pending_exception (&error);
5613 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5615 /*if (module->image)
5616 mono_image_close (module->image);*/
5619 ICALL_EXPORT MonoString*
5620 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5622 MonoDomain *domain = mono_object_domain (module);
5624 g_assert (module->image);
5625 return mono_string_new (domain, module->image->guid);
5628 ICALL_EXPORT gpointer
5629 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5632 if (module->image && module->image->is_module_handle)
5633 return module->image->raw_data;
5636 return (gpointer) (-1);
5640 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5642 if (image_is_dynamic (image)) {
5643 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5644 *pe_kind = dyn->pe_kind;
5645 *machine = dyn->machine;
5648 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5649 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5654 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5656 return (image->md_version_major << 16) | (image->md_version_minor);
5659 ICALL_EXPORT MonoArray*
5660 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5663 MonoArray *exceptions;
5667 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5671 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5672 mono_error_raise_exception (&error);
5674 for (i = 0; i < mono_array_length (exceptions); ++i) {
5675 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5677 mono_set_pending_exception (ex);
5686 mono_memberref_is_method (MonoImage *image, guint32 token)
5688 if (!image_is_dynamic (image)) {
5689 guint32 cols [MONO_MEMBERREF_SIZE];
5691 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5692 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5693 mono_metadata_decode_blob_size (sig, &sig);
5694 return (*sig != 0x6);
5696 MonoClass *handle_class;
5698 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5701 return mono_defaults.methodhandle_class == handle_class;
5706 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5709 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5710 mono_array_addr (type_args, MonoType*, 0));
5712 context->class_inst = NULL;
5714 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5715 mono_array_addr (method_args, MonoType*, 0));
5717 context->method_inst = NULL;
5720 ICALL_EXPORT MonoType*
5721 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5724 int table = mono_metadata_token_table (token);
5725 int index = mono_metadata_token_index (token);
5726 MonoGenericContext context;
5729 *resolve_error = ResolveTokenError_Other;
5731 /* Validate token */
5732 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5733 (table != MONO_TABLE_TYPESPEC)) {
5734 *resolve_error = ResolveTokenError_BadTable;
5738 if (image_is_dynamic (image)) {
5739 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5740 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5741 return klass ? &klass->byval_arg : NULL;
5744 init_generic_context_from_args (&context, type_args, method_args);
5745 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5746 return klass ? &klass->byval_arg : NULL;
5749 if ((index <= 0) || (index > image->tables [table].rows)) {
5750 *resolve_error = ResolveTokenError_OutOfRange;
5754 init_generic_context_from_args (&context, type_args, method_args);
5755 klass = mono_class_get_checked (image, token, &error);
5757 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5758 if (!mono_error_ok (&error)) {
5759 mono_error_set_pending_exception (&error);
5764 return &klass->byval_arg;
5769 ICALL_EXPORT MonoMethod*
5770 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5773 int table = mono_metadata_token_table (token);
5774 int index = mono_metadata_token_index (token);
5775 MonoGenericContext context;
5778 *resolve_error = ResolveTokenError_Other;
5780 /* Validate token */
5781 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5782 (table != MONO_TABLE_MEMBERREF)) {
5783 *resolve_error = ResolveTokenError_BadTable;
5787 if (image_is_dynamic (image)) {
5788 if (table == MONO_TABLE_METHOD)
5789 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5791 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5792 *resolve_error = ResolveTokenError_BadTable;
5796 init_generic_context_from_args (&context, type_args, method_args);
5797 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5800 if ((index <= 0) || (index > image->tables [table].rows)) {
5801 *resolve_error = ResolveTokenError_OutOfRange;
5804 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5805 *resolve_error = ResolveTokenError_BadTable;
5809 init_generic_context_from_args (&context, type_args, method_args);
5810 method = mono_get_method_checked (image, token, NULL, &context, &error);
5811 mono_error_set_pending_exception (&error);
5816 ICALL_EXPORT MonoString*
5817 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5819 int index = mono_metadata_token_index (token);
5821 *error = ResolveTokenError_Other;
5823 /* Validate token */
5824 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5825 *error = ResolveTokenError_BadTable;
5829 if (image_is_dynamic (image))
5830 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5832 if ((index <= 0) || (index >= image->heap_us.size)) {
5833 *error = ResolveTokenError_OutOfRange;
5837 /* FIXME: What to do if the index points into the middle of a string ? */
5839 return mono_ldstr (mono_domain_get (), image, index);
5842 ICALL_EXPORT MonoClassField*
5843 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5847 int table = mono_metadata_token_table (token);
5848 int index = mono_metadata_token_index (token);
5849 MonoGenericContext context;
5850 MonoClassField *field;
5852 *resolve_error = ResolveTokenError_Other;
5854 /* Validate token */
5855 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5856 *resolve_error = ResolveTokenError_BadTable;
5860 if (image_is_dynamic (image)) {
5861 if (table == MONO_TABLE_FIELD)
5862 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5864 if (mono_memberref_is_method (image, token)) {
5865 *resolve_error = ResolveTokenError_BadTable;
5869 init_generic_context_from_args (&context, type_args, method_args);
5870 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5873 if ((index <= 0) || (index > image->tables [table].rows)) {
5874 *resolve_error = ResolveTokenError_OutOfRange;
5877 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5878 *resolve_error = ResolveTokenError_BadTable;
5882 init_generic_context_from_args (&context, type_args, method_args);
5883 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5884 mono_error_set_pending_exception (&error);
5890 ICALL_EXPORT MonoObject*
5891 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5895 int table = mono_metadata_token_table (token);
5897 *error = ResolveTokenError_Other;
5900 case MONO_TABLE_TYPEDEF:
5901 case MONO_TABLE_TYPEREF:
5902 case MONO_TABLE_TYPESPEC: {
5903 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5905 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
5906 mono_error_raise_exception (&merror);
5913 case MONO_TABLE_METHOD:
5914 case MONO_TABLE_METHODSPEC: {
5915 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5917 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5918 mono_error_raise_exception (&merror);
5924 case MONO_TABLE_FIELD: {
5925 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5927 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5928 mono_error_raise_exception (&merror);
5934 case MONO_TABLE_MEMBERREF:
5935 if (mono_memberref_is_method (image, token)) {
5936 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5938 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5939 mono_error_raise_exception (&merror);
5946 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5948 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5949 mono_error_raise_exception (&merror);
5958 *error = ResolveTokenError_BadTable;
5964 ICALL_EXPORT MonoArray*
5965 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5967 int table = mono_metadata_token_table (token);
5968 int idx = mono_metadata_token_index (token);
5969 MonoTableInfo *tables = image->tables;
5974 *error = ResolveTokenError_OutOfRange;
5976 /* FIXME: Support other tables ? */
5977 if (table != MONO_TABLE_STANDALONESIG)
5980 if (image_is_dynamic (image))
5983 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5986 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5988 ptr = mono_metadata_blob_heap (image, sig);
5989 len = mono_metadata_decode_blob_size (ptr, &ptr);
5991 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5992 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5996 ICALL_EXPORT MonoReflectionType*
5997 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6000 MonoReflectionType *ret;
6002 int isbyref = 0, rank;
6003 char *str = mono_string_to_utf8 (smodifiers);
6006 klass = mono_class_from_mono_type (tb->type.type);
6008 /* logic taken from mono_reflection_parse_type(): keep in sync */
6012 if (isbyref) { /* only one level allowed by the spec */
6021 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6022 mono_error_raise_exception (&error);
6026 klass = mono_ptr_class_get (&klass->byval_arg);
6027 mono_class_init (klass);
6038 else if (*p != '*') { /* '*' means unknown lower bound */
6049 klass = mono_array_class_get (klass, rank);
6050 mono_class_init (klass);
6059 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6060 mono_error_raise_exception (&error);
6065 ICALL_EXPORT MonoBoolean
6066 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
6072 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6078 check_for_invalid_type (MonoClass *klass)
6082 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6085 name = mono_type_get_full_name (klass);
6086 str = mono_string_new (mono_domain_get (), name);
6088 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
6091 ICALL_EXPORT MonoReflectionType *
6092 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6095 MonoReflectionType *ret;
6096 MonoClass *klass, *aklass;
6098 klass = mono_class_from_mono_type (type->type);
6099 check_for_invalid_type (klass);
6101 if (rank == 0) //single dimentional array
6102 aklass = mono_array_class_get (klass, 1);
6104 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6106 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6107 mono_error_raise_exception (&error);
6112 ICALL_EXPORT MonoReflectionType *
6113 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6116 MonoReflectionType *ret;
6119 klass = mono_class_from_mono_type (type->type);
6120 mono_class_init_or_throw (klass);
6121 check_for_invalid_type (klass);
6123 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6124 mono_error_raise_exception (&error);
6129 ICALL_EXPORT MonoReflectionType *
6130 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6133 MonoReflectionType *ret;
6134 MonoClass *klass, *pklass;
6136 klass = mono_class_from_mono_type (type->type);
6137 mono_class_init_or_throw (klass);
6138 check_for_invalid_type (klass);
6140 pklass = mono_ptr_class_get (type->type);
6142 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6143 mono_error_raise_exception (&error);
6148 ICALL_EXPORT MonoObject *
6149 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6150 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6153 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6154 MonoObject *delegate;
6156 MonoMethod *method = info->method;
6158 mono_class_init_or_throw (delegate_class);
6160 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
6162 if (mono_security_core_clr_enabled ()) {
6163 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6167 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6168 mono_error_raise_exception (&error);
6170 if (method_is_dynamic (method)) {
6171 /* Creating a trampoline would leak memory */
6172 func = mono_compile_method (method);
6174 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6175 method = mono_object_get_virtual_method (target, method);
6176 func = mono_create_ftnptr (mono_domain_get (),
6177 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6180 mono_delegate_ctor_with_method (delegate, target, func, method);
6185 ICALL_EXPORT MonoMulticastDelegate *
6186 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6189 MonoMulticastDelegate *ret;
6191 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6193 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6194 mono_error_raise_exception (&error);
6195 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6200 ICALL_EXPORT MonoReflectionMethod*
6201 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6203 MonoReflectionMethod *ret = NULL;
6205 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6206 mono_error_raise_exception (&error);
6212 static inline gint32
6213 mono_array_get_byte_length (MonoArray *array)
6219 klass = array->obj.vtable->klass;
6221 if (array->bounds == NULL)
6222 length = array->max_length;
6225 for (i = 0; i < klass->rank; ++ i)
6226 length *= array->bounds [i].length;
6229 switch (klass->element_class->byval_arg.type) {
6232 case MONO_TYPE_BOOLEAN:
6236 case MONO_TYPE_CHAR:
6244 return length * sizeof (gpointer);
6255 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6257 return mono_array_get_byte_length (array);
6261 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6263 return mono_array_get (array, gint8, idx);
6267 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6269 mono_array_set (array, gint8, idx, value);
6272 ICALL_EXPORT MonoBoolean
6273 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6275 guint8 *src_buf, *dest_buf;
6278 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6282 g_assert (count >= 0);
6284 /* This is called directly from the class libraries without going through the managed wrapper */
6285 MONO_CHECK_ARG_NULL (src, FALSE);
6286 MONO_CHECK_ARG_NULL (dest, FALSE);
6288 /* watch out for integer overflow */
6289 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6292 src_buf = (guint8 *)src->vector + src_offset;
6293 dest_buf = (guint8 *)dest->vector + dest_offset;
6296 memcpy (dest_buf, src_buf, count);
6298 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6303 #ifndef DISABLE_REMOTING
6304 ICALL_EXPORT MonoObject *
6305 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6308 MonoDomain *domain = mono_object_domain (this_obj);
6310 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6311 MonoTransparentProxy *tp;
6315 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6316 mono_error_raise_exception (&error);
6317 tp = (MonoTransparentProxy*) res;
6319 MONO_OBJECT_SETREF (tp, rp, rp);
6320 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6321 klass = mono_class_from_mono_type (type);
6323 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6324 mono_class_setup_vtable (klass);
6325 if (mono_class_has_failure (klass)) {
6326 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6330 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
6331 tp->remote_class = mono_remote_class (domain, class_name, klass);
6333 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6337 ICALL_EXPORT MonoReflectionType *
6338 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6341 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6342 mono_error_raise_exception (&error);
6348 /* System.Environment */
6351 ves_icall_System_Environment_get_UserName (void)
6353 /* using glib is more portable */
6354 return mono_string_new (mono_domain_get (), g_get_user_name ());
6358 ICALL_EXPORT MonoString *
6359 ves_icall_System_Environment_get_MachineName (void)
6361 #if defined (HOST_WIN32)
6366 len = MAX_COMPUTERNAME_LENGTH + 1;
6367 buf = g_new (gunichar2, len);
6370 if (GetComputerName (buf, (PDWORD) &len)) {
6372 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6373 mono_error_raise_exception (&error);
6378 #elif !defined(DISABLE_SOCKETS)
6382 #if defined _SC_HOST_NAME_MAX
6383 n = sysconf (_SC_HOST_NAME_MAX);
6387 buf = g_malloc (n+1);
6389 if (gethostname (buf, n) == 0){
6391 result = mono_string_new (mono_domain_get (), buf);
6398 return mono_string_new (mono_domain_get (), "mono");
6403 ves_icall_System_Environment_get_Platform (void)
6405 #if defined (TARGET_WIN32)
6408 #elif defined(__MACH__)
6411 // Notice that the value is hidden from user code, and only exposed
6412 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6413 // define and making assumptions based on Unix/128/4 values before there
6414 // was a MacOS define. Lots of code would assume that not-Unix meant
6415 // Windows, but in this case, it would be OSX.
6424 ICALL_EXPORT MonoString *
6425 ves_icall_System_Environment_get_NewLine (void)
6427 #if defined (HOST_WIN32)
6428 return mono_string_new (mono_domain_get (), "\r\n");
6430 return mono_string_new (mono_domain_get (), "\n");
6434 ICALL_EXPORT MonoBoolean
6435 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6437 #if SIZEOF_VOID_P == 8
6441 gboolean isWow64Process = FALSE;
6442 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6443 return (MonoBoolean)isWow64Process;
6445 #elif defined(HAVE_SYS_UTSNAME_H)
6446 struct utsname name;
6448 if (uname (&name) >= 0) {
6449 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6456 ICALL_EXPORT MonoString *
6457 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6465 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6466 value = g_getenv (utf8_name);
6473 return mono_string_new (mono_domain_get (), value);
6477 * There is no standard way to get at environ.
6480 #ifndef __MINGW32_VERSION
6481 #if defined(__APPLE__)
6482 #if defined (TARGET_OSX)
6483 /* Apple defines this in crt_externs.h but doesn't provide that header for
6484 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6485 * in fact exist on all implementations (so far)
6487 gchar ***_NSGetEnviron(void);
6488 #define environ (*_NSGetEnviron())
6490 static char *mono_environ[1] = { NULL };
6491 #define environ mono_environ
6492 #endif /* defined (TARGET_OSX) */
6500 ICALL_EXPORT MonoArray *
6501 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6512 env_strings = GetEnvironmentStrings();
6515 env_string = env_strings;
6516 while (*env_string != '\0') {
6517 /* weird case that MS seems to skip */
6518 if (*env_string != '=')
6520 while (*env_string != '\0')
6526 domain = mono_domain_get ();
6527 names = mono_array_new (domain, mono_defaults.string_class, n);
6531 env_string = env_strings;
6532 while (*env_string != '\0') {
6533 /* weird case that MS seems to skip */
6534 if (*env_string != '=') {
6535 equal_str = wcschr(env_string, '=');
6536 g_assert(equal_str);
6538 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6539 mono_error_raise_exception (&error);
6540 mono_array_setref (names, n, str);
6543 while (*env_string != '\0')
6548 FreeEnvironmentStrings (env_strings);
6561 for (e = environ; *e != 0; ++ e)
6564 domain = mono_domain_get ();
6565 names = mono_array_new (domain, mono_defaults.string_class, n);
6568 for (e = environ; *e != 0; ++ e) {
6569 parts = g_strsplit (*e, "=", 2);
6571 str = mono_string_new (domain, *parts);
6572 mono_array_setref (names, n, str);
6585 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6587 #if !GLIB_CHECK_VERSION(2,4,0)
6588 #define g_setenv(a,b,c) setenv(a,b,c)
6589 #define g_unsetenv(a) unsetenv(a)
6593 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6596 gunichar2 *utf16_name, *utf16_value;
6598 gchar *utf8_name, *utf8_value;
6603 utf16_name = mono_string_to_utf16 (name);
6604 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6605 SetEnvironmentVariable (utf16_name, NULL);
6606 g_free (utf16_name);
6610 utf16_value = mono_string_to_utf16 (value);
6612 SetEnvironmentVariable (utf16_name, utf16_value);
6614 g_free (utf16_name);
6615 g_free (utf16_value);
6617 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6619 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6620 g_unsetenv (utf8_name);
6625 utf8_value = mono_string_to_utf8_checked (value, &error);
6626 if (!mono_error_ok (&error)) {
6628 mono_error_set_pending_exception (&error);
6631 g_setenv (utf8_name, utf8_value, TRUE);
6634 g_free (utf8_value);
6639 ves_icall_System_Environment_Exit (int result)
6641 mono_environment_exitcode_set (result);
6643 /* FIXME: There are some cleanup hangs that should be worked out, but
6644 * if the program is going to exit, everything will be cleaned up when
6645 * NaCl exits anyway.
6647 #ifndef __native_client__
6648 if (!mono_runtime_try_shutdown ())
6649 mono_thread_exit ();
6651 /* Suspend all managed threads since the runtime is going away */
6652 mono_thread_suspend_all_other_threads ();
6654 mono_runtime_quit ();
6657 /* we may need to do some cleanup here... */
6661 ICALL_EXPORT MonoString*
6662 ves_icall_System_Environment_GetGacPath (void)
6664 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6667 ICALL_EXPORT MonoString*
6668 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6670 #if defined (HOST_WIN32)
6671 #ifndef CSIDL_FLAG_CREATE
6672 #define CSIDL_FLAG_CREATE 0x8000
6675 WCHAR path [MAX_PATH];
6676 /* Create directory if no existing */
6677 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6682 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6683 mono_error_raise_exception (&error);
6687 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6689 return mono_string_new (mono_domain_get (), "");
6692 ICALL_EXPORT MonoArray *
6693 ves_icall_System_Environment_GetLogicalDrives (void)
6696 gunichar2 buf [256], *ptr, *dname;
6698 guint initial_size = 127, size = 128;
6701 MonoString *drivestr;
6702 MonoDomain *domain = mono_domain_get ();
6708 while (size > initial_size) {
6709 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6710 if (size > initial_size) {
6713 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6714 initial_size = size;
6728 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6733 while (*u16) { u16++; len ++; }
6734 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6735 mono_error_raise_exception (&error);
6736 mono_array_setref (result, ndrives++, drivestr);
6746 ICALL_EXPORT MonoString *
6747 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6749 gunichar2 volume_name [MAX_PATH + 1];
6751 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6753 return mono_string_from_utf16 (volume_name);
6756 ICALL_EXPORT MonoString *
6757 ves_icall_System_Environment_InternalGetHome (void)
6759 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6762 static const char *encodings [] = {
6764 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6765 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6766 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6768 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6769 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6770 "x_unicode_2_0_utf_7",
6772 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6773 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6775 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6778 "unicodefffe", "utf_16be",
6785 * Returns the internal codepage, if the value of "int_code_page" is
6786 * 1 at entry, and we can not compute a suitable code page number,
6787 * returns the code page as a string
6789 ICALL_EXPORT MonoString*
6790 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6795 char *codepage = NULL;
6797 int want_name = *int_code_page;
6800 *int_code_page = -1;
6802 g_get_charset (&cset);
6803 c = codepage = strdup (cset);
6804 for (c = codepage; *c; c++){
6805 if (isascii (*c) && isalpha (*c))
6810 /* g_print ("charset: %s\n", cset); */
6812 /* handle some common aliases */
6815 for (i = 0; p != 0; ){
6818 p = encodings [++i];
6821 if (strcmp (p, codepage) == 0){
6822 *int_code_page = code;
6825 p = encodings [++i];
6828 if (strstr (codepage, "utf_8") != NULL)
6829 *int_code_page |= 0x10000000;
6832 if (want_name && *int_code_page == -1)
6833 return mono_string_new (mono_domain_get (), cset);
6838 ICALL_EXPORT MonoBoolean
6839 ves_icall_System_Environment_get_HasShutdownStarted (void)
6841 if (mono_runtime_is_shutting_down ())
6844 if (mono_domain_is_unloading (mono_domain_get ()))
6851 ves_icall_System_Environment_BroadcastSettingChange (void)
6854 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6859 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6865 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6866 MonoReflectionMethod *method,
6867 MonoArray *out_args)
6869 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6872 #ifndef DISABLE_REMOTING
6873 ICALL_EXPORT MonoBoolean
6874 ves_icall_IsTransparentProxy (MonoObject *proxy)
6879 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6885 ICALL_EXPORT MonoReflectionMethod *
6886 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6887 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6889 MonoReflectionMethod *ret = NULL;
6894 MonoMethod **vtable;
6895 MonoMethod *res = NULL;
6897 MONO_CHECK_ARG_NULL (rtype, NULL);
6898 MONO_CHECK_ARG_NULL (rmethod, NULL);
6900 method = rmethod->method;
6901 klass = mono_class_from_mono_type (rtype->type);
6902 mono_class_init_or_throw (klass);
6904 if (MONO_CLASS_IS_INTERFACE (klass))
6907 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6910 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6911 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6917 mono_class_setup_vtable (klass);
6918 vtable = klass->vtable;
6920 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6921 gboolean variance_used = FALSE;
6922 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6923 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6925 res = vtable [offs + method->slot];
6927 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6930 if (method->slot != -1)
6931 res = vtable [method->slot];
6937 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
6938 mono_error_raise_exception (&error);
6943 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6949 klass = mono_class_from_mono_type (type->type);
6950 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
6951 if (!is_ok (&error)) {
6952 mono_error_set_pending_exception (&error);
6956 mono_vtable_set_is_remote (vtable, enable);
6959 #else /* DISABLE_REMOTING */
6962 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6964 g_assert_not_reached ();
6969 ICALL_EXPORT MonoObject *
6970 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6977 domain = mono_object_domain (type);
6978 klass = mono_class_from_mono_type (type->type);
6979 mono_class_init_or_throw (klass);
6981 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
6982 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6986 if (klass->rank >= 1) {
6987 g_assert (klass->rank == 1);
6988 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6990 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
6991 if (!is_ok (&error)) {
6992 mono_error_set_pending_exception (&error);
6995 /* Bypass remoting object creation check */
6996 ret = mono_object_new_alloc_specific_checked (vtable, &error);
6997 mono_error_set_pending_exception (&error);
7003 ICALL_EXPORT MonoString *
7004 ves_icall_System_IO_get_temp_path (void)
7006 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7009 #ifndef PLATFORM_NO_DRIVEINFO
7010 ICALL_EXPORT MonoBoolean
7011 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7012 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7016 ULARGE_INTEGER wapi_free_bytes_avail;
7017 ULARGE_INTEGER wapi_total_number_of_bytes;
7018 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7020 *error = ERROR_SUCCESS;
7021 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7022 &wapi_total_number_of_free_bytes);
7025 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7026 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7027 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7029 *free_bytes_avail = 0;
7030 *total_number_of_bytes = 0;
7031 *total_number_of_free_bytes = 0;
7032 *error = GetLastError ();
7038 ICALL_EXPORT guint32
7039 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7041 return GetDriveType (mono_string_chars (root_path_name));
7045 ICALL_EXPORT gpointer
7046 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
7048 return mono_compile_method (method);
7051 ICALL_EXPORT MonoString *
7052 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7057 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7059 #if defined (HOST_WIN32)
7060 /* Avoid mixing '/' and '\\' */
7063 for (i = strlen (path) - 1; i >= 0; i--)
7064 if (path [i] == '/')
7068 mcpath = mono_string_new (mono_domain_get (), path);
7075 get_bundled_app_config (void)
7077 const gchar *app_config;
7080 gchar *config_file_name, *config_file_path;
7081 gsize len, config_file_path_length, config_ext_length;
7084 domain = mono_domain_get ();
7085 file = domain->setup->configuration_file;
7086 if (!file || file->length == 0)
7089 // Retrieve config file and remove the extension
7090 config_file_name = mono_string_to_utf8 (file);
7091 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7092 if (!config_file_path)
7093 config_file_path = config_file_name;
7095 config_file_path_length = strlen (config_file_path);
7096 config_ext_length = strlen (".config");
7097 if (config_file_path_length <= config_ext_length)
7100 len = config_file_path_length - config_ext_length;
7101 module = (gchar *)g_malloc0 (len + 1);
7102 memcpy (module, config_file_path, len);
7103 // Get the config file from the module name
7104 app_config = mono_config_string_for_assembly_file (module);
7107 if (config_file_name != config_file_path)
7108 g_free (config_file_name);
7109 g_free (config_file_path);
7114 return mono_string_new (mono_domain_get (), app_config);
7118 get_bundled_machine_config (void)
7120 const gchar *machine_config;
7122 machine_config = mono_get_machine_config ();
7124 if (!machine_config)
7127 return mono_string_new (mono_domain_get (), machine_config);
7130 ICALL_EXPORT MonoString *
7131 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7136 path = g_path_get_dirname (mono_get_config_dir ());
7138 #if defined (HOST_WIN32)
7139 /* Avoid mixing '/' and '\\' */
7142 for (i = strlen (path) - 1; i >= 0; i--)
7143 if (path [i] == '/')
7147 ipath = mono_string_new (mono_domain_get (), path);
7153 ICALL_EXPORT gboolean
7154 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7156 MonoPEResourceDataEntry *entry;
7159 if (!assembly || !result || !size)
7164 image = assembly->assembly->image;
7165 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7169 *result = mono_image_rva_map (image, entry->rde_data_offset);
7174 *size = entry->rde_size;
7179 ICALL_EXPORT MonoBoolean
7180 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7182 return mono_is_debugger_attached ();
7185 ICALL_EXPORT MonoBoolean
7186 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7188 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7189 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7195 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7197 if (mono_get_runtime_callbacks ()->debug_log)
7198 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7202 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7204 #if defined (HOST_WIN32)
7205 OutputDebugString (mono_string_chars (message));
7207 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7211 /* Only used for value types */
7212 ICALL_EXPORT MonoObject *
7213 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7220 domain = mono_object_domain (type);
7221 klass = mono_class_from_mono_type (type->type);
7222 mono_class_init_or_throw (klass);
7224 if (mono_class_is_nullable (klass))
7225 /* No arguments -> null */
7228 result = mono_object_new_checked (domain, klass, &error);
7229 mono_error_raise_exception (&error);
7233 ICALL_EXPORT MonoReflectionMethod *
7234 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7236 MonoReflectionMethod *ret = NULL;
7239 MonoClass *klass, *parent;
7240 MonoGenericContext *generic_inst = NULL;
7241 MonoMethod *method = m->method;
7242 MonoMethod *result = NULL;
7245 if (method->klass == NULL)
7248 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7249 MONO_CLASS_IS_INTERFACE (method->klass) ||
7250 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7253 slot = mono_method_get_vtable_slot (method);
7257 klass = method->klass;
7258 if (klass->generic_class) {
7259 generic_inst = mono_class_get_context (klass);
7260 klass = klass->generic_class->container_class;
7264 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7265 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7266 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7267 or klass is the generic container class and generic_inst is the instantiation.
7269 when we go to the parent, if the parent is an open constructed type, we need to
7270 replace the type parameters by the definitions from the generic_inst, and then take it
7271 apart again into the klass and the generic_inst.
7273 For cases like this:
7274 class C<T> : B<T, int> {
7275 public override void Foo () { ... }
7277 class B<U,V> : A<HashMap<U,V>> {
7278 public override void Foo () { ... }
7281 public virtual void Foo () { ... }
7284 if at each iteration the parent isn't open, we can skip inflating it. if at some
7285 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7288 MonoGenericContext *parent_inst = NULL;
7289 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7291 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7292 if (!mono_error_ok (&error)) {
7293 mono_error_set_pending_exception (&error);
7297 if (parent->generic_class) {
7298 parent_inst = mono_class_get_context (parent);
7299 parent = parent->generic_class->container_class;
7302 mono_class_setup_vtable (parent);
7303 if (parent->vtable_size <= slot)
7306 generic_inst = parent_inst;
7309 klass = klass->parent;
7312 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7313 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7314 if (!mono_error_ok (&error)) {
7315 mono_error_set_pending_exception (&error);
7319 generic_inst = NULL;
7321 if (klass->generic_class) {
7322 generic_inst = mono_class_get_context (klass);
7323 klass = klass->generic_class->container_class;
7329 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7330 if (!mono_error_ok (&error)) {
7331 mono_error_set_pending_exception (&error);
7336 if (klass == method->klass)
7339 /*This is possible if definition == FALSE.
7340 * Do it here to be really sure we don't read invalid memory.
7342 if (slot >= klass->vtable_size)
7345 mono_class_setup_vtable (klass);
7347 result = klass->vtable [slot];
7348 if (result == NULL) {
7349 /* It is an abstract method */
7350 gpointer iter = NULL;
7351 while ((result = mono_class_get_methods (klass, &iter)))
7352 if (result->slot == slot)
7359 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7360 mono_error_raise_exception (&error);
7364 ICALL_EXPORT MonoString*
7365 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7367 MonoMethod *method = m->method;
7369 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7374 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7376 iter->sig = *(MonoMethodSignature**)argsp;
7378 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7379 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7382 /* FIXME: it's not documented what start is exactly... */
7386 iter->args = argsp + sizeof (gpointer);
7388 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7390 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7393 ICALL_EXPORT MonoTypedRef
7394 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7396 guint32 i, arg_size;
7400 i = iter->sig->sentinelpos + iter->next_arg;
7402 g_assert (i < iter->sig->param_count);
7404 res.type = iter->sig->params [i];
7405 res.klass = mono_class_from_mono_type (res.type);
7406 arg_size = mono_type_stack_size (res.type, &align);
7407 #if defined(__arm__) || defined(__mips__)
7408 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7410 res.value = iter->args;
7411 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7412 /* Values are stored as 8 byte register sized objects, but 'value'
7413 * is dereferenced as a pointer in other routines.
7415 res.value = (char*)res.value + 4;
7417 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7418 if (arg_size <= sizeof (gpointer)) {
7420 int padding = arg_size - mono_type_size (res.type, &dummy);
7421 res.value = (guint8*)res.value + padding;
7424 iter->args = (char*)iter->args + arg_size;
7427 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7432 ICALL_EXPORT MonoTypedRef
7433 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7435 guint32 i, arg_size;
7439 i = iter->sig->sentinelpos + iter->next_arg;
7441 g_assert (i < iter->sig->param_count);
7443 while (i < iter->sig->param_count) {
7444 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7446 res.type = iter->sig->params [i];
7447 res.klass = mono_class_from_mono_type (res.type);
7448 /* FIXME: endianess issue... */
7449 arg_size = mono_type_stack_size (res.type, &align);
7450 #if defined(__arm__) || defined(__mips__)
7451 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7453 res.value = iter->args;
7454 iter->args = (char*)iter->args + arg_size;
7456 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7459 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7467 ICALL_EXPORT MonoType*
7468 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7472 i = iter->sig->sentinelpos + iter->next_arg;
7474 g_assert (i < iter->sig->param_count);
7476 return iter->sig->params [i];
7479 ICALL_EXPORT MonoObject*
7480 mono_TypedReference_ToObject (MonoTypedRef* tref)
7482 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7483 MonoObject** objp = (MonoObject **)tref->value;
7487 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
7490 ICALL_EXPORT MonoTypedRef
7491 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7494 MonoReflectionField *f;
7496 MonoType *ftype = NULL;
7500 memset (&res, 0, sizeof (res));
7503 g_assert (mono_array_length (fields) > 0);
7505 klass = target->vtable->klass;
7507 for (i = 0; i < mono_array_length (fields); ++i) {
7508 f = mono_array_get (fields, MonoReflectionField*, i);
7510 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7513 if (f->field->parent != klass) {
7514 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7518 p = (guint8*)target + f->field->offset;
7520 p += f->field->offset - sizeof (MonoObject);
7521 klass = mono_class_from_mono_type (f->field->type);
7522 ftype = f->field->type;
7526 res.klass = mono_class_from_mono_type (ftype);
7533 prelink_method (MonoMethod *method)
7535 const char *exc_class, *exc_arg;
7536 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7538 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7540 mono_raise_exception(
7541 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7543 /* create the wrapper, too? */
7547 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7549 prelink_method (method->method);
7553 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7555 MonoClass *klass = mono_class_from_mono_type (type->type);
7557 gpointer iter = NULL;
7559 mono_class_init_or_throw (klass);
7561 while ((m = mono_class_get_methods (klass, &iter)))
7565 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7567 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7568 gint32 const **exponents,
7569 gunichar2 const **digitLowerTable,
7570 gunichar2 const **digitUpperTable,
7571 gint64 const **tenPowersList,
7572 gint32 const **decHexDigits)
7574 *mantissas = Formatter_MantissaBitsTable;
7575 *exponents = Formatter_TensExponentTable;
7576 *digitLowerTable = Formatter_DigitLowerTable;
7577 *digitUpperTable = Formatter_DigitUpperTable;
7578 *tenPowersList = Formatter_TenPowersList;
7579 *decHexDigits = Formatter_DecHexDigits;
7583 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7584 * and avoid useless allocations.
7589 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7592 MonoReflectionType *rt;
7595 for (i = 0; i < type->num_mods; ++i) {
7596 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7601 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7603 for (i = 0; i < type->num_mods; ++i) {
7604 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7605 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
7606 mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */
7608 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, &error);
7609 mono_error_raise_exception (&error);
7611 mono_array_setref (res, count, rt);
7618 ICALL_EXPORT MonoArray*
7619 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7621 MonoType *type = param->ClassImpl->type;
7622 MonoClass *member_class = mono_object_class (param->MemberImpl);
7623 MonoMethod *method = NULL;
7626 MonoMethodSignature *sig;
7628 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7629 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7630 method = rmethod->method;
7631 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7632 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7633 if (!(method = prop->property->get))
7634 method = prop->property->set;
7637 char *type_name = mono_type_get_full_name (member_class);
7638 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7639 MonoException *ex = mono_get_exception_not_supported (msg);
7642 mono_set_pending_exception (ex);
7646 image = method->klass->image;
7647 pos = param->PositionImpl;
7648 sig = mono_method_signature (method);
7652 type = sig->params [pos];
7654 return type_array_from_modifiers (image, type, optional);
7658 get_property_type (MonoProperty *prop)
7660 MonoMethodSignature *sig;
7662 sig = mono_method_signature (prop->get);
7664 } else if (prop->set) {
7665 sig = mono_method_signature (prop->set);
7666 return sig->params [sig->param_count - 1];
7671 ICALL_EXPORT MonoArray*
7672 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7674 MonoType *type = get_property_type (property->property);
7675 MonoImage *image = property->klass->image;
7679 return type_array_from_modifiers (image, type, optional);
7683 *Construct a MonoType suited to be used to decode a constant blob object.
7685 * @type is the target type which will be constructed
7686 * @blob_type is the blob type, for example, that comes from the constant table
7687 * @real_type is the expected constructed type.
7690 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7692 type->type = blob_type;
7693 type->data.klass = NULL;
7694 if (blob_type == MONO_TYPE_CLASS)
7695 type->data.klass = mono_defaults.object_class;
7696 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7697 /* For enums, we need to use the base type */
7698 type->type = MONO_TYPE_VALUETYPE;
7699 type->data.klass = mono_class_from_mono_type (real_type);
7701 type->data.klass = mono_class_from_mono_type (real_type);
7704 ICALL_EXPORT MonoObject*
7705 property_info_get_default_value (MonoReflectionProperty *property)
7708 MonoProperty *prop = property->property;
7709 MonoType *type = get_property_type (prop);
7710 MonoDomain *domain = mono_object_domain (property);
7711 MonoTypeEnum def_type;
7712 const char *def_value;
7715 mono_class_init (prop->parent);
7717 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7718 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7722 def_value = mono_class_get_property_default_value (prop, &def_type);
7724 mono_type_from_blob_type (&blob_type, def_type, type);
7725 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7730 ICALL_EXPORT MonoBoolean
7731 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7734 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7735 MonoCustomAttrInfo *cinfo;
7738 mono_class_init_or_throw (attr_class);
7740 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7741 if (!is_ok (&error)) {
7742 mono_error_set_pending_exception (&error);
7747 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7749 mono_custom_attrs_free (cinfo);
7753 ICALL_EXPORT MonoArray*
7754 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7756 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7761 mono_class_init_or_throw (attr_class);
7763 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7764 if (!mono_error_ok (&error)) {
7765 mono_error_set_pending_exception (&error);
7769 if (mono_loader_get_last_error ()) {
7770 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7777 ICALL_EXPORT MonoArray*
7778 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7782 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7783 mono_error_set_pending_exception (&error);
7788 ICALL_EXPORT MonoString*
7789 ves_icall_Mono_Runtime_GetDisplayName (void)
7792 MonoString *display_name;
7794 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7795 display_name = mono_string_new (mono_domain_get (), info);
7797 return display_name;
7800 ICALL_EXPORT MonoString*
7801 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7804 MonoString *message;
7808 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7809 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7812 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7814 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7815 mono_error_raise_exception (&error);
7822 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7825 char *path_str = mono_string_to_utf8 (path);
7827 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7835 ICALL_EXPORT gpointer
7836 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
7838 return GetCurrentProcess ();
7841 ICALL_EXPORT MonoBoolean
7842 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
7844 return GetExitCodeProcess (handle, (guint32*) exitcode);
7847 ICALL_EXPORT MonoBoolean
7848 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
7850 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
7851 return CloseHandle (handle);
7853 return CloseProcess (handle);
7857 ICALL_EXPORT MonoBoolean
7858 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
7860 return TerminateProcess (handle, exitcode);
7864 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
7866 return WaitForInputIdle (handle, milliseconds);
7869 ICALL_EXPORT MonoBoolean
7870 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
7872 return GetProcessWorkingSetSize (handle, min, max);
7875 ICALL_EXPORT MonoBoolean
7876 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
7878 return SetProcessWorkingSetSize (handle, min, max);
7881 ICALL_EXPORT MonoBoolean
7882 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
7884 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
7888 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
7890 return mono_process_current_pid ();
7894 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
7896 return GetPriorityClass (handle);
7899 ICALL_EXPORT MonoBoolean
7900 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
7902 return SetPriorityClass (handle, priorityClass);
7905 #ifndef DISABLE_ICALL_TABLES
7907 #define ICALL_TYPE(id,name,first)
7908 #define ICALL(id,name,func) Icall_ ## id,
7911 #include "metadata/icall-def.h"
7917 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7918 #define ICALL(id,name,func)
7920 #include "metadata/icall-def.h"
7926 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7927 #define ICALL(id,name,func)
7929 guint16 first_icall;
7932 static const IcallTypeDesc
7933 icall_type_descs [] = {
7934 #include "metadata/icall-def.h"
7938 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7941 #define ICALL_TYPE(id,name,first)
7944 #ifdef HAVE_ARRAY_ELEM_INIT
7945 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7946 #define MSGSTRFIELD1(line) str##line
7948 static const struct msgstrtn_t {
7949 #define ICALL(id,name,func)
7951 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7952 #include "metadata/icall-def.h"
7954 } icall_type_names_str = {
7955 #define ICALL_TYPE(id,name,first) (name),
7956 #include "metadata/icall-def.h"
7959 static const guint16 icall_type_names_idx [] = {
7960 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7961 #include "metadata/icall-def.h"
7964 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7966 static const struct msgstr_t {
7968 #define ICALL_TYPE(id,name,first)
7969 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7970 #include "metadata/icall-def.h"
7972 } icall_names_str = {
7973 #define ICALL(id,name,func) (name),
7974 #include "metadata/icall-def.h"
7977 static const guint16 icall_names_idx [] = {
7978 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7979 #include "metadata/icall-def.h"
7982 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7988 #define ICALL_TYPE(id,name,first) name,
7989 #define ICALL(id,name,func)
7990 static const char* const
7991 icall_type_names [] = {
7992 #include "metadata/icall-def.h"
7996 #define icall_type_name_get(id) (icall_type_names [(id)])
8000 #define ICALL_TYPE(id,name,first)
8001 #define ICALL(id,name,func) name,
8002 static const char* const
8004 #include "metadata/icall-def.h"
8007 #define icall_name_get(id) icall_names [(id)]
8009 #endif /* !HAVE_ARRAY_ELEM_INIT */
8013 #define ICALL_TYPE(id,name,first)
8014 #define ICALL(id,name,func) func,
8015 static const gconstpointer
8016 icall_functions [] = {
8017 #include "metadata/icall-def.h"
8021 #ifdef ENABLE_ICALL_SYMBOL_MAP
8024 #define ICALL_TYPE(id,name,first)
8025 #define ICALL(id,name,func) #func,
8026 static const gconstpointer
8027 icall_symbols [] = {
8028 #include "metadata/icall-def.h"
8033 #endif /* DISABLE_ICALL_TABLES */
8035 static mono_mutex_t icall_mutex;
8036 static GHashTable *icall_hash = NULL;
8037 static GHashTable *jit_icall_hash_name = NULL;
8038 static GHashTable *jit_icall_hash_addr = NULL;
8041 mono_icall_init (void)
8043 #ifndef DISABLE_ICALL_TABLES
8046 /* check that tables are sorted: disable in release */
8049 const char *prev_class = NULL;
8050 const char *prev_method;
8052 for (i = 0; i < Icall_type_num; ++i) {
8053 const IcallTypeDesc *desc;
8056 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8057 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8058 prev_class = icall_type_name_get (i);
8059 desc = &icall_type_descs [i];
8060 num_icalls = icall_desc_num_icalls (desc);
8061 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8062 for (j = 0; j < num_icalls; ++j) {
8063 const char *methodn = icall_name_get (desc->first_icall + j);
8064 if (prev_method && strcmp (prev_method, methodn) >= 0)
8065 g_print ("method %s should come before method %s\n", methodn, prev_method);
8066 prev_method = methodn;
8072 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8073 mono_os_mutex_init (&icall_mutex);
8077 mono_icall_lock (void)
8079 mono_locks_os_acquire (&icall_mutex, IcallLock);
8083 mono_icall_unlock (void)
8085 mono_locks_os_release (&icall_mutex, IcallLock);
8089 mono_icall_cleanup (void)
8091 g_hash_table_destroy (icall_hash);
8092 g_hash_table_destroy (jit_icall_hash_name);
8093 g_hash_table_destroy (jit_icall_hash_addr);
8094 mono_os_mutex_destroy (&icall_mutex);
8098 * mono_add_internal_call:
8099 * @name: method specification to surface to the managed world
8100 * @method: pointer to a C method to invoke when the method is called
8102 * This method surfaces the C function pointed by @method as a method
8103 * that has been surfaced in managed code with the method specified in
8104 * @name as an internal call.
8106 * Internal calls are surfaced to all app domains loaded and they are
8107 * accessibly by a type with the specified name.
8109 * You must provide a fully qualified type name, that is namespaces
8110 * and type name, followed by a colon and the method name, with an
8111 * optional signature to bind.
8113 * For example, the following are all valid declarations:
8115 * "MyApp.Services.ScriptService:Accelerate"
8116 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8118 * You use method parameters in cases where there might be more than
8119 * one surface method to managed code. That way you can register different
8120 * internal calls for different method overloads.
8122 * The internal calls are invoked with no marshalling. This means that .NET
8123 * types like System.String are exposed as `MonoString *` parameters. This is
8124 * different than the way that strings are surfaced in P/Invoke.
8126 * For more information on how the parameters are marshalled, see the
8127 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8130 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8131 * reference for more information on the format of method descriptions.
8134 mono_add_internal_call (const char *name, gconstpointer method)
8138 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8140 mono_icall_unlock ();
8143 #ifndef DISABLE_ICALL_TABLES
8145 #ifdef HAVE_ARRAY_ELEM_INIT
8147 compare_method_imap (const void *key, const void *elem)
8149 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8150 return strcmp (key, method_name);
8154 find_method_icall (const IcallTypeDesc *imap, const char *name)
8156 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);
8159 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8163 compare_class_imap (const void *key, const void *elem)
8165 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8166 return strcmp (key, class_name);
8169 static const IcallTypeDesc*
8170 find_class_icalls (const char *name)
8172 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);
8175 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8178 #else /* HAVE_ARRAY_ELEM_INIT */
8181 compare_method_imap (const void *key, const void *elem)
8183 const char** method_name = (const char**)elem;
8184 return strcmp (key, *method_name);
8188 find_method_icall (const IcallTypeDesc *imap, const char *name)
8190 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8193 return (gpointer)icall_functions [(nameslot - icall_names)];
8197 compare_class_imap (const void *key, const void *elem)
8199 const char** class_name = (const char**)elem;
8200 return strcmp (key, *class_name);
8203 static const IcallTypeDesc*
8204 find_class_icalls (const char *name)
8206 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8209 return &icall_type_descs [nameslot - icall_type_names];
8212 #endif /* HAVE_ARRAY_ELEM_INIT */
8214 #endif /* DISABLE_ICALL_TABLES */
8217 * we should probably export this as an helper (handle nested types).
8218 * Returns the number of chars written in buf.
8221 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8223 int nspacelen, cnamelen;
8224 nspacelen = strlen (klass->name_space);
8225 cnamelen = strlen (klass->name);
8226 if (nspacelen + cnamelen + 2 > bufsize)
8229 memcpy (buf, klass->name_space, nspacelen);
8230 buf [nspacelen ++] = '.';
8232 memcpy (buf + nspacelen, klass->name, cnamelen);
8233 buf [nspacelen + cnamelen] = 0;
8234 return nspacelen + cnamelen;
8237 #ifdef DISABLE_ICALL_TABLES
8239 no_icall_table (void)
8241 g_assert_not_reached ();
8246 mono_lookup_internal_call (MonoMethod *method)
8251 int typelen = 0, mlen, siglen;
8253 #ifndef DISABLE_ICALL_TABLES
8254 const IcallTypeDesc *imap = NULL;
8257 g_assert (method != NULL);
8259 if (method->is_inflated)
8260 method = ((MonoMethodInflated *) method)->declaring;
8262 if (method->klass->nested_in) {
8263 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8267 mname [pos++] = '/';
8270 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8276 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8281 #ifndef DISABLE_ICALL_TABLES
8282 imap = find_class_icalls (mname);
8285 mname [typelen] = ':';
8286 mname [typelen + 1] = ':';
8288 mlen = strlen (method->name);
8289 memcpy (mname + typelen + 2, method->name, mlen);
8290 sigstart = mname + typelen + 2 + mlen;
8293 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8294 siglen = strlen (tmpsig);
8295 if (typelen + mlen + siglen + 6 > sizeof (mname))
8298 memcpy (sigstart + 1, tmpsig, siglen);
8299 sigstart [siglen + 1] = ')';
8300 sigstart [siglen + 2] = 0;
8305 res = g_hash_table_lookup (icall_hash, mname);
8307 mono_icall_unlock ();;
8310 /* try without signature */
8312 res = g_hash_table_lookup (icall_hash, mname);
8314 mono_icall_unlock ();
8318 #ifdef DISABLE_ICALL_TABLES
8319 mono_icall_unlock ();
8320 /* Fail only when the result is actually used */
8321 /* mono_marshal_get_native_wrapper () depends on this */
8322 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8323 return ves_icall_System_String_ctor_RedirectToCreateString;
8325 return no_icall_table;
8327 /* it wasn't found in the static call tables */
8329 mono_icall_unlock ();
8332 res = find_method_icall (imap, sigstart - mlen);
8334 mono_icall_unlock ();
8337 /* try _with_ signature */
8339 res = find_method_icall (imap, sigstart - mlen);
8341 mono_icall_unlock ();
8345 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8346 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8347 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8348 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8349 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");
8350 g_print ("If you see other errors or faults after this message they are probably related\n");
8351 g_print ("and you need to fix your mono install first.\n");
8353 mono_icall_unlock ();
8359 #ifdef ENABLE_ICALL_SYMBOL_MAP
8361 func_cmp (gconstpointer key, gconstpointer p)
8363 return (gsize)key - (gsize)*(gsize*)p;
8368 * mono_lookup_icall_symbol:
8370 * Given the icall METHOD, returns its C symbol.
8373 mono_lookup_icall_symbol (MonoMethod *m)
8375 #ifdef DISABLE_ICALL_TABLES
8376 g_assert_not_reached ();
8379 #ifdef ENABLE_ICALL_SYMBOL_MAP
8383 static gconstpointer *functions_sorted;
8384 static const char**symbols_sorted;
8385 static gboolean inited;
8390 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8391 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8392 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8393 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8394 /* Bubble sort the two arrays */
8398 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8399 if (functions_sorted [i] > functions_sorted [i + 1]) {
8402 tmp = functions_sorted [i];
8403 functions_sorted [i] = functions_sorted [i + 1];
8404 functions_sorted [i + 1] = tmp;
8405 tmp = symbols_sorted [i];
8406 symbols_sorted [i] = symbols_sorted [i + 1];
8407 symbols_sorted [i + 1] = tmp;
8414 func = mono_lookup_internal_call (m);
8417 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8421 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8423 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8424 g_assert_not_reached ();
8431 type_from_typename (char *type_name)
8433 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8435 if (!strcmp (type_name, "int"))
8436 klass = mono_defaults.int_class;
8437 else if (!strcmp (type_name, "ptr"))
8438 klass = mono_defaults.int_class;
8439 else if (!strcmp (type_name, "void"))
8440 klass = mono_defaults.void_class;
8441 else if (!strcmp (type_name, "int32"))
8442 klass = mono_defaults.int32_class;
8443 else if (!strcmp (type_name, "uint32"))
8444 klass = mono_defaults.uint32_class;
8445 else if (!strcmp (type_name, "int8"))
8446 klass = mono_defaults.sbyte_class;
8447 else if (!strcmp (type_name, "uint8"))
8448 klass = mono_defaults.byte_class;
8449 else if (!strcmp (type_name, "int16"))
8450 klass = mono_defaults.int16_class;
8451 else if (!strcmp (type_name, "uint16"))
8452 klass = mono_defaults.uint16_class;
8453 else if (!strcmp (type_name, "long"))
8454 klass = mono_defaults.int64_class;
8455 else if (!strcmp (type_name, "ulong"))
8456 klass = mono_defaults.uint64_class;
8457 else if (!strcmp (type_name, "float"))
8458 klass = mono_defaults.single_class;
8459 else if (!strcmp (type_name, "double"))
8460 klass = mono_defaults.double_class;
8461 else if (!strcmp (type_name, "object"))
8462 klass = mono_defaults.object_class;
8463 else if (!strcmp (type_name, "obj"))
8464 klass = mono_defaults.object_class;
8465 else if (!strcmp (type_name, "string"))
8466 klass = mono_defaults.string_class;
8467 else if (!strcmp (type_name, "bool"))
8468 klass = mono_defaults.boolean_class;
8469 else if (!strcmp (type_name, "boolean"))
8470 klass = mono_defaults.boolean_class;
8472 g_error ("%s", type_name);
8473 g_assert_not_reached ();
8475 return &klass->byval_arg;
8479 * LOCKING: Take the corlib image lock.
8481 MonoMethodSignature*
8482 mono_create_icall_signature (const char *sigstr)
8487 MonoMethodSignature *res, *res2;
8488 MonoImage *corlib = mono_defaults.corlib;
8490 mono_image_lock (corlib);
8491 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8492 mono_image_unlock (corlib);
8497 parts = g_strsplit (sigstr, " ", 256);
8506 res = mono_metadata_signature_alloc (corlib, len - 1);
8511 * Under windows, the default pinvoke calling convention is STDCALL but
8514 res->call_convention = MONO_CALL_C;
8517 res->ret = type_from_typename (parts [0]);
8518 for (i = 1; i < len; ++i) {
8519 res->params [i - 1] = type_from_typename (parts [i]);
8524 mono_image_lock (corlib);
8525 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8527 res = res2; /*Value is allocated in the image pool*/
8529 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8530 mono_image_unlock (corlib);
8536 mono_find_jit_icall_by_name (const char *name)
8538 MonoJitICallInfo *info;
8539 g_assert (jit_icall_hash_name);
8542 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8543 mono_icall_unlock ();
8548 mono_find_jit_icall_by_addr (gconstpointer addr)
8550 MonoJitICallInfo *info;
8551 g_assert (jit_icall_hash_addr);
8554 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8555 mono_icall_unlock ();
8561 * mono_get_jit_icall_info:
8563 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8564 * caller should access it while holding the icall lock.
8567 mono_get_jit_icall_info (void)
8569 return jit_icall_hash_name;
8573 * mono_lookup_jit_icall_symbol:
8575 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8578 mono_lookup_jit_icall_symbol (const char *name)
8580 MonoJitICallInfo *info;
8581 const char *res = NULL;
8584 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8586 res = info->c_symbol;
8587 mono_icall_unlock ();
8592 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8595 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8596 mono_icall_unlock ();
8600 * 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
8601 * icalls without wrappers in some cases.
8604 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8606 MonoJitICallInfo *info;
8613 if (!jit_icall_hash_name) {
8614 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8615 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8618 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8619 g_warning ("jit icall already defined \"%s\"\n", name);
8620 g_assert_not_reached ();
8623 info = g_new0 (MonoJitICallInfo, 1);
8628 info->c_symbol = c_symbol;
8629 info->no_raise = no_raise;
8632 info->wrapper = func;
8634 info->wrapper = NULL;
8637 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8638 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8640 mono_icall_unlock ();
8645 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8647 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);