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/exception-internals.h>
49 #include <mono/metadata/file-io.h>
50 #include <mono/metadata/console-io.h>
51 #include <mono/metadata/mono-route.h>
52 #include <mono/metadata/socket-io.h>
53 #include <mono/metadata/mono-endian.h>
54 #include <mono/metadata/tokentype.h>
55 #include <mono/metadata/domain-internals.h>
56 #include <mono/metadata/metadata-internals.h>
57 #include <mono/metadata/class-internals.h>
58 #include <mono/metadata/reflection-internals.h>
59 #include <mono/metadata/marshal.h>
60 #include <mono/metadata/gc-internals.h>
61 #include <mono/metadata/mono-gc.h>
62 #include <mono/metadata/rand.h>
63 #include <mono/metadata/sysmath.h>
64 #include <mono/metadata/string-icalls.h>
65 #include <mono/metadata/debug-helpers.h>
66 #include <mono/metadata/process.h>
67 #include <mono/metadata/environment.h>
68 #include <mono/metadata/profiler-private.h>
69 #include <mono/metadata/locales.h>
70 #include <mono/metadata/filewatcher.h>
71 #include <mono/metadata/security.h>
72 #include <mono/metadata/mono-config.h>
73 #include <mono/metadata/cil-coff.h>
74 #include <mono/metadata/number-formatter.h>
75 #include <mono/metadata/security-manager.h>
76 #include <mono/metadata/security-core-clr.h>
77 #include <mono/metadata/mono-perfcounters.h>
78 #include <mono/metadata/mono-debug.h>
79 #include <mono/metadata/mono-ptr-array.h>
80 #include <mono/metadata/verify-internals.h>
81 #include <mono/metadata/runtime.h>
82 #include <mono/metadata/file-mmap.h>
83 #include <mono/metadata/seq-points-data.h>
84 #include <mono/io-layer/io-layer.h>
85 #include <mono/utils/monobitset.h>
86 #include <mono/utils/mono-time.h>
87 #include <mono/utils/mono-proclib.h>
88 #include <mono/utils/mono-string.h>
89 #include <mono/utils/mono-error-internals.h>
90 #include <mono/utils/mono-mmap.h>
91 #include <mono/utils/mono-io-portability.h>
92 #include <mono/utils/mono-digest.h>
93 #include <mono/utils/bsearch.h>
94 #include <mono/utils/mono-os-mutex.h>
95 #include <mono/utils/mono-threads.h>
97 #if defined (HOST_WIN32)
101 #include "decimal-ms.h"
102 #include "number-ms.h"
104 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
105 #include <sys/utsname.h>
108 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
110 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
112 /* Lazy class loading functions */
113 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
114 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
115 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
116 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
121 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
123 static inline MonoBoolean
124 is_generic_parameter (MonoType *type)
126 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
130 mono_class_init_checked (MonoClass *klass, MonoError *error)
132 mono_error_init (error);
134 if (!mono_class_init (klass))
135 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
138 ICALL_EXPORT MonoObject *
139 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
145 ac = (MonoClass *)arr->obj.vtable->klass;
147 esize = mono_array_element_size (ac);
148 ea = (gpointer*)((char*)arr->vector + (pos * esize));
150 if (ac->element_class->valuetype)
151 return mono_value_box (arr->obj.vtable->domain, ac->element_class, ea);
153 return (MonoObject *)*ea;
156 ICALL_EXPORT MonoObject *
157 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
163 MONO_CHECK_ARG_NULL (idxs, NULL);
166 ic = (MonoClass *)io->obj.vtable->klass;
168 ac = (MonoClass *)arr->obj.vtable->klass;
170 g_assert (ic->rank == 1);
171 if (io->bounds != NULL || io->max_length != ac->rank) {
172 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
176 ind = (gint32 *)io->vector;
178 if (arr->bounds == NULL) {
179 if (*ind < 0 || *ind >= arr->max_length) {
180 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
184 return ves_icall_System_Array_GetValueImpl (arr, *ind);
187 for (i = 0; i < ac->rank; i++) {
188 if ((ind [i] < arr->bounds [i].lower_bound) ||
189 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
190 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
195 pos = ind [0] - arr->bounds [0].lower_bound;
196 for (i = 1; i < ac->rank; i++)
197 pos = pos * arr->bounds [i].length + ind [i] -
198 arr->bounds [i].lower_bound;
200 return ves_icall_System_Array_GetValueImpl (arr, pos);
204 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
206 MonoClass *ac, *vc, *ec;
216 vc = value->vtable->klass;
220 ac = arr->obj.vtable->klass;
221 ec = ac->element_class;
223 esize = mono_array_element_size (ac);
224 ea = (gpointer*)((char*)arr->vector + (pos * esize));
225 va = (gpointer*)((char*)value + sizeof (MonoObject));
227 if (mono_class_is_nullable (ec)) {
228 mono_nullable_init ((guint8*)ea, value, ec);
233 mono_gc_bzero_atomic (ea, esize);
237 #define NO_WIDENING_CONVERSION G_STMT_START{\
238 mono_set_pending_exception (mono_get_exception_argument ( \
239 "value", "not a widening conversion")); \
243 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
244 if (esize < vsize + (extra)) { \
245 mono_set_pending_exception (mono_get_exception_argument ( \
246 "value", "not a widening conversion")); \
251 #define INVALID_CAST G_STMT_START{ \
252 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
253 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
257 /* Check element (destination) type. */
258 switch (ec->byval_arg.type) {
259 case MONO_TYPE_STRING:
260 switch (vc->byval_arg.type) {
261 case MONO_TYPE_STRING:
267 case MONO_TYPE_BOOLEAN:
268 switch (vc->byval_arg.type) {
269 case MONO_TYPE_BOOLEAN:
282 NO_WIDENING_CONVERSION;
291 if (!ec->valuetype) {
292 if (!mono_object_isinst (value, ec))
294 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
298 if (mono_object_isinst (value, ec)) {
299 if (ec->has_references)
300 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
302 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
309 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
311 et = ec->byval_arg.type;
312 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
313 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
315 vt = vc->byval_arg.type;
316 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
317 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
319 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
325 case MONO_TYPE_CHAR: \
326 CHECK_WIDENING_CONVERSION(0); \
327 *(etype *) ea = (etype) u64; \
329 /* You can't assign a signed value to an unsigned array. */ \
334 /* You can't assign a floating point number to an integer array. */ \
337 NO_WIDENING_CONVERSION; \
341 #define ASSIGN_SIGNED(etype) G_STMT_START{\
347 CHECK_WIDENING_CONVERSION(0); \
348 *(etype *) ea = (etype) i64; \
350 /* You can assign an unsigned value to a signed array if the array's */ \
351 /* element size is larger than the value size. */ \
356 case MONO_TYPE_CHAR: \
357 CHECK_WIDENING_CONVERSION(1); \
358 *(etype *) ea = (etype) u64; \
360 /* You can't assign a floating point number to an integer array. */ \
363 NO_WIDENING_CONVERSION; \
367 #define ASSIGN_REAL(etype) G_STMT_START{\
371 CHECK_WIDENING_CONVERSION(0); \
372 *(etype *) ea = (etype) r64; \
374 /* All integer values fit into a floating point array, so we don't */ \
375 /* need to CHECK_WIDENING_CONVERSION here. */ \
380 *(etype *) ea = (etype) i64; \
386 case MONO_TYPE_CHAR: \
387 *(etype *) ea = (etype) u64; \
394 u64 = *(guint8 *) va;
397 u64 = *(guint16 *) va;
400 u64 = *(guint32 *) va;
403 u64 = *(guint64 *) va;
409 i64 = *(gint16 *) va;
412 i64 = *(gint32 *) va;
415 i64 = *(gint64 *) va;
418 r64 = *(gfloat *) va;
421 r64 = *(gdouble *) va;
424 u64 = *(guint16 *) va;
426 case MONO_TYPE_BOOLEAN:
427 /* Boolean is only compatible with itself. */
440 NO_WIDENING_CONVERSION;
447 /* If we can't do a direct copy, let's try a widening conversion. */
450 ASSIGN_UNSIGNED (guint16);
452 ASSIGN_UNSIGNED (guint8);
454 ASSIGN_UNSIGNED (guint16);
456 ASSIGN_UNSIGNED (guint32);
458 ASSIGN_UNSIGNED (guint64);
460 ASSIGN_SIGNED (gint8);
462 ASSIGN_SIGNED (gint16);
464 ASSIGN_SIGNED (gint32);
466 ASSIGN_SIGNED (gint64);
468 ASSIGN_REAL (gfloat);
470 ASSIGN_REAL (gdouble);
474 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
478 #undef NO_WIDENING_CONVERSION
479 #undef CHECK_WIDENING_CONVERSION
480 #undef ASSIGN_UNSIGNED
486 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
492 MONO_CHECK_ARG_NULL (idxs,);
494 ic = idxs->obj.vtable->klass;
495 ac = arr->obj.vtable->klass;
497 g_assert (ic->rank == 1);
498 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
499 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
503 ind = (gint32 *)idxs->vector;
505 if (arr->bounds == NULL) {
506 if (*ind < 0 || *ind >= arr->max_length) {
507 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
511 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
515 for (i = 0; i < ac->rank; i++)
516 if ((ind [i] < arr->bounds [i].lower_bound) ||
517 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
518 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
522 pos = ind [0] - arr->bounds [0].lower_bound;
523 for (i = 1; i < ac->rank; i++)
524 pos = pos * arr->bounds [i].length + ind [i] -
525 arr->bounds [i].lower_bound;
527 ves_icall_System_Array_SetValueImpl (arr, value, pos);
530 ICALL_EXPORT MonoArray *
531 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
534 MonoClass *aklass, *klass;
537 gboolean bounded = FALSE;
539 MONO_CHECK_ARG_NULL (type, NULL);
540 MONO_CHECK_ARG_NULL (lengths, NULL);
542 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
544 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
546 for (i = 0; i < mono_array_length (lengths); i++) {
547 if (mono_array_get (lengths, gint32, i) < 0) {
548 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
553 klass = mono_class_from_mono_type (type->type);
554 mono_class_init_checked (klass, &error);
555 mono_error_raise_exception (&error);
557 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
558 /* vectors are not the same as one dimensional arrays with no-zero bounds */
563 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
565 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
566 for (i = 0; i < aklass->rank; ++i) {
567 sizes [i] = mono_array_get (lengths, guint32, i);
569 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
571 sizes [i + aklass->rank] = 0;
574 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
575 mono_error_set_pending_exception (&error);
580 ICALL_EXPORT MonoArray *
581 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
584 MonoClass *aklass, *klass;
587 gboolean bounded = FALSE;
589 MONO_CHECK_ARG_NULL (type, NULL);
590 MONO_CHECK_ARG_NULL (lengths, NULL);
592 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
594 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
596 for (i = 0; i < mono_array_length (lengths); i++) {
597 if ((mono_array_get (lengths, gint64, i) < 0) ||
598 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
599 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
604 klass = mono_class_from_mono_type (type->type);
605 mono_class_init_checked (klass, &error);
606 mono_error_raise_exception (&error);
608 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
609 /* vectors are not the same as one dimensional arrays with no-zero bounds */
614 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
616 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
617 for (i = 0; i < aklass->rank; ++i) {
618 sizes [i] = mono_array_get (lengths, guint64, i);
620 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
622 sizes [i + aklass->rank] = 0;
625 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
626 mono_error_set_pending_exception (&error);
632 ves_icall_System_Array_GetRank (MonoObject *arr)
634 return arr->vtable->klass->rank;
638 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
640 gint32 rank = arr->obj.vtable->klass->rank;
643 if ((dimension < 0) || (dimension >= rank)) {
644 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
648 if (arr->bounds == NULL)
649 length = arr->max_length;
651 length = arr->bounds [dimension].length;
653 #ifdef MONO_BIG_ARRAYS
654 if (length > G_MAXINT32) {
655 mono_set_pending_exception (mono_get_exception_overflow ());
663 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
665 gint32 rank = arr->obj.vtable->klass->rank;
667 if ((dimension < 0) || (dimension >= rank)) {
668 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
672 if (arr->bounds == NULL)
673 return arr->max_length;
675 return arr->bounds [dimension].length;
679 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
681 gint32 rank = arr->obj.vtable->klass->rank;
683 if ((dimension < 0) || (dimension >= rank)) {
684 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
688 if (arr->bounds == NULL)
691 return arr->bounds [dimension].lower_bound;
695 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
697 int sz = mono_array_element_size (mono_object_class (arr));
698 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
701 ICALL_EXPORT gboolean
702 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
707 MonoVTable *src_vtable;
708 MonoVTable *dest_vtable;
709 MonoClass *src_class;
710 MonoClass *dest_class;
712 src_vtable = source->obj.vtable;
713 dest_vtable = dest->obj.vtable;
715 if (src_vtable->rank != dest_vtable->rank)
718 if (source->bounds || dest->bounds)
721 /* there's no integer overflow since mono_array_length returns an unsigned integer */
722 if ((dest_idx + length > mono_array_length_fast (dest)) ||
723 (source_idx + length > mono_array_length_fast (source)))
726 src_class = src_vtable->klass->element_class;
727 dest_class = dest_vtable->klass->element_class;
730 * Handle common cases.
733 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
734 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
736 if (src_class == mono_defaults.object_class && dest_class->valuetype)
739 /* Check if we're copying a char[] <==> (u)short[] */
740 if (src_class != dest_class) {
741 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
744 /* 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. */
745 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
749 if (dest_class->valuetype) {
750 element_size = mono_array_element_size (source->obj.vtable->klass);
751 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
752 if (dest_class->has_references) {
753 mono_value_copy_array (dest, dest_idx, source_addr, length);
755 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
756 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
759 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
766 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
772 ac = (MonoClass *)arr->obj.vtable->klass;
774 esize = mono_array_element_size (ac);
775 ea = (gpointer*)((char*)arr->vector + (pos * esize));
777 mono_gc_memmove_atomic (value, ea, esize);
781 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
787 ac = (MonoClass *)arr->obj.vtable->klass;
788 ec = ac->element_class;
790 esize = mono_array_element_size (ac);
791 ea = (gpointer*)((char*)arr->vector + (pos * esize));
793 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
794 g_assert (esize == sizeof (gpointer));
795 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
797 g_assert (ec->inited);
798 g_assert (esize == mono_class_value_size (ec, NULL));
799 if (ec->has_references)
800 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
802 mono_gc_memmove_atomic (ea, value, esize);
807 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
809 MonoClass *klass = array->obj.vtable->klass;
810 guint32 size = mono_array_element_size (klass);
811 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
813 const char *field_data;
815 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
816 MonoException *exc = mono_get_exception_argument("array",
817 "Cannot initialize array of non-primitive type.");
818 mono_set_pending_exception (exc);
822 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
823 MonoException *exc = mono_get_exception_argument("field_handle",
824 "Field doesn't have an RVA");
825 mono_set_pending_exception (exc);
829 size *= array->max_length;
830 field_data = mono_field_get_data (field_handle);
832 if (size > mono_type_size (field_handle->type, &align)) {
833 MonoException *exc = mono_get_exception_argument("field_handle",
834 "Field not large enough to fill array");
835 mono_set_pending_exception (exc);
839 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
841 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
842 guint ## n *src = (guint ## n *) field_data; \
844 nEnt = (size / sizeof(guint ## n)); \
846 for (i = 0; i < nEnt; i++) { \
847 data[i] = read ## n (&src[i]); \
851 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
853 switch (type->type) {
870 memcpy (mono_array_addr (array, char, 0), field_data, size);
874 memcpy (mono_array_addr (array, char, 0), field_data, size);
879 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
881 return offsetof (MonoString, chars);
884 ICALL_EXPORT MonoObject *
885 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
887 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
891 MonoObject *ret = mono_object_clone_checked (obj, &error);
892 mono_error_set_pending_exception (&error);
899 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
905 MONO_CHECK_ARG_NULL (handle,);
907 klass = mono_class_from_mono_type (handle);
908 MONO_CHECK_ARG (handle, klass,);
910 if (klass->generic_container)
913 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
914 if (!is_ok (&error)) {
915 mono_error_set_pending_exception (&error);
919 /* This will call the type constructor */
920 if (!mono_runtime_class_init_full (vtable, &error))
921 mono_error_set_pending_exception (&error);
925 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
929 mono_image_check_for_module_cctor (image);
930 if (image->has_module_cctor) {
931 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
932 if (!mono_error_ok (&error)) {
933 mono_error_set_pending_exception (&error);
936 /*It's fine to raise the exception here*/
937 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
938 if (!is_ok (&error)) {
939 mono_error_set_pending_exception (&error);
942 if (!mono_runtime_class_init_full (vtable, &error))
943 mono_error_set_pending_exception (&error);
947 ICALL_EXPORT MonoBoolean
948 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
953 /* later make this configurable and per-arch */
954 int min_size = 4096 * 4 * sizeof (void*);
955 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
956 /* if we have no info we are optimistic and assume there is enough room */
960 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
964 current = (guint8 *)&stack_addr;
965 if (current > stack_addr) {
966 if ((current - stack_addr) < min_size)
969 if (current - (stack_addr - stack_size) < min_size)
975 ICALL_EXPORT MonoObject *
976 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
979 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
980 mono_error_set_pending_exception (&error);
986 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
989 MonoObject **values = NULL;
992 gint32 result = (int)(gsize)mono_defaults.int32_class;
993 MonoClassField* field;
996 klass = mono_object_class (this_obj);
998 if (mono_class_num_fields (klass) == 0)
1002 * Compute the starting value of the hashcode for fields of primitive
1003 * types, and return the remaining fields in an array to the managed side.
1004 * This way, we can avoid costly reflection operations in managed code.
1007 while ((field = mono_class_get_fields (klass, &iter))) {
1008 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1010 if (mono_field_is_deleted (field))
1012 /* FIXME: Add more types */
1013 switch (field->type->type) {
1015 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1017 case MONO_TYPE_STRING: {
1019 s = *(MonoString**)((guint8*)this_obj + field->offset);
1021 result ^= mono_string_hash (s);
1026 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1027 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1028 values [count++] = o;
1034 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1035 for (i = 0; i < count; ++i)
1036 mono_array_setref (*fields, i, values [i]);
1043 ICALL_EXPORT MonoBoolean
1044 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1047 MonoObject **values = NULL;
1049 MonoClassField* field;
1053 MONO_CHECK_ARG_NULL (that, FALSE);
1055 if (this_obj->vtable != that->vtable)
1058 klass = mono_object_class (this_obj);
1060 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1061 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1064 * Do the comparison for fields of primitive type and return a result if
1065 * possible. Otherwise, return the remaining fields in an array to the
1066 * managed side. This way, we can avoid costly reflection operations in
1071 while ((field = mono_class_get_fields (klass, &iter))) {
1072 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1074 if (mono_field_is_deleted (field))
1076 /* FIXME: Add more types */
1077 switch (field->type->type) {
1080 case MONO_TYPE_BOOLEAN:
1081 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1086 case MONO_TYPE_CHAR:
1087 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1092 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1097 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1101 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1105 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1110 case MONO_TYPE_STRING: {
1111 MonoString *s1, *s2;
1112 guint32 s1len, s2len;
1113 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1114 s2 = *(MonoString**)((guint8*)that + field->offset);
1117 if ((s1 == NULL) || (s2 == NULL))
1119 s1len = mono_string_length (s1);
1120 s2len = mono_string_length (s2);
1124 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1130 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1131 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1132 values [count++] = o;
1133 o = mono_field_get_value_object (mono_object_domain (this_obj), field, that);
1134 values [count++] = o;
1137 if (klass->enumtype)
1138 /* enums only have one non-static field */
1144 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1145 for (i = 0; i < count; ++i)
1146 mono_array_setref_fast (*fields, i, values [i]);
1153 ICALL_EXPORT MonoReflectionType *
1154 ves_icall_System_Object_GetType (MonoObject *obj)
1157 MonoReflectionType *ret;
1158 #ifndef DISABLE_REMOTING
1159 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1160 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1163 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1165 mono_error_raise_exception (&error);
1171 ves_icall_MonoType_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1173 mtype->type = &obj->vtable->klass->byval_arg;
1174 g_assert (mtype->type->type);
1178 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1180 MONO_CHECK_ARG_NULL (obj, 0);
1183 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1184 mono_error_raise_exception (&error);
1189 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1190 MonoReflectionMethod *method,
1191 MonoArray *opt_param_types)
1193 MONO_CHECK_ARG_NULL (method, 0);
1196 gint32 result = mono_image_create_method_token (
1197 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1198 mono_error_raise_exception (&error);
1203 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1206 mono_image_create_pefile (mb, file, &error);
1207 mono_error_raise_exception (&error);
1211 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1214 if (!mono_image_build_metadata (mb, &error))
1215 mono_error_raise_exception (&error);
1219 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1221 mono_image_register_token (mb->dynamic_image, token, obj);
1224 ICALL_EXPORT MonoObject*
1225 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1229 mono_loader_lock ();
1230 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1231 mono_loader_unlock ();
1237 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1239 MonoMethod **dest = (MonoMethod **)data;
1241 /* skip unmanaged frames */
1257 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1259 MonoMethod **dest = (MonoMethod **)data;
1261 /* skip unmanaged frames */
1266 if (!strcmp (m->klass->name_space, "System.Reflection"))
1275 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1277 MonoMethod **dest = (MonoMethod **)data;
1279 /* skip unmanaged frames */
1283 if (m->wrapper_type != MONO_WRAPPER_NONE)
1286 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1300 static MonoReflectionType *
1301 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1303 MonoMethod *m, *dest;
1305 MonoType *type = NULL;
1306 MonoAssembly *assembly = NULL;
1307 gboolean type_resolve = FALSE;
1309 mono_error_init (error);
1312 * We must compute the calling assembly as type loading must happen under a metadata context.
1313 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1314 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1316 m = mono_method_get_last_managed ();
1319 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1324 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1325 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1326 * to crash. This only seems to happen in some strange remoting
1327 * scenarios and I was unable to figure out what's happening there.
1328 * Dec 10, 2005 - Martin.
1332 assembly = dest->klass->image->assembly;
1333 type_resolve = TRUE;
1335 g_warning (G_STRLOC);
1338 if (info->assembly.name)
1339 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1343 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1344 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1347 if (!info->assembly.name && !type) /* try mscorlib */
1348 type = mono_reflection_get_type (NULL, info, ignoreCase, &type_resolve);
1350 if (assembly && !type && type_resolve) {
1351 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1352 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1358 return mono_type_get_object_checked (mono_domain_get (), type, error);
1361 ICALL_EXPORT MonoReflectionType*
1362 ves_icall_System_Type_internal_from_name (MonoString *name,
1363 MonoBoolean throwOnError,
1364 MonoBoolean ignoreCase)
1367 char *str = mono_string_to_utf8 (name);
1368 MonoTypeNameParse info;
1369 MonoReflectionType *type;
1372 parsedOk = mono_reflection_parse_type (str, &info);
1374 /* mono_reflection_parse_type() mangles the string */
1376 mono_reflection_free_type_info (&info);
1379 mono_set_pending_exception (mono_get_exception_argument("typeName", "failed parse"));
1384 type = type_from_parsed_name (&info, ignoreCase, &error);
1386 mono_reflection_free_type_info (&info);
1389 if (!mono_error_ok (&error)) {
1391 mono_error_set_pending_exception (&error);
1393 mono_error_cleanup (&error);
1398 MonoException *e = NULL;
1401 e = mono_get_exception_type_load (name, NULL);
1403 mono_loader_clear_error ();
1405 mono_set_pending_exception (e);
1414 ICALL_EXPORT MonoReflectionType*
1415 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1418 MonoReflectionType *ret;
1419 MonoDomain *domain = mono_domain_get ();
1421 ret = mono_type_get_object_checked (domain, handle, &error);
1422 mono_error_raise_exception (&error);
1427 /* System.TypeCode */
1446 TYPECODE_STRING = 18
1449 ICALL_EXPORT guint32
1450 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1452 int t = type->type->type;
1454 if (type->type->byref)
1455 return TYPECODE_OBJECT;
1459 case MONO_TYPE_VOID:
1460 return TYPECODE_OBJECT;
1461 case MONO_TYPE_BOOLEAN:
1462 return TYPECODE_BOOLEAN;
1464 return TYPECODE_BYTE;
1466 return TYPECODE_SBYTE;
1468 return TYPECODE_UINT16;
1470 return TYPECODE_INT16;
1471 case MONO_TYPE_CHAR:
1472 return TYPECODE_CHAR;
1476 return TYPECODE_OBJECT;
1478 return TYPECODE_UINT32;
1480 return TYPECODE_INT32;
1482 return TYPECODE_UINT64;
1484 return TYPECODE_INT64;
1486 return TYPECODE_SINGLE;
1488 return TYPECODE_DOUBLE;
1489 case MONO_TYPE_VALUETYPE: {
1490 MonoClass *klass = type->type->data.klass;
1492 if (klass->enumtype) {
1493 t = mono_class_enum_basetype (klass)->type;
1495 } else if (mono_is_corlib_image (klass->image)) {
1496 if (strcmp (klass->name_space, "System") == 0) {
1497 if (strcmp (klass->name, "Decimal") == 0)
1498 return TYPECODE_DECIMAL;
1499 else if (strcmp (klass->name, "DateTime") == 0)
1500 return TYPECODE_DATETIME;
1503 return TYPECODE_OBJECT;
1505 case MONO_TYPE_STRING:
1506 return TYPECODE_STRING;
1507 case MONO_TYPE_SZARRAY:
1508 case MONO_TYPE_ARRAY:
1509 case MONO_TYPE_OBJECT:
1511 case MONO_TYPE_MVAR:
1512 case MONO_TYPE_TYPEDBYREF:
1513 return TYPECODE_OBJECT;
1514 case MONO_TYPE_CLASS:
1516 MonoClass *klass = type->type->data.klass;
1517 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1518 if (strcmp (klass->name, "DBNull") == 0)
1519 return TYPECODE_DBNULL;
1522 return TYPECODE_OBJECT;
1523 case MONO_TYPE_GENERICINST:
1524 return TYPECODE_OBJECT;
1526 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1532 mono_type_is_primitive (MonoType *type)
1534 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1535 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1539 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1541 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1542 return mono_class_enum_basetype (type->data.klass);
1543 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1544 return mono_class_enum_basetype (type->data.generic_class->container_class);
1548 ICALL_EXPORT guint32
1549 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1554 g_assert (type != NULL);
1556 klass = mono_class_from_mono_type (type->type);
1557 klassc = mono_class_from_mono_type (c->type);
1559 if (type->type->byref ^ c->type->byref)
1562 if (type->type->byref) {
1563 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1564 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1566 klass = mono_class_from_mono_type (t);
1567 klassc = mono_class_from_mono_type (ot);
1569 if (mono_type_is_primitive (t)) {
1570 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1571 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1572 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1573 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1574 return t->type == ot->type;
1576 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1579 if (klass->valuetype)
1580 return klass == klassc;
1581 return klass->valuetype == klassc->valuetype;
1584 return mono_class_is_assignable_from (klass, klassc);
1587 ICALL_EXPORT guint32
1588 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1591 MonoClass *klass = mono_class_from_mono_type (type->type);
1592 mono_class_init_checked (klass, &error);
1593 mono_error_raise_exception (&error);
1594 return mono_object_isinst (obj, klass) != NULL;
1597 ICALL_EXPORT guint32
1598 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1600 MonoClass *klass = mono_class_from_mono_type (type->type);
1601 return klass->flags;
1604 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1605 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1608 MonoClass *klass = field->field->parent;
1609 MonoMarshalType *info;
1613 if (klass->generic_container ||
1614 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1617 ftype = mono_field_get_type (field->field);
1618 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1621 info = mono_marshal_load_type_info (klass);
1623 for (i = 0; i < info->num_fields; ++i) {
1624 if (info->fields [i].field == field->field) {
1625 if (!info->fields [i].mspec)
1628 MonoReflectionMarshalAsAttribute* obj;
1629 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1630 if (!mono_error_ok (&error))
1631 mono_error_set_pending_exception (&error);
1640 ICALL_EXPORT MonoReflectionField*
1641 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1644 gboolean found = FALSE;
1651 klass = handle->parent;
1653 klass = mono_class_from_mono_type (type);
1655 /* Check that the field belongs to the class */
1656 for (k = klass; k; k = k->parent) {
1657 if (k == handle->parent) {
1664 /* The managed code will throw the exception */
1668 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1669 mono_error_raise_exception (&error);
1673 ICALL_EXPORT MonoArray*
1674 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1677 MonoType *type = mono_field_get_type_checked (field->field, &error);
1680 if (!mono_error_ok (&error)) {
1681 mono_error_set_pending_exception (&error);
1685 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1686 mono_error_raise_exception (&error);
1691 vell_icall_get_method_attributes (MonoMethod *method)
1693 return method->flags;
1697 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1700 MonoReflectionType *rt;
1701 MonoDomain *domain = mono_domain_get ();
1702 MonoMethodSignature* sig;
1704 sig = mono_method_signature_checked (method, &error);
1705 if (!mono_error_ok (&error)) {
1706 mono_error_set_pending_exception (&error);
1710 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1711 if (!mono_error_ok (&error)) {
1712 mono_error_set_pending_exception (&error);
1716 MONO_STRUCT_SETREF (info, parent, rt);
1718 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1719 if (!mono_error_ok (&error)) {
1720 mono_error_set_pending_exception (&error);
1724 MONO_STRUCT_SETREF (info, ret, rt);
1726 info->attrs = method->flags;
1727 info->implattrs = method->iflags;
1728 if (sig->call_convention == MONO_CALL_DEFAULT)
1729 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1731 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1736 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1739 ICALL_EXPORT MonoArray*
1740 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1742 MonoDomain *domain = mono_domain_get ();
1744 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1747 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1748 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1751 MonoDomain *domain = mono_domain_get ();
1752 MonoReflectionMarshalAsAttribute* res = NULL;
1753 MonoMarshalSpec **mspecs;
1756 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1757 mono_method_get_marshal_info (method, mspecs);
1760 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1761 if (!mono_error_ok (&error)) {
1762 mono_error_set_pending_exception (&error);
1767 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1769 mono_metadata_free_marshal_spec (mspecs [i]);
1776 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1778 MonoClass *parent = field->field->parent;
1779 if (!parent->size_inited)
1780 mono_class_init (parent);
1781 mono_class_setup_fields_locking (parent);
1783 return field->field->offset - sizeof (MonoObject);
1786 ICALL_EXPORT MonoReflectionType*
1787 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1790 MonoReflectionType *ret;
1793 parent = declaring? field->field->parent: field->klass;
1795 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1796 mono_error_raise_exception (&error);
1802 ICALL_EXPORT MonoObject *
1803 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1805 MonoClass *fklass = field->klass;
1806 MonoClassField *cf = field->field;
1807 MonoDomain *domain = mono_object_domain (field);
1809 if (fklass->image->assembly->ref_only) {
1810 mono_set_pending_exception (mono_get_exception_invalid_operation (
1811 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1815 if (mono_security_core_clr_enabled ())
1816 mono_security_core_clr_ensure_reflection_access_field (cf);
1818 return mono_field_get_value_object (domain, cf, obj);
1822 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1825 MonoClassField *cf = field->field;
1829 if (field->klass->image->assembly->ref_only) {
1830 mono_set_pending_exception (mono_get_exception_invalid_operation (
1831 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1835 if (mono_security_core_clr_enabled ())
1836 mono_security_core_clr_ensure_reflection_access_field (cf);
1838 type = mono_field_get_type_checked (cf, &error);
1839 if (!mono_error_ok (&error)) {
1840 mono_error_set_pending_exception (&error);
1844 v = (gchar *) value;
1846 switch (type->type) {
1849 case MONO_TYPE_BOOLEAN:
1852 case MONO_TYPE_CHAR:
1861 case MONO_TYPE_VALUETYPE:
1864 v += sizeof (MonoObject);
1866 case MONO_TYPE_STRING:
1867 case MONO_TYPE_OBJECT:
1868 case MONO_TYPE_CLASS:
1869 case MONO_TYPE_ARRAY:
1870 case MONO_TYPE_SZARRAY:
1873 case MONO_TYPE_GENERICINST: {
1874 MonoGenericClass *gclass = type->data.generic_class;
1875 g_assert (!gclass->context.class_inst->is_open);
1877 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1878 MonoClass *nklass = mono_class_from_mono_type (type);
1879 MonoObject *nullable;
1882 * Convert the boxed vtype into a Nullable structure.
1883 * This is complicated by the fact that Nullables have
1884 * a variable structure.
1886 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1887 if (!mono_error_ok (&error)) {
1888 mono_error_set_pending_exception (&error);
1892 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1894 v = (gchar *)mono_object_unbox (nullable);
1897 if (gclass->container_class->valuetype && (v != NULL))
1898 v += sizeof (MonoObject);
1902 g_error ("type 0x%x not handled in "
1903 "ves_icall_FieldInfo_SetValueInternal", type->type);
1908 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1909 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
1910 if (!is_ok (&error)) {
1911 mono_error_set_pending_exception (&error);
1914 if (!vtable->initialized) {
1915 if (!mono_runtime_class_init_full (vtable, &error)) {
1916 mono_error_set_pending_exception (&error);
1920 mono_field_static_set_value (vtable, cf, v);
1922 mono_field_set_value (obj, cf, v);
1927 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1936 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1937 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1941 if (MONO_TYPE_IS_REFERENCE (f->type))
1942 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1944 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1947 ICALL_EXPORT MonoObject *
1948 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1950 MonoObject *o = NULL;
1951 MonoClassField *field = rfield->field;
1953 MonoDomain *domain = mono_object_domain (rfield);
1955 MonoTypeEnum def_type;
1956 const char *def_value;
1960 mono_class_init (field->parent);
1962 t = mono_field_get_type_checked (field, &error);
1963 if (!mono_error_ok (&error)) {
1964 mono_error_set_pending_exception (&error);
1968 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
1969 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1973 if (image_is_dynamic (field->parent->image)) {
1974 MonoClass *klass = field->parent;
1975 int fidx = field - klass->fields;
1977 g_assert (fidx >= 0 && fidx < klass->field.count);
1978 g_assert (klass->ext);
1979 g_assert (klass->ext->field_def_values);
1980 def_type = klass->ext->field_def_values [fidx].def_type;
1981 def_value = klass->ext->field_def_values [fidx].data;
1982 if (def_type == MONO_TYPE_END) {
1983 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1987 def_value = mono_class_get_field_default_value (field, &def_type);
1988 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
1990 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1995 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1999 case MONO_TYPE_BOOLEAN:
2002 case MONO_TYPE_CHAR:
2010 case MONO_TYPE_R8: {
2013 /* boxed value type */
2014 t = g_new0 (MonoType, 1);
2016 klass = mono_class_from_mono_type (t);
2018 o = mono_object_new_checked (domain, klass, &error);
2019 if (!mono_error_ok (&error)) {
2020 mono_error_set_pending_exception (&error);
2023 v = ((gchar *) o) + sizeof (MonoObject);
2024 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2027 case MONO_TYPE_STRING:
2028 case MONO_TYPE_CLASS:
2029 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2032 g_assert_not_reached ();
2038 ICALL_EXPORT MonoReflectionType*
2039 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2042 MonoReflectionType *ret;
2045 type = mono_field_get_type_checked (ref_field->field, &error);
2046 if (!mono_error_ok (&error)) {
2047 mono_error_set_pending_exception (&error);
2051 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2052 if (!mono_error_ok (&error)) {
2053 mono_error_set_pending_exception (&error);
2060 /* From MonoProperty.cs */
2062 PInfo_Attributes = 1,
2063 PInfo_GetMethod = 1 << 1,
2064 PInfo_SetMethod = 1 << 2,
2065 PInfo_ReflectedType = 1 << 3,
2066 PInfo_DeclaringType = 1 << 4,
2071 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2074 MonoReflectionType *rt;
2075 MonoReflectionMethod *rm;
2076 MonoDomain *domain = mono_object_domain (property);
2077 const MonoProperty *pproperty = property->property;
2079 if ((req_info & PInfo_ReflectedType) != 0) {
2080 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2081 mono_error_raise_exception (&error);
2083 MONO_STRUCT_SETREF (info, parent, rt);
2085 if ((req_info & PInfo_DeclaringType) != 0) {
2086 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2087 mono_error_raise_exception (&error);
2089 MONO_STRUCT_SETREF (info, declaring_type, rt);
2092 if ((req_info & PInfo_Name) != 0)
2093 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2095 if ((req_info & PInfo_Attributes) != 0)
2096 info->attrs = pproperty->attrs;
2098 if ((req_info & PInfo_GetMethod) != 0) {
2099 if (pproperty->get &&
2100 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2101 pproperty->get->klass == property->klass)) {
2102 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2103 mono_error_raise_exception (&error);
2108 MONO_STRUCT_SETREF (info, get, rm);
2110 if ((req_info & PInfo_SetMethod) != 0) {
2111 if (pproperty->set &&
2112 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2113 pproperty->set->klass == property->klass)) {
2114 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2115 mono_error_raise_exception (&error);
2120 MONO_STRUCT_SETREF (info, set, rm);
2123 * There may be other methods defined for properties, though, it seems they are not exposed
2124 * in the reflection API
2129 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2132 MonoReflectionType *rt;
2133 MonoReflectionMethod *rm;
2134 MonoDomain *domain = mono_object_domain (event);
2136 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2137 mono_error_raise_exception (&error);
2139 MONO_STRUCT_SETREF (info, reflected_type, rt);
2141 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2142 mono_error_raise_exception (&error);
2144 MONO_STRUCT_SETREF (info, declaring_type, rt);
2146 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2147 info->attrs = event->event->attrs;
2149 if (event->event->add) {
2150 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2151 mono_error_raise_exception (&error);
2156 MONO_STRUCT_SETREF (info, add_method, rm);
2158 if (event->event->remove) {
2159 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2160 mono_error_raise_exception (&error);
2165 MONO_STRUCT_SETREF (info, remove_method, rm);
2167 if (event->event->raise) {
2168 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2169 mono_error_raise_exception (&error);
2174 MONO_STRUCT_SETREF (info, raise_method, rm);
2176 #ifndef MONO_SMALL_CONFIG
2177 if (event->event->other) {
2179 while (event->event->other [n])
2181 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2183 for (i = 0; i < n; i++) {
2184 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2185 mono_error_raise_exception (&error);
2186 mono_array_setref (info->other_methods, i, rm);
2193 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2198 mono_class_setup_interfaces (klass, error);
2199 if (!mono_error_ok (error))
2202 for (i = 0; i < klass->interface_count; i++) {
2203 ic = klass->interfaces [i];
2204 g_hash_table_insert (ifaces, ic, ic);
2206 collect_interfaces (ic, ifaces, error);
2207 if (!mono_error_ok (error))
2213 MonoArray *iface_array;
2214 MonoGenericContext *context;
2218 } FillIfaceArrayData;
2221 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2223 MonoReflectionType *rt;
2224 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2225 MonoClass *ic = (MonoClass *)key;
2226 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2228 if (!mono_error_ok (data->error))
2231 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2232 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2233 if (!mono_error_ok (data->error))
2237 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2238 if (!mono_error_ok (data->error))
2241 mono_array_setref (data->iface_array, data->next_idx++, rt);
2244 mono_metadata_free_type (inflated);
2248 get_interfaces_hash (gconstpointer v1)
2250 MonoClass *k = (MonoClass*)v1;
2252 return k->type_token;
2255 ICALL_EXPORT MonoArray*
2256 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2259 MonoClass *klass = mono_class_from_mono_type (type->type);
2261 FillIfaceArrayData data = { 0 };
2264 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2266 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2267 data.context = mono_class_get_context (klass);
2268 klass = klass->generic_class->container_class;
2271 for (parent = klass; parent; parent = parent->parent) {
2272 mono_class_setup_interfaces (parent, &error);
2273 if (!mono_error_ok (&error))
2275 collect_interfaces (parent, iface_hash, &error);
2276 if (!mono_error_ok (&error))
2280 data.error = &error;
2281 data.domain = mono_object_domain (type);
2283 len = g_hash_table_size (iface_hash);
2285 g_hash_table_destroy (iface_hash);
2286 if (!data.domain->empty_types)
2287 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2288 return data.domain->empty_types;
2291 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2292 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2293 if (!mono_error_ok (&error))
2296 g_hash_table_destroy (iface_hash);
2297 return data.iface_array;
2300 g_hash_table_destroy (iface_hash);
2301 mono_error_set_pending_exception (&error);
2306 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2308 gboolean variance_used;
2309 MonoClass *klass = mono_class_from_mono_type (type->type);
2310 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2311 MonoReflectionMethod *member;
2314 int i = 0, len, ioffset;
2318 mono_class_init_checked (klass, &error);
2319 mono_error_raise_exception (&error);
2320 mono_class_init_checked (iclass, &error);
2321 mono_error_raise_exception (&error);
2323 mono_class_setup_vtable (klass);
2325 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2329 len = mono_class_num_methods (iclass);
2330 domain = mono_object_domain (type);
2331 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2332 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2334 while ((method = mono_class_get_methods (iclass, &iter))) {
2335 member = mono_method_get_object_checked (domain, method, iclass, &error);
2336 mono_error_raise_exception (&error);
2337 mono_array_setref (*methods, i, member);
2338 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2339 mono_error_raise_exception (&error);
2340 mono_array_setref (*targets, i, member);
2347 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2350 MonoClass *klass = mono_class_from_mono_type (type->type);
2352 mono_class_init_checked (klass, &error);
2353 mono_error_raise_exception (&error);
2355 if (image_is_dynamic (klass->image)) {
2356 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2357 *packing = tb->packing_size;
2358 *size = tb->class_size;
2360 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2364 ICALL_EXPORT MonoReflectionType*
2365 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2368 MonoReflectionType *ret;
2371 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2372 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2373 mono_error_raise_exception (&error);
2378 klass = mono_class_from_mono_type (type->type);
2379 mono_class_init_checked (klass, &error);
2380 mono_error_raise_exception (&error);
2382 // GetElementType should only return a type for:
2383 // Array Pointer PassedByRef
2384 if (type->type->byref)
2385 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2386 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2387 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2388 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2389 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2393 mono_error_raise_exception (&error);
2398 ICALL_EXPORT MonoReflectionType*
2399 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2402 MonoReflectionType *ret;
2404 if (type->type->byref)
2407 MonoClass *klass = mono_class_from_mono_type (type->type);
2411 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2412 mono_error_raise_exception (&error);
2417 ICALL_EXPORT MonoBoolean
2418 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2420 return type->type->type == MONO_TYPE_PTR;
2423 ICALL_EXPORT MonoBoolean
2424 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2426 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)));
2429 ICALL_EXPORT MonoBoolean
2430 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2432 return type->type->byref;
2435 ICALL_EXPORT MonoBoolean
2436 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2439 MonoClass *klass = mono_class_from_mono_type (type->type);
2440 mono_class_init_checked (klass, &error);
2441 mono_error_raise_exception (&error);
2443 return mono_class_is_com_object (klass);
2446 ICALL_EXPORT guint32
2447 ves_icall_RuntimeTypeHandle_GetMetadataToken (MonoReflectionType *obj)
2449 return mono_reflection_get_token ((MonoObject*)obj);
2452 ICALL_EXPORT MonoReflectionModule*
2453 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2456 MonoReflectionModule *result = NULL;
2457 MonoClass *klass = mono_class_from_mono_type (type->type);
2458 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2459 if (!mono_error_ok (&error))
2460 mono_error_set_pending_exception (&error);
2464 ICALL_EXPORT MonoReflectionAssembly*
2465 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2468 MonoDomain *domain = mono_domain_get ();
2469 MonoClass *klass = mono_class_from_mono_type (type->type);
2470 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2472 mono_error_set_pending_exception (&error);
2476 ICALL_EXPORT MonoReflectionType*
2477 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2480 MonoReflectionType *ret;
2481 MonoDomain *domain = mono_domain_get ();
2484 if (type->type->byref)
2486 if (type->type->type == MONO_TYPE_VAR) {
2487 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2488 klass = param ? param->owner.klass : NULL;
2489 } else if (type->type->type == MONO_TYPE_MVAR) {
2490 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2491 klass = param ? param->owner.method->klass : NULL;
2493 klass = mono_class_from_mono_type (type->type)->nested_in;
2499 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2500 mono_error_raise_exception (&error);
2505 ICALL_EXPORT MonoString*
2506 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2508 MonoDomain *domain = mono_domain_get ();
2509 MonoClass *klass = mono_class_from_mono_type (type->type);
2511 if (type->type->byref) {
2512 char *n = g_strdup_printf ("%s&", klass->name);
2513 MonoString *res = mono_string_new (domain, n);
2519 return mono_string_new (domain, klass->name);
2523 ICALL_EXPORT MonoString*
2524 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2526 MonoDomain *domain = mono_domain_get ();
2527 MonoClass *klass = mono_class_from_mono_type (type->type);
2529 while (klass->nested_in)
2530 klass = klass->nested_in;
2532 if (klass->name_space [0] == '\0')
2535 return mono_string_new (domain, klass->name_space);
2539 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2543 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2544 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2548 klass = mono_class_from_mono_type (type->type);
2554 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2557 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2561 ICALL_EXPORT MonoArray*
2562 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2565 MonoReflectionType *rt;
2567 MonoClass *klass, *pklass;
2568 MonoDomain *domain = mono_object_domain (type);
2571 klass = mono_class_from_mono_type (type->type);
2573 if (klass->generic_container) {
2574 MonoGenericContainer *container = klass->generic_container;
2575 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2576 for (i = 0; i < container->type_argc; ++i) {
2577 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2579 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2580 mono_error_raise_exception (&error);
2582 mono_array_setref (res, i, rt);
2584 } else if (klass->generic_class) {
2585 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2586 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2587 for (i = 0; i < inst->type_argc; ++i) {
2588 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2589 mono_error_raise_exception (&error);
2591 mono_array_setref (res, i, rt);
2599 ICALL_EXPORT gboolean
2600 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2604 if (!IS_MONOTYPE (type))
2607 if (type->type->byref)
2610 klass = mono_class_from_mono_type (type->type);
2611 return klass->generic_container != NULL;
2614 ICALL_EXPORT MonoReflectionType*
2615 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2618 MonoReflectionType *ret;
2621 if (type->type->byref)
2624 klass = mono_class_from_mono_type (type->type);
2626 if (klass->generic_container) {
2627 return type; /* check this one */
2629 if (klass->generic_class) {
2630 MonoClass *generic_class = klass->generic_class->container_class;
2633 tb = mono_class_get_ref_info (generic_class);
2635 if (generic_class->wastypebuilder && tb)
2636 return (MonoReflectionType *)tb;
2638 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2639 mono_error_raise_exception (&error);
2647 ICALL_EXPORT MonoReflectionType*
2648 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2651 MonoReflectionType *ret;
2653 MonoType *geninst, **types;
2656 g_assert (IS_MONOTYPE (type));
2657 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2658 mono_error_raise_exception (&error);
2660 count = mono_array_length (type_array);
2661 types = g_new0 (MonoType *, count);
2663 for (i = 0; i < count; i++) {
2664 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2665 types [i] = t->type;
2668 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2673 klass = mono_class_from_mono_type (geninst);
2675 /*we might inflate to the GTD*/
2676 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2677 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2681 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2682 mono_error_raise_exception (&error);
2687 ICALL_EXPORT gboolean
2688 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2692 if (!IS_MONOTYPE (type))
2695 if (type->type->byref)
2698 klass = mono_class_from_mono_type (type->type);
2699 return klass->generic_class != NULL || klass->generic_container != NULL;
2703 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2705 if (!IS_MONOTYPE (type))
2708 if (is_generic_parameter (type->type))
2709 return mono_type_get_generic_param_num (type->type);
2713 ICALL_EXPORT GenericParameterAttributes
2714 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2716 g_assert (IS_MONOTYPE (type));
2717 g_assert (is_generic_parameter (type->type));
2718 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2721 ICALL_EXPORT MonoArray *
2722 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2725 MonoReflectionType *rt;
2726 MonoGenericParamInfo *param_info;
2732 g_assert (IS_MONOTYPE (type));
2734 domain = mono_object_domain (type);
2735 param_info = mono_generic_param_info (type->type->data.generic_param);
2736 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2739 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2740 for (i = 0; i < count; i++) {
2741 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2742 mono_error_raise_exception (&error);
2744 mono_array_setref (res, i, rt);
2751 ICALL_EXPORT MonoBoolean
2752 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2754 return is_generic_parameter (type->type);
2757 ICALL_EXPORT MonoBoolean
2758 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2760 return is_generic_parameter (tb->type.type);
2764 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2765 MonoReflectionType *t)
2767 enumtype->type = t->type;
2770 ICALL_EXPORT MonoReflectionMethod*
2771 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2772 MonoReflectionMethod* generic)
2779 MonoReflectionMethod *ret = NULL;
2781 domain = ((MonoObject *)type)->vtable->domain;
2783 klass = mono_class_from_mono_type (type->type);
2784 mono_class_init_checked (klass, &error);
2785 mono_error_raise_exception (&error);
2788 while ((method = mono_class_get_methods (klass, &iter))) {
2789 if (method->token == generic->method->token) {
2790 ret = mono_method_get_object_checked (domain, method, klass, &error);
2791 mono_error_raise_exception (&error);
2798 ICALL_EXPORT MonoReflectionMethod *
2799 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2802 MonoType *type = ref_type->type;
2804 MonoReflectionMethod *ret = NULL;
2806 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2807 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2810 if (type->type == MONO_TYPE_VAR)
2813 method = mono_type_get_generic_param_owner (type)->owner.method;
2816 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2817 if (!mono_error_ok (&error))
2818 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2822 ICALL_EXPORT MonoBoolean
2823 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2825 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2829 ICALL_EXPORT MonoBoolean
2830 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2832 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2837 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2839 MonoDomain *domain = mono_domain_get ();
2840 MonoImage *image = method->method->klass->image;
2841 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2842 MonoTableInfo *tables = image->tables;
2843 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2844 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2845 guint32 im_cols [MONO_IMPLMAP_SIZE];
2846 guint32 scope_token;
2847 const char *import = NULL;
2848 const char *scope = NULL;
2850 if (image_is_dynamic (image)) {
2851 MonoReflectionMethodAux *method_aux =
2852 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2854 import = method_aux->dllentry;
2855 scope = method_aux->dll;
2858 if (!import || !scope) {
2859 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2864 if (piinfo->implmap_idx) {
2865 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2867 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2868 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2869 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2870 scope = mono_metadata_string_heap (image, scope_token);
2874 *flags = piinfo->piflags;
2875 *entry_point = mono_string_new (domain, import);
2876 *dll_name = mono_string_new (domain, scope);
2879 ICALL_EXPORT MonoReflectionMethod *
2880 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2882 MonoMethodInflated *imethod;
2884 MonoReflectionMethod *ret = NULL;
2887 if (method->method->is_generic)
2890 if (!method->method->is_inflated)
2893 imethod = (MonoMethodInflated *) method->method;
2895 result = imethod->declaring;
2896 /* Not a generic method. */
2897 if (!result->is_generic)
2900 if (image_is_dynamic (method->method->klass->image)) {
2901 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2902 MonoReflectionMethod *res;
2905 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2906 * the dynamic case as well ?
2908 mono_image_lock ((MonoImage*)image);
2909 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2910 mono_image_unlock ((MonoImage*)image);
2916 if (imethod->context.class_inst) {
2917 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2918 /*Generic methods gets the context of the GTD.*/
2919 if (mono_class_get_context (klass)) {
2920 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2921 if (!mono_error_ok (&error))
2926 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2928 if (!mono_error_ok (&error))
2929 mono_error_set_pending_exception (&error);
2933 ICALL_EXPORT gboolean
2934 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2936 return mono_method_signature (method->method)->generic_param_count != 0;
2939 ICALL_EXPORT gboolean
2940 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2942 return method->method->is_generic;
2945 ICALL_EXPORT MonoArray*
2946 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2949 MonoReflectionType *rt;
2954 domain = mono_object_domain (method);
2956 if (method->method->is_inflated) {
2957 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2960 count = inst->type_argc;
2961 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2963 for (i = 0; i < count; i++) {
2964 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2965 mono_error_raise_exception (&error);
2967 mono_array_setref (res, i, rt);
2974 count = mono_method_signature (method->method)->generic_param_count;
2975 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2977 for (i = 0; i < count; i++) {
2978 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2979 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2980 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
2982 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2983 mono_error_raise_exception (&error);
2985 mono_array_setref (res, i, rt);
2991 ICALL_EXPORT MonoObject *
2992 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
2996 * Invoke from reflection is supposed to always be a virtual call (the API
2997 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2998 * greater flexibility.
3000 MonoMethod *m = method->method;
3001 MonoMethodSignature *sig = mono_method_signature (m);
3004 void *obj = this_arg;
3008 if (mono_security_core_clr_enabled ())
3009 mono_security_core_clr_ensure_reflection_access_method (m);
3011 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3012 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3013 mono_error_cleanup (&error); /* FIXME does this make sense? */
3014 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3019 if (!mono_object_isinst (this_arg, m->klass)) {
3020 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3021 char *target_name = mono_type_get_full_name (m->klass);
3022 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3023 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3025 g_free (target_name);
3029 m = mono_object_get_virtual_method (this_arg, m);
3030 /* must pass the pointer to the value for valuetype methods */
3031 if (m->klass->valuetype)
3032 obj = mono_object_unbox (this_arg);
3033 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3034 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3039 if (sig->ret->byref) {
3040 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"));
3044 pcount = params? mono_array_length (params): 0;
3045 if (pcount != sig->param_count) {
3046 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3050 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3051 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."));
3055 image = m->klass->image;
3056 if (image->assembly->ref_only) {
3057 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."));
3061 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3062 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3066 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3070 intptr_t *lower_bounds;
3071 pcount = mono_array_length (params);
3072 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3073 /* Note: the synthetized array .ctors have int32 as argument type */
3074 for (i = 0; i < pcount; ++i)
3075 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3077 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3078 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3079 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3080 if (!mono_error_ok (&error)) {
3081 mono_error_set_pending_exception (&error);
3085 for (i = 0; i < mono_array_length (arr); ++i) {
3086 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3087 if (!mono_error_ok (&error)) {
3088 mono_error_set_pending_exception (&error);
3091 mono_array_setref_fast (arr, i, subarray);
3093 return (MonoObject*)arr;
3096 if (m->klass->rank == pcount) {
3097 /* Only lengths provided. */
3098 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3099 if (!mono_error_ok (&error)) {
3100 mono_error_set_pending_exception (&error);
3104 return (MonoObject*)arr;
3106 g_assert (pcount == (m->klass->rank * 2));
3107 /* The arguments are lower-bound-length pairs */
3108 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3110 for (i = 0; i < pcount / 2; ++i) {
3111 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3112 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3115 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3116 if (!mono_error_ok (&error)) {
3117 mono_error_set_pending_exception (&error);
3121 return (MonoObject*)arr;
3124 return mono_runtime_invoke_array (m, obj, params, NULL);
3127 #ifndef DISABLE_REMOTING
3128 ICALL_EXPORT MonoObject *
3129 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3131 MonoDomain *domain = mono_object_domain (method);
3132 MonoMethod *m = method->method;
3133 MonoMethodSignature *sig = mono_method_signature (m);
3134 MonoArray *out_args;
3136 int i, j, outarg_count = 0;
3138 if (m->klass == mono_defaults.object_class) {
3139 if (!strcmp (m->name, "FieldGetter")) {
3140 MonoClass *k = this_arg->vtable->klass;
3144 /* If this is a proxy, then it must be a CBO */
3145 if (k == mono_defaults.transparent_proxy_class) {
3146 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3147 this_arg = tp->rp->unwrapped_server;
3148 g_assert (this_arg);
3149 k = this_arg->vtable->klass;
3152 name = mono_array_get (params, MonoString *, 1);
3153 str = mono_string_to_utf8 (name);
3156 MonoClassField* field = mono_class_get_field_from_name (k, str);
3158 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3159 if (field_klass->valuetype)
3160 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
3162 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3164 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3165 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3166 mono_array_setref (out_args, 0, result);
3174 g_assert_not_reached ();
3176 } else if (!strcmp (m->name, "FieldSetter")) {
3177 MonoClass *k = this_arg->vtable->klass;
3183 /* If this is a proxy, then it must be a CBO */
3184 if (k == mono_defaults.transparent_proxy_class) {
3185 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3186 this_arg = tp->rp->unwrapped_server;
3187 g_assert (this_arg);
3188 k = this_arg->vtable->klass;
3191 name = mono_array_get (params, MonoString *, 1);
3192 str = mono_string_to_utf8 (name);
3195 MonoClassField* field = mono_class_get_field_from_name (k, str);
3197 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3198 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3200 if (field_klass->valuetype) {
3201 size = mono_type_size (field->type, &align);
3202 g_assert (size == mono_class_value_size (field_klass, NULL));
3203 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3205 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3208 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3209 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3219 g_assert_not_reached ();
3224 for (i = 0; i < mono_array_length (params); i++) {
3225 if (sig->params [i]->byref)
3229 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3231 /* handle constructors only for objects already allocated */
3232 if (!strcmp (method->method->name, ".ctor"))
3233 g_assert (this_arg);
3235 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3236 g_assert (!method->method->klass->valuetype);
3237 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3239 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3240 if (sig->params [i]->byref) {
3242 arg = mono_array_get (params, gpointer, i);
3243 mono_array_setref (out_args, j, arg);
3248 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3255 read_enum_value (const char *mem, int type)
3258 case MONO_TYPE_BOOLEAN:
3260 return *(guint8*)mem;
3262 return *(gint8*)mem;
3263 case MONO_TYPE_CHAR:
3265 return read16 (mem);
3267 return (gint16) read16 (mem);
3269 return read32 (mem);
3271 return (gint32) read32 (mem);
3274 return read64 (mem);
3276 g_assert_not_reached ();
3282 write_enum_value (char *mem, int type, guint64 value)
3286 case MONO_TYPE_I1: {
3287 guint8 *p = (guint8*)mem;
3292 case MONO_TYPE_I2: {
3293 guint16 *p = (guint16 *)mem;
3298 case MONO_TYPE_I4: {
3299 guint32 *p = (guint32 *)mem;
3304 case MONO_TYPE_I8: {
3305 guint64 *p = (guint64 *)mem;
3310 g_assert_not_reached ();
3315 ICALL_EXPORT MonoObject *
3316 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3324 domain = mono_object_domain (enumType);
3325 enumc = mono_class_from_mono_type (enumType->type);
3327 mono_class_init_checked (enumc, &error);
3328 mono_error_raise_exception (&error);
3330 etype = mono_class_enum_basetype (enumc);
3332 res = mono_object_new_checked (domain, enumc, &error);
3333 mono_error_raise_exception (&error);
3334 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3339 ICALL_EXPORT MonoBoolean
3340 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3342 int size = mono_class_value_size (a->vtable->klass, NULL);
3343 guint64 a_val = 0, b_val = 0;
3345 memcpy (&a_val, mono_object_unbox (a), size);
3346 memcpy (&b_val, mono_object_unbox (b), size);
3348 return (a_val & b_val) == b_val;
3351 ICALL_EXPORT MonoObject *
3352 ves_icall_System_Enum_get_value (MonoObject *eobj)
3364 g_assert (eobj->vtable->klass->enumtype);
3366 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3367 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3368 mono_error_raise_exception (&error);
3369 dst = (char *)res + sizeof (MonoObject);
3370 src = (char *)eobj + sizeof (MonoObject);
3371 size = mono_class_value_size (enumc, NULL);
3373 memcpy (dst, src, size);
3378 ICALL_EXPORT MonoReflectionType *
3379 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3382 MonoReflectionType *ret;
3386 klass = mono_class_from_mono_type (type->type);
3387 mono_class_init_checked (klass, &error);
3388 mono_error_raise_exception (&error);
3390 etype = mono_class_enum_basetype (klass);
3392 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3396 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3397 mono_error_raise_exception (&error);
3403 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3405 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3406 gpointer odata = (char *)other + sizeof (MonoObject);
3407 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3408 g_assert (basetype);
3413 if (eobj->vtable->klass != other->vtable->klass)
3416 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3417 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3418 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3421 return me > other ? 1 : -1; \
3424 switch (basetype->type) {
3426 COMPARE_ENUM_VALUES (guint8);
3428 COMPARE_ENUM_VALUES (gint8);
3429 case MONO_TYPE_CHAR:
3431 COMPARE_ENUM_VALUES (guint16);
3433 COMPARE_ENUM_VALUES (gint16);
3435 COMPARE_ENUM_VALUES (guint32);
3437 COMPARE_ENUM_VALUES (gint32);
3439 COMPARE_ENUM_VALUES (guint64);
3441 COMPARE_ENUM_VALUES (gint64);
3445 #undef COMPARE_ENUM_VALUES
3446 /* indicates that the enum was of an unsupported unerlying type */
3451 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3453 gpointer data = (char *)eobj + sizeof (MonoObject);
3454 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3455 g_assert (basetype);
3457 switch (basetype->type) {
3458 case MONO_TYPE_I1: {
3459 gint8 value = *((gint8*)data);
3460 return ((int)value ^ (int)value << 8);
3463 return *((guint8*)data);
3464 case MONO_TYPE_CHAR:
3466 return *((guint16*)data);
3468 case MONO_TYPE_I2: {
3469 gint16 value = *((gint16*)data);
3470 return ((int)(guint16)value | (((int)value) << 16));
3473 return *((guint32*)data);
3475 return *((gint32*)data);
3477 case MONO_TYPE_I8: {
3478 gint64 value = *((gint64*)data);
3479 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3482 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3487 ICALL_EXPORT MonoBoolean
3488 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3491 MonoDomain *domain = mono_object_domain (type);
3492 MonoClass *enumc = mono_class_from_mono_type (type->type);
3493 guint j = 0, nvalues;
3495 MonoClassField *field;
3497 guint64 field_value, previous_value = 0;
3498 gboolean sorted = TRUE;
3500 mono_class_init_checked (enumc, &error);
3501 mono_error_raise_exception (&error);
3503 if (!enumc->enumtype) {
3504 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3508 base_type = mono_class_enum_basetype (enumc)->type;
3510 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3511 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3512 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3515 while ((field = mono_class_get_fields (enumc, &iter))) {
3517 MonoTypeEnum def_type;
3519 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3521 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3523 if (mono_field_is_deleted (field))
3525 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3527 p = mono_class_get_field_default_value (field, &def_type);
3528 /* len = */ mono_metadata_decode_blob_size (p, &p);
3530 field_value = read_enum_value (p, base_type);
3531 mono_array_set (*values, guint64, j, field_value);
3533 if (previous_value > field_value)
3536 previous_value = field_value;
3544 BFLAGS_IgnoreCase = 1,
3545 BFLAGS_DeclaredOnly = 2,
3546 BFLAGS_Instance = 4,
3548 BFLAGS_Public = 0x10,
3549 BFLAGS_NonPublic = 0x20,
3550 BFLAGS_FlattenHierarchy = 0x40,
3551 BFLAGS_InvokeMethod = 0x100,
3552 BFLAGS_CreateInstance = 0x200,
3553 BFLAGS_GetField = 0x400,
3554 BFLAGS_SetField = 0x800,
3555 BFLAGS_GetProperty = 0x1000,
3556 BFLAGS_SetProperty = 0x2000,
3557 BFLAGS_ExactBinding = 0x10000,
3558 BFLAGS_SuppressChangeType = 0x20000,
3559 BFLAGS_OptionalParamBinding = 0x40000
3562 ICALL_EXPORT MonoArray*
3563 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3567 MonoClass *startklass, *klass, *refklass;
3572 char *utf8_name = NULL;
3573 int (*compare_func) (const char *s1, const char *s2) = NULL;
3574 MonoClassField *field;
3575 MonoPtrArray tmp_array;
3577 domain = ((MonoObject *)type)->vtable->domain;
3578 if (type->type->byref)
3579 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3581 klass = startklass = mono_class_from_mono_type (type->type);
3582 refklass = mono_class_from_mono_type (reftype->type);
3584 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3587 if (mono_class_has_failure (klass)) {
3588 mono_ptr_array_destroy (tmp_array);
3589 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3594 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3595 guint32 flags = mono_field_get_flags (field);
3597 if (mono_field_is_deleted_with_flags (field, flags))
3599 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3600 if (bflags & BFLAGS_Public)
3602 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3603 if (bflags & BFLAGS_NonPublic) {
3610 if (flags & FIELD_ATTRIBUTE_STATIC) {
3611 if (bflags & BFLAGS_Static)
3612 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3615 if (bflags & BFLAGS_Instance)
3623 if (utf8_name == NULL) {
3624 utf8_name = mono_string_to_utf8 (name);
3625 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3628 if (compare_func (mono_field_get_name (field), utf8_name))
3632 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3633 if (!mono_error_ok (&error))
3635 mono_ptr_array_append (tmp_array, member);
3637 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3640 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3642 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3643 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3645 mono_ptr_array_destroy (tmp_array);
3647 if (utf8_name != NULL)
3652 mono_ptr_array_destroy (tmp_array);
3653 mono_error_raise_exception (&error);
3654 g_assert_not_reached ();
3658 method_nonpublic (MonoMethod* method, gboolean start_klass)
3660 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3661 case METHOD_ATTRIBUTE_ASSEM:
3662 return (start_klass || mono_defaults.generic_ilist_class);
3663 case METHOD_ATTRIBUTE_PRIVATE:
3665 case METHOD_ATTRIBUTE_PUBLIC:
3673 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3676 MonoClass *startklass;
3680 /*FIXME, use MonoBitSet*/
3681 guint32 method_slots_default [8];
3682 guint32 *method_slots = NULL;
3683 int (*compare_func) (const char *s1, const char *s2) = NULL;
3685 array = g_ptr_array_new ();
3690 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3692 /* An optimization for calls made from Delegate:CreateDelegate () */
3693 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3694 method = mono_get_delegate_invoke (klass);
3695 if (mono_loader_get_last_error ())
3698 g_ptr_array_add (array, method);
3702 mono_class_setup_methods (klass);
3703 mono_class_setup_vtable (klass);
3704 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3707 if (is_generic_parameter (&klass->byval_arg))
3708 nslots = mono_class_get_vtable_size (klass->parent);
3710 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3711 if (nslots >= sizeof (method_slots_default) * 8) {
3712 method_slots = g_new0 (guint32, nslots / 32 + 1);
3714 method_slots = method_slots_default;
3715 memset (method_slots, 0, sizeof (method_slots_default));
3718 mono_class_setup_methods (klass);
3719 mono_class_setup_vtable (klass);
3720 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3724 while ((method = mono_class_get_methods (klass, &iter))) {
3726 if (method->slot != -1) {
3727 g_assert (method->slot < nslots);
3728 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3730 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3731 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3734 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3736 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3737 if (bflags & BFLAGS_Public)
3739 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3745 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3746 if (bflags & BFLAGS_Static)
3747 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3750 if (bflags & BFLAGS_Instance)
3758 if (compare_func (name, method->name))
3763 g_ptr_array_add (array, method);
3765 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3767 if (method_slots != method_slots_default)
3768 g_free (method_slots);
3773 if (method_slots != method_slots_default)
3774 g_free (method_slots);
3775 g_ptr_array_free (array, TRUE);
3777 if (mono_class_has_failure (klass)) {
3778 *ex = mono_class_get_exception_for_failure (klass);
3780 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3781 mono_loader_clear_error ();
3786 ICALL_EXPORT MonoArray*
3787 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3789 static MonoClass *MethodInfo_array;
3793 MonoVTable *array_vtable;
3794 MonoException *ex = NULL;
3795 const char *mname = NULL;
3796 GPtrArray *method_array;
3797 MonoClass *klass, *refklass;
3800 mono_error_init (&error);
3802 if (!MethodInfo_array) {
3803 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3804 mono_memory_barrier ();
3805 MethodInfo_array = klass;
3808 klass = mono_class_from_mono_type (type->type);
3809 refklass = mono_class_from_mono_type (reftype->type);
3810 domain = ((MonoObject *)type)->vtable->domain;
3811 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3812 if (!is_ok (&error)) {
3813 mono_error_set_pending_exception (&error);
3816 if (type->type->byref) {
3817 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3818 mono_error_set_pending_exception (&error);
3824 mname = mono_string_to_utf8 (name);
3826 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3827 g_free ((char*)mname);
3829 mono_set_pending_exception (ex);
3833 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3834 if (!mono_error_ok (&error)) {
3835 mono_error_set_pending_exception (&error);
3839 for (i = 0; i < method_array->len; ++i) {
3840 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3841 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3842 if (!mono_error_ok (&error))
3844 mono_array_setref (res, i, rm);
3848 g_ptr_array_free (method_array, TRUE);
3849 if (!mono_error_ok (&error))
3850 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3854 ICALL_EXPORT MonoArray*
3855 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3858 MonoClass *startklass, *klass, *refklass;
3863 gpointer iter = NULL;
3864 MonoPtrArray tmp_array;
3867 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3869 domain = ((MonoObject *)type)->vtable->domain;
3870 if (type->type->byref)
3871 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3872 klass = startklass = mono_class_from_mono_type (type->type);
3873 refklass = mono_class_from_mono_type (reftype->type);
3875 mono_class_setup_methods (klass);
3876 if (mono_class_has_failure (klass)) {
3877 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3882 while ((method = mono_class_get_methods (klass, &iter))) {
3884 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3886 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3887 if (bflags & BFLAGS_Public)
3890 if (bflags & BFLAGS_NonPublic)
3896 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3897 if (bflags & BFLAGS_Static)
3898 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3901 if (bflags & BFLAGS_Instance)
3907 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3908 if (!mono_error_ok (&error)) {
3909 mono_error_set_pending_exception (&error);
3913 mono_ptr_array_append (tmp_array, member);
3916 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
3918 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3919 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3921 mono_ptr_array_destroy (tmp_array);
3927 property_hash (gconstpointer data)
3929 MonoProperty *prop = (MonoProperty*)data;
3931 return g_str_hash (prop->name);
3935 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3937 if (method1->is_inflated)
3938 method1 = ((MonoMethodInflated*) method1)->declaring;
3939 if (method2->is_inflated)
3940 method2 = ((MonoMethodInflated*) method2)->declaring;
3942 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3946 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3948 // Properties are hide-by-name-and-signature
3949 if (!g_str_equal (prop1->name, prop2->name))
3952 /* If we see a property in a generic method, we want to
3953 compare the generic signatures, not the inflated signatures
3954 because we might conflate two properties that were
3958 public T this[T t] { getter { return t; } } // method 1
3959 public U this[U u] { getter { return u; } } // method 2
3962 If we see int Foo<int,int>::Item[int] we need to know if
3963 the indexer came from method 1 or from method 2, and we
3964 shouldn't conflate them. (Bugzilla 36283)
3966 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
3969 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
3976 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3981 return method_nonpublic (accessor, start_klass);
3984 ICALL_EXPORT MonoArray*
3985 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3989 MonoClass *startklass, *klass;
3995 gchar *propname = NULL;
3996 int (*compare_func) (const char *s1, const char *s2) = NULL;
3998 GHashTable *properties = NULL;
3999 MonoPtrArray tmp_array;
4001 mono_error_init (&error);
4003 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4005 domain = ((MonoObject *)type)->vtable->domain;
4006 if (type->type->byref)
4007 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
4008 klass = startklass = mono_class_from_mono_type (type->type);
4011 propname = mono_string_to_utf8 (name);
4012 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4015 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4017 mono_class_setup_methods (klass);
4018 mono_class_setup_vtable (klass);
4019 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4023 while ((prop = mono_class_get_properties (klass, &iter))) {
4029 flags = method->flags;
4032 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4033 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4034 if (bflags & BFLAGS_Public)
4036 } else if (bflags & BFLAGS_NonPublic) {
4037 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4038 property_accessor_nonpublic(prop->set, startklass == klass)) {
4045 if (flags & METHOD_ATTRIBUTE_STATIC) {
4046 if (bflags & BFLAGS_Static)
4047 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4050 if (bflags & BFLAGS_Instance)
4059 if (compare_func (propname, prop->name))
4063 if (g_hash_table_lookup (properties, prop))
4066 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4069 mono_ptr_array_append (tmp_array, pr);
4071 g_hash_table_insert (properties, prop, prop);
4073 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4076 g_hash_table_destroy (properties);
4079 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4080 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4081 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4083 mono_ptr_array_destroy (tmp_array);
4090 if (mono_class_has_failure (klass)) {
4091 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4093 mono_error_set_from_loader_error (&error);
4094 mono_loader_clear_error ();
4099 g_hash_table_destroy (properties);
4102 mono_ptr_array_destroy (tmp_array);
4104 mono_error_set_pending_exception (&error);
4110 event_hash (gconstpointer data)
4112 MonoEvent *event = (MonoEvent*)data;
4114 return g_str_hash (event->name);
4118 event_equal (MonoEvent *event1, MonoEvent *event2)
4120 // Events are hide-by-name
4121 return g_str_equal (event1->name, event2->name);
4124 ICALL_EXPORT MonoArray*
4125 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4129 MonoClass *startklass, *klass;
4135 char *utf8_name = NULL;
4136 int (*compare_func) (const char *s1, const char *s2) = NULL;
4137 GHashTable *events = NULL;
4138 MonoPtrArray tmp_array;
4140 mono_error_init (&error);
4142 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4144 domain = mono_object_domain (type);
4145 if (type->type->byref)
4146 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4147 klass = startklass = mono_class_from_mono_type (type->type);
4149 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4151 mono_class_setup_methods (klass);
4152 mono_class_setup_vtable (klass);
4153 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4157 while ((event = mono_class_get_events (klass, &iter))) {
4159 method = event->add;
4161 method = event->remove;
4163 method = event->raise;
4165 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4166 if (bflags & BFLAGS_Public)
4168 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4169 if (bflags & BFLAGS_NonPublic)
4174 if (bflags & BFLAGS_NonPublic)
4180 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4181 if (bflags & BFLAGS_Static)
4182 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4185 if (bflags & BFLAGS_Instance)
4190 if (bflags & BFLAGS_Instance)
4196 if (utf8_name == NULL) {
4197 utf8_name = mono_string_to_utf8 (name);
4198 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4201 if (compare_func (event->name, utf8_name))
4205 if (g_hash_table_lookup (events, event))
4208 MonoReflectionEvent *ev_obj;
4209 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4212 mono_ptr_array_append (tmp_array, ev_obj);
4214 g_hash_table_insert (events, event, event);
4216 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4219 g_hash_table_destroy (events);
4221 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4223 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4224 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4226 mono_ptr_array_destroy (tmp_array);
4228 if (utf8_name != NULL)
4234 if (mono_class_has_failure (klass)) {
4235 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4237 mono_error_set_from_loader_error (&error);
4238 mono_loader_clear_error ();
4244 g_hash_table_destroy (events);
4245 if (utf8_name != NULL)
4248 mono_ptr_array_destroy (tmp_array);
4250 mono_error_set_pending_exception (&error);
4254 ICALL_EXPORT MonoArray*
4255 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4258 MonoReflectionType *rt;
4266 MonoPtrArray tmp_array;
4268 domain = ((MonoObject *)type)->vtable->domain;
4269 if (type->type->byref)
4270 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4271 klass = mono_class_from_mono_type (type->type);
4274 * If a nested type is generic, return its generic type definition.
4275 * Note that this means that the return value is essentially the set
4276 * of nested types of the generic type definition of @klass.
4278 * A note in MSDN claims that a generic type definition can have
4279 * nested types that aren't generic. In any case, the container of that
4280 * nested type would be the generic type definition.
4282 if (klass->generic_class)
4283 klass = klass->generic_class->container_class;
4285 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4287 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4289 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4290 if (bflags & BFLAGS_Public)
4293 if (bflags & BFLAGS_NonPublic)
4301 str = mono_string_to_utf8 (name);
4302 mono_identifier_unescape_type_name_chars (str);
4305 if (strcmp (nested->name, str))
4309 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4310 mono_error_raise_exception (&error);
4312 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4315 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4317 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4318 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4320 mono_ptr_array_destroy (tmp_array);
4328 ICALL_EXPORT MonoReflectionType*
4329 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4332 MonoReflectionType *ret;
4334 MonoType *type = NULL;
4335 MonoTypeNameParse info;
4336 gboolean type_resolve;
4338 /* On MS.NET, this does not fire a TypeResolve event */
4339 type_resolve = TRUE;
4340 str = mono_string_to_utf8 (name);
4341 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4342 if (!mono_reflection_parse_type (str, &info)) {
4344 mono_reflection_free_type_info (&info);
4346 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4349 /*g_print ("failed parse\n");*/
4353 if (info.assembly.name) {
4355 mono_reflection_free_type_info (&info);
4357 /* 1.0 and 2.0 throw different exceptions */
4358 if (mono_defaults.generic_ilist_class)
4359 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4361 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4367 if (module != NULL) {
4369 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4374 if (assembly_is_dynamic (assembly->assembly)) {
4375 /* Enumerate all modules */
4376 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4380 if (abuilder->modules) {
4381 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4382 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4383 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4389 if (!type && abuilder->loaded_modules) {
4390 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4391 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4392 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4399 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4401 mono_reflection_free_type_info (&info);
4403 MonoException *e = NULL;
4406 e = mono_get_exception_type_load (name, NULL);
4408 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4409 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4411 mono_loader_clear_error ();
4414 mono_set_pending_exception (e);
4416 } else if (mono_loader_get_last_error ()) {
4418 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4421 mono_loader_clear_error ();
4424 if (type->type == MONO_TYPE_CLASS) {
4425 MonoClass *klass = mono_type_get_class (type);
4427 /* need to report exceptions ? */
4428 if (throwOnError && mono_class_has_failure (klass)) {
4429 /* report SecurityException (or others) that occured when loading the assembly */
4430 MonoException *exc = mono_class_get_exception_for_failure (klass);
4431 mono_loader_clear_error ();
4432 mono_set_pending_exception (exc);
4437 /* g_print ("got it\n"); */
4438 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4439 mono_error_raise_exception (&error);
4445 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4448 gchar *shadow_ini_file;
4451 /* Check for shadow-copied assembly */
4452 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4453 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4455 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4456 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4462 g_free (shadow_ini_file);
4463 if (content != NULL) {
4466 *filename = content;
4473 ICALL_EXPORT MonoString *
4474 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4476 MonoDomain *domain = mono_object_domain (assembly);
4477 MonoAssembly *mass = assembly->assembly;
4478 MonoString *res = NULL;
4483 if (g_path_is_absolute (mass->image->name)) {
4484 absolute = g_strdup (mass->image->name);
4485 dirname = g_path_get_dirname (absolute);
4487 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4488 dirname = g_strdup (mass->basedir);
4491 replace_shadow_path (domain, dirname, &absolute);
4496 for (i = strlen (absolute) - 1; i >= 0; i--)
4497 if (absolute [i] == '\\')
4502 uri = g_filename_to_uri (absolute, NULL, NULL);
4504 const char *prepend = "file://";
4506 if (*absolute == '/' && *(absolute + 1) == '/') {
4509 prepend = "file:///";
4512 uri = g_strconcat (prepend, absolute, NULL);
4516 res = mono_string_new (domain, uri);
4523 ICALL_EXPORT MonoBoolean
4524 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4526 MonoAssembly *mass = assembly->assembly;
4528 return mass->in_gac;
4531 ICALL_EXPORT MonoReflectionAssembly*
4532 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4537 MonoImageOpenStatus status;
4538 MonoReflectionAssembly* result = NULL;
4540 name = mono_string_to_utf8 (mname);
4541 res = mono_assembly_load_with_partial_name (name, &status);
4547 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4549 mono_error_set_pending_exception (&error);
4553 ICALL_EXPORT MonoString *
4554 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4556 MonoDomain *domain = mono_object_domain (assembly);
4559 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4564 ICALL_EXPORT MonoBoolean
4565 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4567 return assembly->assembly->ref_only;
4570 ICALL_EXPORT MonoString *
4571 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4573 MonoDomain *domain = mono_object_domain (assembly);
4575 return mono_string_new (domain, assembly->assembly->image->version);
4578 ICALL_EXPORT MonoReflectionMethod*
4579 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4582 MonoReflectionMethod *res = NULL;
4585 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4589 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4590 if (!mono_error_ok (&error))
4593 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4596 if (!mono_error_ok (&error))
4597 mono_error_set_pending_exception (&error);
4601 ICALL_EXPORT MonoReflectionModule*
4602 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4605 MonoReflectionModule *result = NULL;
4606 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4607 if (!mono_error_ok (&error))
4608 mono_error_set_pending_exception (&error);
4612 ICALL_EXPORT MonoArray*
4613 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4615 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4616 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4620 for (i = 0; i < table->rows; ++i) {
4621 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4622 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4628 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4630 static MonoMethod *create_version = NULL;
4634 mono_error_init (error);
4637 if (!create_version) {
4638 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4639 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4640 g_assert (create_version);
4641 mono_method_desc_free (desc);
4647 args [3] = &revision;
4648 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4649 return_val_if_nok (error, NULL);
4651 mono_runtime_invoke_checked (create_version, result, args, error);
4652 return_val_if_nok (error, NULL);
4657 ICALL_EXPORT MonoArray*
4658 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4662 MonoDomain *domain = mono_object_domain (assembly);
4664 static MonoMethod *create_culture = NULL;
4665 MonoImage *image = assembly->assembly->image;
4669 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4672 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4674 if (count > 0 && !create_culture) {
4675 MonoMethodDesc *desc = mono_method_desc_new (
4676 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4677 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4678 g_assert (create_culture);
4679 mono_method_desc_free (desc);
4682 for (i = 0; i < count; i++) {
4683 MonoObject *version;
4684 MonoReflectionAssemblyName *aname;
4685 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4687 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4689 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4690 domain, mono_class_get_assembly_name_class (), &error);
4691 mono_error_raise_exception (&error);
4693 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4695 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4696 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4697 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4698 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4699 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4700 aname->versioncompat = 1; /* SameMachine (default) */
4701 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4703 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4704 mono_error_raise_exception (&error);
4706 MONO_OBJECT_SETREF (aname, version, version);
4708 if (create_culture) {
4710 MonoBoolean assembly_ref = 1;
4711 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4712 args [1] = &assembly_ref;
4714 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4715 mono_error_raise_exception (&error);
4717 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4720 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4721 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4722 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4724 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4725 /* public key token isn't copied - the class library will
4726 automatically generate it from the public key if required */
4727 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4728 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4730 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4731 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4734 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4737 /* note: this function doesn't return the codebase on purpose (i.e. it can
4738 be used under partial trust as path information isn't present). */
4740 mono_array_setref (result, i, aname);
4745 /* move this in some file in mono/util/ */
4747 g_concat_dir_and_file (const char *dir, const char *file)
4749 g_return_val_if_fail (dir != NULL, NULL);
4750 g_return_val_if_fail (file != NULL, NULL);
4753 * If the directory name doesn't have a / on the end, we need
4754 * to add one so we get a proper path to the file
4756 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4757 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4759 return g_strconcat (dir, file, NULL);
4763 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4766 char *n = mono_string_to_utf8 (name);
4767 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4769 guint32 cols [MONO_MANIFEST_SIZE];
4770 guint32 impl, file_idx;
4774 for (i = 0; i < table->rows; ++i) {
4775 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4776 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4777 if (strcmp (val, n) == 0)
4781 if (i == table->rows)
4784 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4787 * this code should only be called after obtaining the
4788 * ResourceInfo and handling the other cases.
4790 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4791 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4793 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4798 module = assembly->assembly->image;
4801 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4802 mono_error_raise_exception (&error);
4803 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4805 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4808 ICALL_EXPORT gboolean
4809 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4812 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4814 guint32 cols [MONO_MANIFEST_SIZE];
4815 guint32 file_cols [MONO_FILE_SIZE];
4819 n = mono_string_to_utf8 (name);
4820 for (i = 0; i < table->rows; ++i) {
4821 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4822 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4823 if (strcmp (val, n) == 0)
4827 if (i == table->rows)
4830 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4831 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4834 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4835 case MONO_IMPLEMENTATION_FILE:
4836 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4837 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4838 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4839 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4840 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4841 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4844 info->location = RESOURCE_LOCATION_EMBEDDED;
4847 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4848 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4849 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4850 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4851 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4852 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4854 mono_set_pending_exception (ex);
4857 MonoReflectionAssembly *assm_obj;
4858 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4860 mono_error_set_pending_exception (&error);
4863 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4865 /* Obtain info recursively */
4866 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4867 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4870 case MONO_IMPLEMENTATION_EXP_TYPE:
4871 g_assert_not_reached ();
4879 ICALL_EXPORT MonoObject*
4880 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4882 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4883 MonoArray *result = NULL;
4888 /* check hash if needed */
4890 n = mono_string_to_utf8 (name);
4891 for (i = 0; i < table->rows; ++i) {
4892 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4893 if (strcmp (val, n) == 0) {
4896 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4897 fn = mono_string_new (mono_object_domain (assembly), n);
4899 return (MonoObject*)fn;
4907 for (i = 0; i < table->rows; ++i) {
4908 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4912 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4915 for (i = 0; i < table->rows; ++i) {
4916 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4917 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4918 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4919 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4924 return (MonoObject*)result;
4927 ICALL_EXPORT MonoArray*
4928 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4931 MonoDomain *domain = mono_domain_get();
4934 int i, j, file_count = 0;
4935 MonoImage **modules;
4936 guint32 module_count, real_module_count;
4937 MonoTableInfo *table;
4938 guint32 cols [MONO_FILE_SIZE];
4939 MonoImage *image = assembly->assembly->image;
4941 g_assert (image != NULL);
4942 g_assert (!assembly_is_dynamic (assembly->assembly));
4944 table = &image->tables [MONO_TABLE_FILE];
4945 file_count = table->rows;
4947 modules = image->modules;
4948 module_count = image->module_count;
4950 real_module_count = 0;
4951 for (i = 0; i < module_count; ++i)
4953 real_module_count ++;
4955 klass = mono_class_get_module_class ();
4956 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4958 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
4959 mono_error_raise_exception (&error);
4960 mono_array_setref (res, 0, image_obj);
4962 for (i = 0; i < module_count; ++i)
4964 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
4965 mono_error_raise_exception (&error);
4966 mono_array_setref (res, j, rm);
4970 for (i = 0; i < file_count; ++i, ++j) {
4971 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4972 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
4973 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
4974 mono_error_raise_exception (&error);
4975 mono_array_setref (res, j, rm);
4978 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4980 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4981 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
4984 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
4985 mono_error_raise_exception (&error);
4986 mono_array_setref (res, j, rm);
4993 ICALL_EXPORT MonoReflectionMethod*
4994 ves_icall_GetCurrentMethod (void)
4996 MonoReflectionMethod *res = NULL;
4999 MonoMethod *m = mono_method_get_last_managed ();
5002 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5006 while (m->is_inflated)
5007 m = ((MonoMethodInflated*)m)->declaring;
5009 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5010 mono_error_raise_exception (&error);
5016 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5019 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5022 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5023 //method is inflated, we should inflate it on the other class
5024 MonoGenericContext ctx;
5025 ctx.method_inst = inflated->context.method_inst;
5026 ctx.class_inst = inflated->context.class_inst;
5027 if (klass->generic_class)
5028 ctx.class_inst = klass->generic_class->context.class_inst;
5029 else if (klass->generic_container)
5030 ctx.class_inst = klass->generic_container->context.class_inst;
5031 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5032 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5036 mono_class_setup_methods (method->klass);
5037 if (mono_class_has_failure (method->klass))
5039 for (i = 0; i < method->klass->method.count; ++i) {
5040 if (method->klass->methods [i] == method) {
5045 mono_class_setup_methods (klass);
5046 if (mono_class_has_failure (klass))
5048 g_assert (offset >= 0 && offset < klass->method.count);
5049 return klass->methods [offset];
5052 ICALL_EXPORT MonoReflectionMethod*
5053 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5055 MonoReflectionMethod *res = NULL;
5059 klass = mono_class_from_mono_type (type);
5060 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5062 if (method->klass != klass) {
5063 method = mono_method_get_equivalent_method (method, klass);
5068 klass = method->klass;
5069 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5070 mono_error_raise_exception (&error);
5074 ICALL_EXPORT MonoReflectionMethodBody*
5075 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5077 return mono_method_body_get_object (mono_domain_get (), method);
5080 ICALL_EXPORT MonoReflectionAssembly*
5081 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5084 MonoReflectionAssembly *result;
5085 MonoMethod *dest = NULL;
5087 mono_stack_walk_no_il (get_executing, &dest);
5089 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5091 mono_error_set_pending_exception (&error);
5096 ICALL_EXPORT MonoReflectionAssembly*
5097 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5100 MonoReflectionAssembly *result;
5101 MonoDomain* domain = mono_domain_get ();
5103 if (!domain->entry_assembly)
5106 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5108 mono_error_set_pending_exception (&error);
5112 ICALL_EXPORT MonoReflectionAssembly*
5113 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5118 MonoReflectionAssembly *result;
5121 mono_stack_walk_no_il (get_executing, &dest);
5123 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5127 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5130 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5132 mono_error_set_pending_exception (&error);
5136 ICALL_EXPORT MonoString *
5137 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5138 gboolean assembly_qualified)
5140 MonoDomain *domain = mono_object_domain (object);
5141 MonoTypeNameFormat format;
5146 format = assembly_qualified ?
5147 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5148 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5150 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5152 name = mono_type_get_name_full (object->type, format);
5156 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5161 res = mono_string_new (domain, name);
5168 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5171 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5173 mono_class_init_checked (klass, &error);
5174 mono_error_raise_exception (&error);
5175 return mono_security_core_clr_class_level (klass);
5179 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5181 MonoClassField *field = rfield->field;
5182 return mono_security_core_clr_field_level (field, TRUE);
5186 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5188 MonoMethod *method = rfield->method;
5189 return mono_security_core_clr_method_level (method, TRUE);
5193 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)
5195 static MonoMethod *create_culture = NULL;
5199 const char *pkey_ptr;
5201 MonoBoolean assembly_ref = 0;
5203 mono_error_init (error);
5205 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5206 aname->major = name->major;
5207 aname->minor = name->minor;
5208 aname->build = name->build;
5209 aname->flags = name->flags;
5210 aname->revision = name->revision;
5211 aname->hashalg = name->hash_alg;
5212 aname->versioncompat = 1; /* SameMachine (default) */
5213 aname->processor_architecture = name->arch;
5215 if (by_default_version) {
5216 MonoObject *version;
5218 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5219 return_if_nok (error);
5221 MONO_OBJECT_SETREF (aname, version, version);
5225 if (absolute != NULL && *absolute != '\0') {
5226 const gchar *prepend = "file://";
5229 codebase = g_strdup (absolute);
5234 for (i = strlen (codebase) - 1; i >= 0; i--)
5235 if (codebase [i] == '\\')
5238 if (*codebase == '/' && *(codebase + 1) == '/') {
5241 prepend = "file:///";
5245 result = g_strconcat (prepend, codebase, NULL);
5251 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5255 if (!create_culture) {
5256 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5257 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5258 g_assert (create_culture);
5259 mono_method_desc_free (desc);
5262 if (name->culture) {
5263 args [0] = mono_string_new (domain, name->culture);
5264 args [1] = &assembly_ref;
5266 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5267 return_if_nok (error);
5269 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5272 if (name->public_key) {
5273 pkey_ptr = (char*)name->public_key;
5274 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5276 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5277 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5278 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5279 } else if (default_publickey) {
5280 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5281 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5284 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5285 if (name->public_key_token [0]) {
5289 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5290 p = mono_array_addr (aname->keyToken, char, 0);
5292 for (i = 0, j = 0; i < 8; i++) {
5293 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5294 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5297 } else if (default_token) {
5298 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5302 ICALL_EXPORT MonoString *
5303 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5305 MonoDomain *domain = mono_object_domain (assembly);
5306 MonoAssembly *mass = assembly->assembly;
5310 name = mono_stringify_assembly_name (&mass->aname);
5311 res = mono_string_new (domain, name);
5318 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5322 MonoAssembly *mass = assembly->assembly;
5324 if (g_path_is_absolute (mass->image->name)) {
5325 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5326 mono_error_set_pending_exception (&error);
5329 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5331 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5332 mono_error_set_pending_exception (&error);
5338 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5342 MonoImageOpenStatus status = MONO_IMAGE_OK;
5345 MonoAssemblyName name;
5348 filename = mono_string_to_utf8 (fname);
5350 dirname = g_path_get_dirname (filename);
5351 replace_shadow_path (mono_domain_get (), dirname, &filename);
5354 image = mono_image_open (filename, &status);
5360 if (status == MONO_IMAGE_IMAGE_INVALID)
5361 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5363 exc = mono_get_exception_file_not_found2 (NULL, fname);
5364 mono_set_pending_exception (exc);
5368 res = mono_assembly_fill_assembly_name (image, &name);
5370 mono_image_close (image);
5372 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5376 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5377 mono_error_set_pending_exception (&error);
5379 mono_image_close (image);
5383 ICALL_EXPORT MonoBoolean
5384 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5385 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5387 MonoBoolean result = FALSE;
5388 MonoDeclSecurityEntry entry;
5390 /* SecurityAction.RequestMinimum */
5391 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5392 *minimum = entry.blob;
5393 *minLength = entry.size;
5396 /* SecurityAction.RequestOptional */
5397 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5398 *optional = entry.blob;
5399 *optLength = entry.size;
5402 /* SecurityAction.RequestRefuse */
5403 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5404 *refused = entry.blob;
5405 *refLength = entry.size;
5413 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5415 guint32 attrs, visibility;
5417 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5418 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5419 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5422 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5428 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5430 MonoReflectionType *rt;
5433 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5436 mono_error_init (error);
5438 /* we start the count from 1 because we skip the special type <Module> */
5441 for (i = 1; i < tdef->rows; ++i) {
5442 if (mono_module_type_is_visible (tdef, image, i + 1))
5446 count = tdef->rows - 1;
5448 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5449 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5451 for (i = 1; i < tdef->rows; ++i) {
5452 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5453 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5454 mono_loader_assert_no_error (); /* Plug any leaks */
5455 mono_error_assert_ok (error);
5458 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5459 return_val_if_nok (error, NULL);
5461 mono_array_setref (res, count, rt);
5463 MonoException *ex = mono_error_convert_to_exception (error);
5464 mono_array_setref (*exceptions, count, ex);
5473 ICALL_EXPORT MonoArray*
5474 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5477 MonoArray *res = NULL;
5478 MonoArray *exceptions = NULL;
5479 MonoImage *image = NULL;
5480 MonoTableInfo *table = NULL;
5483 int i, len, ex_count;
5485 domain = mono_object_domain (assembly);
5487 g_assert (!assembly_is_dynamic (assembly->assembly));
5488 image = assembly->assembly->image;
5489 table = &image->tables [MONO_TABLE_FILE];
5490 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5491 mono_error_raise_exception (&error);
5493 /* Append data from all modules in the assembly */
5494 for (i = 0; i < table->rows; ++i) {
5495 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5496 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5501 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5502 mono_error_raise_exception (&error);
5504 /* Append the new types to the end of the array */
5505 if (mono_array_length (res2) > 0) {
5507 MonoArray *res3, *ex3;
5509 len1 = mono_array_length (res);
5510 len2 = mono_array_length (res2);
5512 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5513 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5514 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5517 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5518 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5519 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5526 /* the ReflectionTypeLoadException must have all the types (Types property),
5527 * NULL replacing types which throws an exception. The LoaderException must
5528 * contain all exceptions for NULL items.
5531 len = mono_array_length (res);
5534 for (i = 0; i < len; i++) {
5535 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5539 klass = mono_type_get_class (t->type);
5540 if ((klass != NULL) && mono_class_has_failure (klass)) {
5541 /* keep the class in the list */
5542 list = g_list_append (list, klass);
5543 /* and replace Type with NULL */
5544 mono_array_setref (res, i, NULL);
5551 if (list || ex_count) {
5553 MonoException *exc = NULL;
5554 MonoArray *exl = NULL;
5555 int j, length = g_list_length (list) + ex_count;
5557 mono_loader_clear_error ();
5559 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5560 /* Types for which mono_class_get_checked () succeeded */
5561 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5562 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5563 mono_array_setref (exl, i, exc);
5565 /* Types for which it don't */
5566 for (j = 0; j < mono_array_length (exceptions); ++j) {
5567 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5569 g_assert (i < length);
5570 mono_array_setref (exl, i, exc);
5577 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5578 if (!is_ok (&error)) {
5579 mono_error_set_pending_exception (&error);
5582 mono_loader_clear_error ();
5583 mono_set_pending_exception (exc);
5590 ICALL_EXPORT gboolean
5591 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5594 MonoAssemblyName aname;
5595 MonoDomain *domain = mono_object_domain (name);
5597 gboolean is_version_defined;
5598 gboolean is_token_defined;
5600 aname.public_key = NULL;
5601 val = mono_string_to_utf8 (assname);
5602 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5603 g_free ((guint8*) aname.public_key);
5608 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5609 mono_error_set_pending_exception (&error);
5611 mono_assembly_name_free (&aname);
5612 g_free ((guint8*) aname.public_key);
5618 ICALL_EXPORT MonoReflectionType*
5619 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5622 MonoReflectionType *ret;
5623 MonoDomain *domain = mono_object_domain (module);
5626 g_assert (module->image);
5628 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5629 /* These images do not have a global type */
5632 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5633 if (!mono_error_ok (&error)) {
5634 mono_error_set_pending_exception (&error);
5638 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5639 if (!mono_error_ok (&error)) {
5640 mono_error_set_pending_exception (&error);
5648 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5650 /*if (module->image)
5651 mono_image_close (module->image);*/
5654 ICALL_EXPORT MonoString*
5655 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5657 MonoDomain *domain = mono_object_domain (module);
5659 g_assert (module->image);
5660 return mono_string_new (domain, module->image->guid);
5663 ICALL_EXPORT gpointer
5664 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5667 if (module->image && module->image->is_module_handle)
5668 return module->image->raw_data;
5671 return (gpointer) (-1);
5675 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5677 if (image_is_dynamic (image)) {
5678 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5679 *pe_kind = dyn->pe_kind;
5680 *machine = dyn->machine;
5683 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5684 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5689 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5691 return (image->md_version_major << 16) | (image->md_version_minor);
5694 ICALL_EXPORT MonoArray*
5695 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5698 MonoArray *exceptions;
5702 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5706 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5707 mono_error_raise_exception (&error);
5709 for (i = 0; i < mono_array_length (exceptions); ++i) {
5710 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5712 mono_set_pending_exception (ex);
5721 mono_memberref_is_method (MonoImage *image, guint32 token)
5723 if (!image_is_dynamic (image)) {
5724 guint32 cols [MONO_MEMBERREF_SIZE];
5726 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5727 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5728 mono_metadata_decode_blob_size (sig, &sig);
5729 return (*sig != 0x6);
5731 MonoClass *handle_class;
5733 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5736 return mono_defaults.methodhandle_class == handle_class;
5741 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5744 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5745 mono_array_addr (type_args, MonoType*, 0));
5747 context->class_inst = NULL;
5749 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5750 mono_array_addr (method_args, MonoType*, 0));
5752 context->method_inst = NULL;
5755 ICALL_EXPORT MonoType*
5756 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5759 int table = mono_metadata_token_table (token);
5760 int index = mono_metadata_token_index (token);
5761 MonoGenericContext context;
5764 *resolve_error = ResolveTokenError_Other;
5766 /* Validate token */
5767 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5768 (table != MONO_TABLE_TYPESPEC)) {
5769 *resolve_error = ResolveTokenError_BadTable;
5773 if (image_is_dynamic (image)) {
5774 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5775 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5776 return klass ? &klass->byval_arg : NULL;
5779 init_generic_context_from_args (&context, type_args, method_args);
5780 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5781 return klass ? &klass->byval_arg : NULL;
5784 if ((index <= 0) || (index > image->tables [table].rows)) {
5785 *resolve_error = ResolveTokenError_OutOfRange;
5789 init_generic_context_from_args (&context, type_args, method_args);
5790 klass = mono_class_get_checked (image, token, &error);
5792 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5793 if (!mono_error_ok (&error)) {
5794 mono_error_set_pending_exception (&error);
5799 return &klass->byval_arg;
5804 ICALL_EXPORT MonoMethod*
5805 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5808 int table = mono_metadata_token_table (token);
5809 int index = mono_metadata_token_index (token);
5810 MonoGenericContext context;
5813 *resolve_error = ResolveTokenError_Other;
5815 /* Validate token */
5816 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5817 (table != MONO_TABLE_MEMBERREF)) {
5818 *resolve_error = ResolveTokenError_BadTable;
5822 if (image_is_dynamic (image)) {
5823 if (table == MONO_TABLE_METHOD)
5824 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5826 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5827 *resolve_error = ResolveTokenError_BadTable;
5831 init_generic_context_from_args (&context, type_args, method_args);
5832 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5835 if ((index <= 0) || (index > image->tables [table].rows)) {
5836 *resolve_error = ResolveTokenError_OutOfRange;
5839 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5840 *resolve_error = ResolveTokenError_BadTable;
5844 init_generic_context_from_args (&context, type_args, method_args);
5845 method = mono_get_method_checked (image, token, NULL, &context, &error);
5846 mono_error_set_pending_exception (&error);
5851 ICALL_EXPORT MonoString*
5852 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5854 int index = mono_metadata_token_index (token);
5856 *error = ResolveTokenError_Other;
5858 /* Validate token */
5859 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5860 *error = ResolveTokenError_BadTable;
5864 if (image_is_dynamic (image))
5865 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5867 if ((index <= 0) || (index >= image->heap_us.size)) {
5868 *error = ResolveTokenError_OutOfRange;
5872 /* FIXME: What to do if the index points into the middle of a string ? */
5874 return mono_ldstr (mono_domain_get (), image, index);
5877 ICALL_EXPORT MonoClassField*
5878 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5882 int table = mono_metadata_token_table (token);
5883 int index = mono_metadata_token_index (token);
5884 MonoGenericContext context;
5885 MonoClassField *field;
5887 *resolve_error = ResolveTokenError_Other;
5889 /* Validate token */
5890 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5891 *resolve_error = ResolveTokenError_BadTable;
5895 if (image_is_dynamic (image)) {
5896 if (table == MONO_TABLE_FIELD)
5897 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5899 if (mono_memberref_is_method (image, token)) {
5900 *resolve_error = ResolveTokenError_BadTable;
5904 init_generic_context_from_args (&context, type_args, method_args);
5905 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5908 if ((index <= 0) || (index > image->tables [table].rows)) {
5909 *resolve_error = ResolveTokenError_OutOfRange;
5912 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5913 *resolve_error = ResolveTokenError_BadTable;
5917 init_generic_context_from_args (&context, type_args, method_args);
5918 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5919 mono_error_set_pending_exception (&error);
5925 ICALL_EXPORT MonoObject*
5926 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5930 int table = mono_metadata_token_table (token);
5932 *error = ResolveTokenError_Other;
5935 case MONO_TABLE_TYPEDEF:
5936 case MONO_TABLE_TYPEREF:
5937 case MONO_TABLE_TYPESPEC: {
5938 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5940 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
5941 mono_error_raise_exception (&merror);
5948 case MONO_TABLE_METHOD:
5949 case MONO_TABLE_METHODSPEC: {
5950 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5952 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5953 mono_error_raise_exception (&merror);
5959 case MONO_TABLE_FIELD: {
5960 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5962 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5963 mono_error_raise_exception (&merror);
5969 case MONO_TABLE_MEMBERREF:
5970 if (mono_memberref_is_method (image, token)) {
5971 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5973 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5974 mono_error_raise_exception (&merror);
5981 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5983 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5984 mono_error_raise_exception (&merror);
5993 *error = ResolveTokenError_BadTable;
5999 ICALL_EXPORT MonoArray*
6000 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
6002 int table = mono_metadata_token_table (token);
6003 int idx = mono_metadata_token_index (token);
6004 MonoTableInfo *tables = image->tables;
6009 *error = ResolveTokenError_OutOfRange;
6011 /* FIXME: Support other tables ? */
6012 if (table != MONO_TABLE_STANDALONESIG)
6015 if (image_is_dynamic (image))
6018 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6021 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6023 ptr = mono_metadata_blob_heap (image, sig);
6024 len = mono_metadata_decode_blob_size (ptr, &ptr);
6026 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
6027 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6031 ICALL_EXPORT MonoReflectionType*
6032 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6035 MonoReflectionType *ret;
6037 int isbyref = 0, rank;
6038 char *str = mono_string_to_utf8 (smodifiers);
6041 klass = mono_class_from_mono_type (tb->type.type);
6043 /* logic taken from mono_reflection_parse_type(): keep in sync */
6047 if (isbyref) { /* only one level allowed by the spec */
6056 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6057 mono_error_raise_exception (&error);
6061 klass = mono_ptr_class_get (&klass->byval_arg);
6062 mono_class_init (klass);
6073 else if (*p != '*') { /* '*' means unknown lower bound */
6084 klass = mono_array_class_get (klass, rank);
6085 mono_class_init (klass);
6094 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6095 mono_error_raise_exception (&error);
6100 ICALL_EXPORT MonoBoolean
6101 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6107 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6113 check_for_invalid_type (MonoClass *klass, MonoError *error)
6118 mono_error_init (error);
6120 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6123 name = mono_type_get_full_name (klass);
6124 str = mono_string_new (mono_domain_get (), name);
6126 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6129 ICALL_EXPORT MonoReflectionType *
6130 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6133 MonoReflectionType *ret;
6134 MonoClass *klass, *aklass;
6136 klass = mono_class_from_mono_type (type->type);
6137 check_for_invalid_type (klass, &error);
6138 mono_error_raise_exception (&error);
6140 if (rank == 0) //single dimentional array
6141 aklass = mono_array_class_get (klass, 1);
6143 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6145 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6146 mono_error_raise_exception (&error);
6151 ICALL_EXPORT MonoReflectionType *
6152 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6155 MonoReflectionType *ret;
6158 klass = mono_class_from_mono_type (type->type);
6159 mono_class_init_checked (klass, &error);
6160 mono_error_raise_exception (&error);
6161 check_for_invalid_type (klass, &error);
6162 mono_error_raise_exception (&error);
6164 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6165 mono_error_raise_exception (&error);
6170 ICALL_EXPORT MonoReflectionType *
6171 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6174 MonoReflectionType *ret;
6175 MonoClass *klass, *pklass;
6177 klass = mono_class_from_mono_type (type->type);
6178 mono_class_init_checked (klass, &error);
6179 mono_error_raise_exception (&error);
6180 check_for_invalid_type (klass, &error);
6181 mono_error_raise_exception (&error);
6183 pklass = mono_ptr_class_get (type->type);
6185 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6186 mono_error_raise_exception (&error);
6191 ICALL_EXPORT MonoObject *
6192 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6193 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6196 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6197 MonoObject *delegate;
6199 MonoMethod *method = info->method;
6201 mono_class_init_checked (delegate_class, &error);
6202 mono_error_raise_exception (&error);
6204 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
6206 if (mono_security_core_clr_enabled ()) {
6207 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6211 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6212 mono_error_raise_exception (&error);
6214 if (method_is_dynamic (method)) {
6215 /* Creating a trampoline would leak memory */
6216 func = mono_compile_method (method);
6218 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6219 method = mono_object_get_virtual_method (target, method);
6220 func = mono_create_ftnptr (mono_domain_get (),
6221 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6224 mono_delegate_ctor_with_method (delegate, target, func, method);
6229 ICALL_EXPORT MonoMulticastDelegate *
6230 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6233 MonoMulticastDelegate *ret;
6235 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6237 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6238 mono_error_raise_exception (&error);
6239 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6244 ICALL_EXPORT MonoReflectionMethod*
6245 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6247 MonoReflectionMethod *ret = NULL;
6249 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6250 mono_error_raise_exception (&error);
6256 static inline gint32
6257 mono_array_get_byte_length (MonoArray *array)
6263 klass = array->obj.vtable->klass;
6265 if (array->bounds == NULL)
6266 length = array->max_length;
6269 for (i = 0; i < klass->rank; ++ i)
6270 length *= array->bounds [i].length;
6273 switch (klass->element_class->byval_arg.type) {
6276 case MONO_TYPE_BOOLEAN:
6280 case MONO_TYPE_CHAR:
6288 return length * sizeof (gpointer);
6299 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6301 return mono_array_get_byte_length (array);
6305 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6307 return mono_array_get (array, gint8, idx);
6311 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6313 mono_array_set (array, gint8, idx, value);
6316 ICALL_EXPORT MonoBoolean
6317 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6319 guint8 *src_buf, *dest_buf;
6322 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6326 g_assert (count >= 0);
6328 /* This is called directly from the class libraries without going through the managed wrapper */
6329 MONO_CHECK_ARG_NULL (src, FALSE);
6330 MONO_CHECK_ARG_NULL (dest, FALSE);
6332 /* watch out for integer overflow */
6333 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6336 src_buf = (guint8 *)src->vector + src_offset;
6337 dest_buf = (guint8 *)dest->vector + dest_offset;
6340 memcpy (dest_buf, src_buf, count);
6342 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6347 #ifndef DISABLE_REMOTING
6348 ICALL_EXPORT MonoObject *
6349 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6352 MonoDomain *domain = mono_object_domain (this_obj);
6354 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6355 MonoTransparentProxy *tp;
6359 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6360 mono_error_raise_exception (&error);
6361 tp = (MonoTransparentProxy*) res;
6363 MONO_OBJECT_SETREF (tp, rp, rp);
6364 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6365 klass = mono_class_from_mono_type (type);
6367 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6368 mono_class_setup_vtable (klass);
6369 if (mono_class_has_failure (klass)) {
6370 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6374 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
6375 tp->remote_class = mono_remote_class (domain, class_name, klass);
6377 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6381 ICALL_EXPORT MonoReflectionType *
6382 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6385 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6386 mono_error_raise_exception (&error);
6392 /* System.Environment */
6395 ves_icall_System_Environment_get_UserName (void)
6397 /* using glib is more portable */
6398 return mono_string_new (mono_domain_get (), g_get_user_name ());
6402 ICALL_EXPORT MonoString *
6403 ves_icall_System_Environment_get_MachineName (void)
6405 #if defined (HOST_WIN32)
6410 len = MAX_COMPUTERNAME_LENGTH + 1;
6411 buf = g_new (gunichar2, len);
6414 if (GetComputerName (buf, (PDWORD) &len)) {
6416 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6417 mono_error_raise_exception (&error);
6422 #elif !defined(DISABLE_SOCKETS)
6426 #if defined _SC_HOST_NAME_MAX
6427 n = sysconf (_SC_HOST_NAME_MAX);
6431 buf = g_malloc (n+1);
6433 if (gethostname (buf, n) == 0){
6435 result = mono_string_new (mono_domain_get (), buf);
6442 return mono_string_new (mono_domain_get (), "mono");
6447 ves_icall_System_Environment_get_Platform (void)
6449 #if defined (TARGET_WIN32)
6452 #elif defined(__MACH__)
6455 // Notice that the value is hidden from user code, and only exposed
6456 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6457 // define and making assumptions based on Unix/128/4 values before there
6458 // was a MacOS define. Lots of code would assume that not-Unix meant
6459 // Windows, but in this case, it would be OSX.
6468 ICALL_EXPORT MonoString *
6469 ves_icall_System_Environment_get_NewLine (void)
6471 #if defined (HOST_WIN32)
6472 return mono_string_new (mono_domain_get (), "\r\n");
6474 return mono_string_new (mono_domain_get (), "\n");
6478 ICALL_EXPORT MonoBoolean
6479 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6481 #if SIZEOF_VOID_P == 8
6485 gboolean isWow64Process = FALSE;
6486 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6487 return (MonoBoolean)isWow64Process;
6489 #elif defined(HAVE_SYS_UTSNAME_H)
6490 struct utsname name;
6492 if (uname (&name) >= 0) {
6493 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6500 ICALL_EXPORT MonoString *
6501 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6509 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6510 value = g_getenv (utf8_name);
6517 return mono_string_new (mono_domain_get (), value);
6521 * There is no standard way to get at environ.
6524 #ifndef __MINGW32_VERSION
6525 #if defined(__APPLE__)
6526 #if defined (TARGET_OSX)
6527 /* Apple defines this in crt_externs.h but doesn't provide that header for
6528 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6529 * in fact exist on all implementations (so far)
6531 gchar ***_NSGetEnviron(void);
6532 #define environ (*_NSGetEnviron())
6534 static char *mono_environ[1] = { NULL };
6535 #define environ mono_environ
6536 #endif /* defined (TARGET_OSX) */
6544 ICALL_EXPORT MonoArray *
6545 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6556 env_strings = GetEnvironmentStrings();
6559 env_string = env_strings;
6560 while (*env_string != '\0') {
6561 /* weird case that MS seems to skip */
6562 if (*env_string != '=')
6564 while (*env_string != '\0')
6570 domain = mono_domain_get ();
6571 names = mono_array_new (domain, mono_defaults.string_class, n);
6575 env_string = env_strings;
6576 while (*env_string != '\0') {
6577 /* weird case that MS seems to skip */
6578 if (*env_string != '=') {
6579 equal_str = wcschr(env_string, '=');
6580 g_assert(equal_str);
6582 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6583 mono_error_raise_exception (&error);
6584 mono_array_setref (names, n, str);
6587 while (*env_string != '\0')
6592 FreeEnvironmentStrings (env_strings);
6605 for (e = environ; *e != 0; ++ e)
6608 domain = mono_domain_get ();
6609 names = mono_array_new (domain, mono_defaults.string_class, n);
6612 for (e = environ; *e != 0; ++ e) {
6613 parts = g_strsplit (*e, "=", 2);
6615 str = mono_string_new (domain, *parts);
6616 mono_array_setref (names, n, str);
6629 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6631 #if !GLIB_CHECK_VERSION(2,4,0)
6632 #define g_setenv(a,b,c) setenv(a,b,c)
6633 #define g_unsetenv(a) unsetenv(a)
6637 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6640 gunichar2 *utf16_name, *utf16_value;
6642 gchar *utf8_name, *utf8_value;
6647 utf16_name = mono_string_to_utf16 (name);
6648 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6649 SetEnvironmentVariable (utf16_name, NULL);
6650 g_free (utf16_name);
6654 utf16_value = mono_string_to_utf16 (value);
6656 SetEnvironmentVariable (utf16_name, utf16_value);
6658 g_free (utf16_name);
6659 g_free (utf16_value);
6661 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6663 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6664 g_unsetenv (utf8_name);
6669 utf8_value = mono_string_to_utf8_checked (value, &error);
6670 if (!mono_error_ok (&error)) {
6672 mono_error_set_pending_exception (&error);
6675 g_setenv (utf8_name, utf8_value, TRUE);
6678 g_free (utf8_value);
6683 ves_icall_System_Environment_Exit (int result)
6685 mono_environment_exitcode_set (result);
6687 /* FIXME: There are some cleanup hangs that should be worked out, but
6688 * if the program is going to exit, everything will be cleaned up when
6689 * NaCl exits anyway.
6691 #ifndef __native_client__
6692 if (!mono_runtime_try_shutdown ())
6693 mono_thread_exit ();
6695 /* Suspend all managed threads since the runtime is going away */
6696 mono_thread_suspend_all_other_threads ();
6698 mono_runtime_quit ();
6701 /* we may need to do some cleanup here... */
6705 ICALL_EXPORT MonoString*
6706 ves_icall_System_Environment_GetGacPath (void)
6708 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6711 ICALL_EXPORT MonoString*
6712 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6714 #if defined (HOST_WIN32)
6715 #ifndef CSIDL_FLAG_CREATE
6716 #define CSIDL_FLAG_CREATE 0x8000
6719 WCHAR path [MAX_PATH];
6720 /* Create directory if no existing */
6721 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6726 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6727 mono_error_raise_exception (&error);
6731 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6733 return mono_string_new (mono_domain_get (), "");
6736 ICALL_EXPORT MonoArray *
6737 ves_icall_System_Environment_GetLogicalDrives (void)
6740 gunichar2 buf [256], *ptr, *dname;
6742 guint initial_size = 127, size = 128;
6745 MonoString *drivestr;
6746 MonoDomain *domain = mono_domain_get ();
6752 while (size > initial_size) {
6753 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6754 if (size > initial_size) {
6757 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6758 initial_size = size;
6772 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6777 while (*u16) { u16++; len ++; }
6778 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6779 mono_error_raise_exception (&error);
6780 mono_array_setref (result, ndrives++, drivestr);
6790 ICALL_EXPORT MonoString *
6791 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6793 gunichar2 volume_name [MAX_PATH + 1];
6795 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6797 return mono_string_from_utf16 (volume_name);
6800 ICALL_EXPORT MonoString *
6801 ves_icall_System_Environment_InternalGetHome (void)
6803 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6806 static const char *encodings [] = {
6808 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6809 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6810 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6812 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6813 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6814 "x_unicode_2_0_utf_7",
6816 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6817 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6819 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6822 "unicodefffe", "utf_16be",
6829 * Returns the internal codepage, if the value of "int_code_page" is
6830 * 1 at entry, and we can not compute a suitable code page number,
6831 * returns the code page as a string
6833 ICALL_EXPORT MonoString*
6834 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6839 char *codepage = NULL;
6841 int want_name = *int_code_page;
6844 *int_code_page = -1;
6846 g_get_charset (&cset);
6847 c = codepage = strdup (cset);
6848 for (c = codepage; *c; c++){
6849 if (isascii (*c) && isalpha (*c))
6854 /* g_print ("charset: %s\n", cset); */
6856 /* handle some common aliases */
6859 for (i = 0; p != 0; ){
6862 p = encodings [++i];
6865 if (strcmp (p, codepage) == 0){
6866 *int_code_page = code;
6869 p = encodings [++i];
6872 if (strstr (codepage, "utf_8") != NULL)
6873 *int_code_page |= 0x10000000;
6876 if (want_name && *int_code_page == -1)
6877 return mono_string_new (mono_domain_get (), cset);
6882 ICALL_EXPORT MonoBoolean
6883 ves_icall_System_Environment_get_HasShutdownStarted (void)
6885 if (mono_runtime_is_shutting_down ())
6888 if (mono_domain_is_unloading (mono_domain_get ()))
6895 ves_icall_System_Environment_BroadcastSettingChange (void)
6898 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6903 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6909 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6910 MonoReflectionMethod *method,
6911 MonoArray *out_args)
6913 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6916 #ifndef DISABLE_REMOTING
6917 ICALL_EXPORT MonoBoolean
6918 ves_icall_IsTransparentProxy (MonoObject *proxy)
6923 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6929 ICALL_EXPORT MonoReflectionMethod *
6930 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6931 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6933 MonoReflectionMethod *ret = NULL;
6938 MonoMethod **vtable;
6939 MonoMethod *res = NULL;
6941 MONO_CHECK_ARG_NULL (rtype, NULL);
6942 MONO_CHECK_ARG_NULL (rmethod, NULL);
6944 method = rmethod->method;
6945 klass = mono_class_from_mono_type (rtype->type);
6946 mono_class_init_checked (klass, &error);
6947 mono_error_raise_exception (&error);
6949 if (MONO_CLASS_IS_INTERFACE (klass))
6952 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6955 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6956 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6962 mono_class_setup_vtable (klass);
6963 vtable = klass->vtable;
6965 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6966 gboolean variance_used = FALSE;
6967 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6968 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6970 res = vtable [offs + method->slot];
6972 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6975 if (method->slot != -1)
6976 res = vtable [method->slot];
6982 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
6983 mono_error_raise_exception (&error);
6988 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6994 klass = mono_class_from_mono_type (type->type);
6995 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
6996 if (!is_ok (&error)) {
6997 mono_error_set_pending_exception (&error);
7001 mono_vtable_set_is_remote (vtable, enable);
7004 #else /* DISABLE_REMOTING */
7007 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7009 g_assert_not_reached ();
7014 ICALL_EXPORT MonoObject *
7015 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7022 domain = mono_object_domain (type);
7023 klass = mono_class_from_mono_type (type->type);
7024 mono_class_init_checked (klass, &error);
7025 mono_error_raise_exception (&error);
7027 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7028 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7032 if (klass->rank >= 1) {
7033 g_assert (klass->rank == 1);
7034 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7036 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7037 if (!is_ok (&error)) {
7038 mono_error_set_pending_exception (&error);
7041 /* Bypass remoting object creation check */
7042 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7043 mono_error_set_pending_exception (&error);
7049 ICALL_EXPORT MonoString *
7050 ves_icall_System_IO_get_temp_path (void)
7052 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7055 #ifndef PLATFORM_NO_DRIVEINFO
7056 ICALL_EXPORT MonoBoolean
7057 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7058 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7062 ULARGE_INTEGER wapi_free_bytes_avail;
7063 ULARGE_INTEGER wapi_total_number_of_bytes;
7064 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7066 *error = ERROR_SUCCESS;
7067 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7068 &wapi_total_number_of_free_bytes);
7071 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7072 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7073 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7075 *free_bytes_avail = 0;
7076 *total_number_of_bytes = 0;
7077 *total_number_of_free_bytes = 0;
7078 *error = GetLastError ();
7084 ICALL_EXPORT guint32
7085 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7087 return GetDriveType (mono_string_chars (root_path_name));
7091 ICALL_EXPORT gpointer
7092 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7094 return mono_compile_method (method);
7097 ICALL_EXPORT MonoString *
7098 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7103 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7105 #if defined (HOST_WIN32)
7106 /* Avoid mixing '/' and '\\' */
7109 for (i = strlen (path) - 1; i >= 0; i--)
7110 if (path [i] == '/')
7114 mcpath = mono_string_new (mono_domain_get (), path);
7121 get_bundled_app_config (void)
7123 const gchar *app_config;
7126 gchar *config_file_name, *config_file_path;
7127 gsize len, config_file_path_length, config_ext_length;
7130 domain = mono_domain_get ();
7131 file = domain->setup->configuration_file;
7132 if (!file || file->length == 0)
7135 // Retrieve config file and remove the extension
7136 config_file_name = mono_string_to_utf8 (file);
7137 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7138 if (!config_file_path)
7139 config_file_path = config_file_name;
7141 config_file_path_length = strlen (config_file_path);
7142 config_ext_length = strlen (".config");
7143 if (config_file_path_length <= config_ext_length)
7146 len = config_file_path_length - config_ext_length;
7147 module = (gchar *)g_malloc0 (len + 1);
7148 memcpy (module, config_file_path, len);
7149 // Get the config file from the module name
7150 app_config = mono_config_string_for_assembly_file (module);
7153 if (config_file_name != config_file_path)
7154 g_free (config_file_name);
7155 g_free (config_file_path);
7160 return mono_string_new (mono_domain_get (), app_config);
7164 get_bundled_machine_config (void)
7166 const gchar *machine_config;
7168 machine_config = mono_get_machine_config ();
7170 if (!machine_config)
7173 return mono_string_new (mono_domain_get (), machine_config);
7176 ICALL_EXPORT MonoString *
7177 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7182 path = g_path_get_dirname (mono_get_config_dir ());
7184 #if defined (HOST_WIN32)
7185 /* Avoid mixing '/' and '\\' */
7188 for (i = strlen (path) - 1; i >= 0; i--)
7189 if (path [i] == '/')
7193 ipath = mono_string_new (mono_domain_get (), path);
7199 ICALL_EXPORT gboolean
7200 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7202 MonoPEResourceDataEntry *entry;
7205 if (!assembly || !result || !size)
7210 image = assembly->assembly->image;
7211 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7215 *result = mono_image_rva_map (image, entry->rde_data_offset);
7220 *size = entry->rde_size;
7225 ICALL_EXPORT MonoBoolean
7226 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7228 return mono_is_debugger_attached ();
7231 ICALL_EXPORT MonoBoolean
7232 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7234 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7235 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7241 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7243 if (mono_get_runtime_callbacks ()->debug_log)
7244 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7248 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7250 #if defined (HOST_WIN32)
7251 OutputDebugString (mono_string_chars (message));
7253 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7257 /* Only used for value types */
7258 ICALL_EXPORT MonoObject *
7259 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7266 domain = mono_object_domain (type);
7267 klass = mono_class_from_mono_type (type->type);
7268 mono_class_init_checked (klass, &error);
7269 mono_error_raise_exception (&error);
7271 if (mono_class_is_nullable (klass))
7272 /* No arguments -> null */
7275 result = mono_object_new_checked (domain, klass, &error);
7276 mono_error_raise_exception (&error);
7280 ICALL_EXPORT MonoReflectionMethod *
7281 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7283 MonoReflectionMethod *ret = NULL;
7286 MonoClass *klass, *parent;
7287 MonoGenericContext *generic_inst = NULL;
7288 MonoMethod *method = m->method;
7289 MonoMethod *result = NULL;
7292 if (method->klass == NULL)
7295 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7296 MONO_CLASS_IS_INTERFACE (method->klass) ||
7297 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7300 slot = mono_method_get_vtable_slot (method);
7304 klass = method->klass;
7305 if (klass->generic_class) {
7306 generic_inst = mono_class_get_context (klass);
7307 klass = klass->generic_class->container_class;
7311 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7312 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7313 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7314 or klass is the generic container class and generic_inst is the instantiation.
7316 when we go to the parent, if the parent is an open constructed type, we need to
7317 replace the type parameters by the definitions from the generic_inst, and then take it
7318 apart again into the klass and the generic_inst.
7320 For cases like this:
7321 class C<T> : B<T, int> {
7322 public override void Foo () { ... }
7324 class B<U,V> : A<HashMap<U,V>> {
7325 public override void Foo () { ... }
7328 public virtual void Foo () { ... }
7331 if at each iteration the parent isn't open, we can skip inflating it. if at some
7332 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7335 MonoGenericContext *parent_inst = NULL;
7336 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7338 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7339 if (!mono_error_ok (&error)) {
7340 mono_error_set_pending_exception (&error);
7344 if (parent->generic_class) {
7345 parent_inst = mono_class_get_context (parent);
7346 parent = parent->generic_class->container_class;
7349 mono_class_setup_vtable (parent);
7350 if (parent->vtable_size <= slot)
7353 generic_inst = parent_inst;
7356 klass = klass->parent;
7359 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7360 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7361 if (!mono_error_ok (&error)) {
7362 mono_error_set_pending_exception (&error);
7366 generic_inst = NULL;
7368 if (klass->generic_class) {
7369 generic_inst = mono_class_get_context (klass);
7370 klass = klass->generic_class->container_class;
7376 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7377 if (!mono_error_ok (&error)) {
7378 mono_error_set_pending_exception (&error);
7383 if (klass == method->klass)
7386 /*This is possible if definition == FALSE.
7387 * Do it here to be really sure we don't read invalid memory.
7389 if (slot >= klass->vtable_size)
7392 mono_class_setup_vtable (klass);
7394 result = klass->vtable [slot];
7395 if (result == NULL) {
7396 /* It is an abstract method */
7397 gpointer iter = NULL;
7398 while ((result = mono_class_get_methods (klass, &iter)))
7399 if (result->slot == slot)
7406 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7407 mono_error_raise_exception (&error);
7411 ICALL_EXPORT MonoString*
7412 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7414 MonoMethod *method = m->method;
7416 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7421 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7423 iter->sig = *(MonoMethodSignature**)argsp;
7425 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7426 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7429 /* FIXME: it's not documented what start is exactly... */
7433 iter->args = argsp + sizeof (gpointer);
7435 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7437 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7440 ICALL_EXPORT MonoTypedRef
7441 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7443 guint32 i, arg_size;
7447 i = iter->sig->sentinelpos + iter->next_arg;
7449 g_assert (i < iter->sig->param_count);
7451 res.type = iter->sig->params [i];
7452 res.klass = mono_class_from_mono_type (res.type);
7453 arg_size = mono_type_stack_size (res.type, &align);
7454 #if defined(__arm__) || defined(__mips__)
7455 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7457 res.value = iter->args;
7458 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7459 /* Values are stored as 8 byte register sized objects, but 'value'
7460 * is dereferenced as a pointer in other routines.
7462 res.value = (char*)res.value + 4;
7464 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7465 if (arg_size <= sizeof (gpointer)) {
7467 int padding = arg_size - mono_type_size (res.type, &dummy);
7468 res.value = (guint8*)res.value + padding;
7471 iter->args = (char*)iter->args + arg_size;
7474 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7479 ICALL_EXPORT MonoTypedRef
7480 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7482 guint32 i, arg_size;
7486 i = iter->sig->sentinelpos + iter->next_arg;
7488 g_assert (i < iter->sig->param_count);
7490 while (i < iter->sig->param_count) {
7491 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7493 res.type = iter->sig->params [i];
7494 res.klass = mono_class_from_mono_type (res.type);
7495 /* FIXME: endianess issue... */
7496 arg_size = mono_type_stack_size (res.type, &align);
7497 #if defined(__arm__) || defined(__mips__)
7498 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7500 res.value = iter->args;
7501 iter->args = (char*)iter->args + arg_size;
7503 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7506 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7514 ICALL_EXPORT MonoType*
7515 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7519 i = iter->sig->sentinelpos + iter->next_arg;
7521 g_assert (i < iter->sig->param_count);
7523 return iter->sig->params [i];
7526 ICALL_EXPORT MonoObject*
7527 mono_TypedReference_ToObject (MonoTypedRef* tref)
7529 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7530 MonoObject** objp = (MonoObject **)tref->value;
7534 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
7537 ICALL_EXPORT MonoTypedRef
7538 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7541 MonoReflectionField *f;
7543 MonoType *ftype = NULL;
7547 memset (&res, 0, sizeof (res));
7550 g_assert (mono_array_length (fields) > 0);
7552 klass = target->vtable->klass;
7554 for (i = 0; i < mono_array_length (fields); ++i) {
7555 f = mono_array_get (fields, MonoReflectionField*, i);
7557 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7560 if (f->field->parent != klass) {
7561 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7565 p = (guint8*)target + f->field->offset;
7567 p += f->field->offset - sizeof (MonoObject);
7568 klass = mono_class_from_mono_type (f->field->type);
7569 ftype = f->field->type;
7573 res.klass = mono_class_from_mono_type (ftype);
7580 prelink_method (MonoMethod *method, MonoError *error)
7582 const char *exc_class, *exc_arg;
7584 mono_error_init (error);
7585 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7587 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7589 mono_error_set_exception_instance (error,
7590 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7593 /* create the wrapper, too? */
7597 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7601 prelink_method (method->method, &error);
7602 mono_error_raise_exception (&error);
7606 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7609 MonoClass *klass = mono_class_from_mono_type (type->type);
7611 gpointer iter = NULL;
7613 mono_class_init_checked (klass, &error);
7614 mono_error_raise_exception (&error);
7616 while ((m = mono_class_get_methods (klass, &iter))) {
7617 prelink_method (m, &error);
7618 mono_error_raise_exception (&error);
7622 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7624 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7625 gint32 const **exponents,
7626 gunichar2 const **digitLowerTable,
7627 gunichar2 const **digitUpperTable,
7628 gint64 const **tenPowersList,
7629 gint32 const **decHexDigits)
7631 *mantissas = Formatter_MantissaBitsTable;
7632 *exponents = Formatter_TensExponentTable;
7633 *digitLowerTable = Formatter_DigitLowerTable;
7634 *digitUpperTable = Formatter_DigitUpperTable;
7635 *tenPowersList = Formatter_TenPowersList;
7636 *decHexDigits = Formatter_DecHexDigits;
7640 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7641 * and avoid useless allocations.
7644 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7646 MonoReflectionType *rt;
7650 mono_error_init (error);
7651 for (i = 0; i < type->num_mods; ++i) {
7652 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7657 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7659 for (i = 0; i < type->num_mods; ++i) {
7660 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7661 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7662 return_val_if_nok (error, NULL);
7664 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7665 return_val_if_nok (error, NULL);
7667 mono_array_setref (res, count, rt);
7674 ICALL_EXPORT MonoArray*
7675 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7678 MonoType *type = param->ClassImpl->type;
7679 MonoClass *member_class = mono_object_class (param->MemberImpl);
7680 MonoMethod *method = NULL;
7683 MonoMethodSignature *sig;
7686 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7687 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7688 method = rmethod->method;
7689 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7690 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7691 if (!(method = prop->property->get))
7692 method = prop->property->set;
7695 char *type_name = mono_type_get_full_name (member_class);
7696 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7697 MonoException *ex = mono_get_exception_not_supported (msg);
7700 mono_set_pending_exception (ex);
7704 image = method->klass->image;
7705 pos = param->PositionImpl;
7706 sig = mono_method_signature (method);
7710 type = sig->params [pos];
7712 res = type_array_from_modifiers (image, type, optional, &error);
7713 mono_error_raise_exception (&error);
7718 get_property_type (MonoProperty *prop)
7720 MonoMethodSignature *sig;
7722 sig = mono_method_signature (prop->get);
7724 } else if (prop->set) {
7725 sig = mono_method_signature (prop->set);
7726 return sig->params [sig->param_count - 1];
7731 ICALL_EXPORT MonoArray*
7732 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7735 MonoType *type = get_property_type (property->property);
7736 MonoImage *image = property->klass->image;
7741 res = type_array_from_modifiers (image, type, optional, &error);
7742 mono_error_raise_exception (&error);
7747 *Construct a MonoType suited to be used to decode a constant blob object.
7749 * @type is the target type which will be constructed
7750 * @blob_type is the blob type, for example, that comes from the constant table
7751 * @real_type is the expected constructed type.
7754 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7756 type->type = blob_type;
7757 type->data.klass = NULL;
7758 if (blob_type == MONO_TYPE_CLASS)
7759 type->data.klass = mono_defaults.object_class;
7760 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7761 /* For enums, we need to use the base type */
7762 type->type = MONO_TYPE_VALUETYPE;
7763 type->data.klass = mono_class_from_mono_type (real_type);
7765 type->data.klass = mono_class_from_mono_type (real_type);
7768 ICALL_EXPORT MonoObject*
7769 property_info_get_default_value (MonoReflectionProperty *property)
7772 MonoProperty *prop = property->property;
7773 MonoType *type = get_property_type (prop);
7774 MonoDomain *domain = mono_object_domain (property);
7775 MonoTypeEnum def_type;
7776 const char *def_value;
7779 mono_class_init (prop->parent);
7781 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7782 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7786 def_value = mono_class_get_property_default_value (prop, &def_type);
7788 mono_type_from_blob_type (&blob_type, def_type, type);
7789 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7794 ICALL_EXPORT MonoBoolean
7795 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7798 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7799 MonoCustomAttrInfo *cinfo;
7802 mono_class_init_checked (attr_class, &error);
7803 mono_error_raise_exception (&error);
7805 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7806 if (!is_ok (&error)) {
7807 mono_error_set_pending_exception (&error);
7812 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7814 mono_custom_attrs_free (cinfo);
7818 ICALL_EXPORT MonoArray*
7819 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7821 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7826 mono_class_init_checked (attr_class, &error);
7827 mono_error_raise_exception (&error);
7830 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7831 if (!mono_error_ok (&error)) {
7832 mono_error_set_pending_exception (&error);
7836 if (mono_loader_get_last_error ()) {
7837 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7844 ICALL_EXPORT MonoArray*
7845 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7849 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7850 mono_error_set_pending_exception (&error);
7855 ICALL_EXPORT MonoString*
7856 ves_icall_Mono_Runtime_GetDisplayName (void)
7859 MonoString *display_name;
7861 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7862 display_name = mono_string_new (mono_domain_get (), info);
7864 return display_name;
7867 ICALL_EXPORT MonoString*
7868 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7871 MonoString *message;
7875 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7876 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7879 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7881 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7882 mono_error_raise_exception (&error);
7889 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7892 char *path_str = mono_string_to_utf8 (path);
7894 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7902 ICALL_EXPORT gpointer
7903 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
7905 return GetCurrentProcess ();
7908 ICALL_EXPORT MonoBoolean
7909 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
7911 return GetExitCodeProcess (handle, (guint32*) exitcode);
7914 ICALL_EXPORT MonoBoolean
7915 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
7917 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
7918 return CloseHandle (handle);
7920 return CloseProcess (handle);
7924 ICALL_EXPORT MonoBoolean
7925 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
7927 return TerminateProcess (handle, exitcode);
7931 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
7933 return WaitForInputIdle (handle, milliseconds);
7936 ICALL_EXPORT MonoBoolean
7937 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
7939 return GetProcessWorkingSetSize (handle, min, max);
7942 ICALL_EXPORT MonoBoolean
7943 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
7945 return SetProcessWorkingSetSize (handle, min, max);
7948 ICALL_EXPORT MonoBoolean
7949 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
7951 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
7955 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
7957 return mono_process_current_pid ();
7961 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
7963 return GetPriorityClass (handle);
7966 ICALL_EXPORT MonoBoolean
7967 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
7969 return SetPriorityClass (handle, priorityClass);
7972 #ifndef DISABLE_ICALL_TABLES
7974 #define ICALL_TYPE(id,name,first)
7975 #define ICALL(id,name,func) Icall_ ## id,
7978 #include "metadata/icall-def.h"
7984 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7985 #define ICALL(id,name,func)
7987 #include "metadata/icall-def.h"
7993 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7994 #define ICALL(id,name,func)
7996 guint16 first_icall;
7999 static const IcallTypeDesc
8000 icall_type_descs [] = {
8001 #include "metadata/icall-def.h"
8005 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8008 #define ICALL_TYPE(id,name,first)
8011 #ifdef HAVE_ARRAY_ELEM_INIT
8012 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8013 #define MSGSTRFIELD1(line) str##line
8015 static const struct msgstrtn_t {
8016 #define ICALL(id,name,func)
8018 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8019 #include "metadata/icall-def.h"
8021 } icall_type_names_str = {
8022 #define ICALL_TYPE(id,name,first) (name),
8023 #include "metadata/icall-def.h"
8026 static const guint16 icall_type_names_idx [] = {
8027 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8028 #include "metadata/icall-def.h"
8031 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8033 static const struct msgstr_t {
8035 #define ICALL_TYPE(id,name,first)
8036 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8037 #include "metadata/icall-def.h"
8039 } icall_names_str = {
8040 #define ICALL(id,name,func) (name),
8041 #include "metadata/icall-def.h"
8044 static const guint16 icall_names_idx [] = {
8045 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8046 #include "metadata/icall-def.h"
8049 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8055 #define ICALL_TYPE(id,name,first) name,
8056 #define ICALL(id,name,func)
8057 static const char* const
8058 icall_type_names [] = {
8059 #include "metadata/icall-def.h"
8063 #define icall_type_name_get(id) (icall_type_names [(id)])
8067 #define ICALL_TYPE(id,name,first)
8068 #define ICALL(id,name,func) name,
8069 static const char* const
8071 #include "metadata/icall-def.h"
8074 #define icall_name_get(id) icall_names [(id)]
8076 #endif /* !HAVE_ARRAY_ELEM_INIT */
8080 #define ICALL_TYPE(id,name,first)
8081 #define ICALL(id,name,func) func,
8082 static const gconstpointer
8083 icall_functions [] = {
8084 #include "metadata/icall-def.h"
8088 #ifdef ENABLE_ICALL_SYMBOL_MAP
8091 #define ICALL_TYPE(id,name,first)
8092 #define ICALL(id,name,func) #func,
8093 static const gconstpointer
8094 icall_symbols [] = {
8095 #include "metadata/icall-def.h"
8100 #endif /* DISABLE_ICALL_TABLES */
8102 static mono_mutex_t icall_mutex;
8103 static GHashTable *icall_hash = NULL;
8104 static GHashTable *jit_icall_hash_name = NULL;
8105 static GHashTable *jit_icall_hash_addr = NULL;
8108 mono_icall_init (void)
8110 #ifndef DISABLE_ICALL_TABLES
8113 /* check that tables are sorted: disable in release */
8116 const char *prev_class = NULL;
8117 const char *prev_method;
8119 for (i = 0; i < Icall_type_num; ++i) {
8120 const IcallTypeDesc *desc;
8123 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8124 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8125 prev_class = icall_type_name_get (i);
8126 desc = &icall_type_descs [i];
8127 num_icalls = icall_desc_num_icalls (desc);
8128 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8129 for (j = 0; j < num_icalls; ++j) {
8130 const char *methodn = icall_name_get (desc->first_icall + j);
8131 if (prev_method && strcmp (prev_method, methodn) >= 0)
8132 g_print ("method %s should come before method %s\n", methodn, prev_method);
8133 prev_method = methodn;
8139 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8140 mono_os_mutex_init (&icall_mutex);
8144 mono_icall_lock (void)
8146 mono_locks_os_acquire (&icall_mutex, IcallLock);
8150 mono_icall_unlock (void)
8152 mono_locks_os_release (&icall_mutex, IcallLock);
8156 mono_icall_cleanup (void)
8158 g_hash_table_destroy (icall_hash);
8159 g_hash_table_destroy (jit_icall_hash_name);
8160 g_hash_table_destroy (jit_icall_hash_addr);
8161 mono_os_mutex_destroy (&icall_mutex);
8165 * mono_add_internal_call:
8166 * @name: method specification to surface to the managed world
8167 * @method: pointer to a C method to invoke when the method is called
8169 * This method surfaces the C function pointed by @method as a method
8170 * that has been surfaced in managed code with the method specified in
8171 * @name as an internal call.
8173 * Internal calls are surfaced to all app domains loaded and they are
8174 * accessibly by a type with the specified name.
8176 * You must provide a fully qualified type name, that is namespaces
8177 * and type name, followed by a colon and the method name, with an
8178 * optional signature to bind.
8180 * For example, the following are all valid declarations:
8182 * "MyApp.Services.ScriptService:Accelerate"
8183 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8185 * You use method parameters in cases where there might be more than
8186 * one surface method to managed code. That way you can register different
8187 * internal calls for different method overloads.
8189 * The internal calls are invoked with no marshalling. This means that .NET
8190 * types like System.String are exposed as `MonoString *` parameters. This is
8191 * different than the way that strings are surfaced in P/Invoke.
8193 * For more information on how the parameters are marshalled, see the
8194 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8197 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8198 * reference for more information on the format of method descriptions.
8201 mono_add_internal_call (const char *name, gconstpointer method)
8205 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8207 mono_icall_unlock ();
8210 #ifndef DISABLE_ICALL_TABLES
8212 #ifdef HAVE_ARRAY_ELEM_INIT
8214 compare_method_imap (const void *key, const void *elem)
8216 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8217 return strcmp (key, method_name);
8221 find_method_icall (const IcallTypeDesc *imap, const char *name)
8223 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);
8226 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8230 compare_class_imap (const void *key, const void *elem)
8232 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8233 return strcmp (key, class_name);
8236 static const IcallTypeDesc*
8237 find_class_icalls (const char *name)
8239 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);
8242 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8245 #else /* HAVE_ARRAY_ELEM_INIT */
8248 compare_method_imap (const void *key, const void *elem)
8250 const char** method_name = (const char**)elem;
8251 return strcmp (key, *method_name);
8255 find_method_icall (const IcallTypeDesc *imap, const char *name)
8257 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8260 return (gpointer)icall_functions [(nameslot - icall_names)];
8264 compare_class_imap (const void *key, const void *elem)
8266 const char** class_name = (const char**)elem;
8267 return strcmp (key, *class_name);
8270 static const IcallTypeDesc*
8271 find_class_icalls (const char *name)
8273 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8276 return &icall_type_descs [nameslot - icall_type_names];
8279 #endif /* HAVE_ARRAY_ELEM_INIT */
8281 #endif /* DISABLE_ICALL_TABLES */
8284 * we should probably export this as an helper (handle nested types).
8285 * Returns the number of chars written in buf.
8288 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8290 int nspacelen, cnamelen;
8291 nspacelen = strlen (klass->name_space);
8292 cnamelen = strlen (klass->name);
8293 if (nspacelen + cnamelen + 2 > bufsize)
8296 memcpy (buf, klass->name_space, nspacelen);
8297 buf [nspacelen ++] = '.';
8299 memcpy (buf + nspacelen, klass->name, cnamelen);
8300 buf [nspacelen + cnamelen] = 0;
8301 return nspacelen + cnamelen;
8304 #ifdef DISABLE_ICALL_TABLES
8306 no_icall_table (void)
8308 g_assert_not_reached ();
8313 mono_lookup_internal_call (MonoMethod *method)
8318 int typelen = 0, mlen, siglen;
8320 #ifndef DISABLE_ICALL_TABLES
8321 const IcallTypeDesc *imap = NULL;
8324 g_assert (method != NULL);
8326 if (method->is_inflated)
8327 method = ((MonoMethodInflated *) method)->declaring;
8329 if (method->klass->nested_in) {
8330 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8334 mname [pos++] = '/';
8337 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8343 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8348 #ifndef DISABLE_ICALL_TABLES
8349 imap = find_class_icalls (mname);
8352 mname [typelen] = ':';
8353 mname [typelen + 1] = ':';
8355 mlen = strlen (method->name);
8356 memcpy (mname + typelen + 2, method->name, mlen);
8357 sigstart = mname + typelen + 2 + mlen;
8360 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8361 siglen = strlen (tmpsig);
8362 if (typelen + mlen + siglen + 6 > sizeof (mname))
8365 memcpy (sigstart + 1, tmpsig, siglen);
8366 sigstart [siglen + 1] = ')';
8367 sigstart [siglen + 2] = 0;
8372 res = g_hash_table_lookup (icall_hash, mname);
8374 mono_icall_unlock ();;
8377 /* try without signature */
8379 res = g_hash_table_lookup (icall_hash, mname);
8381 mono_icall_unlock ();
8385 #ifdef DISABLE_ICALL_TABLES
8386 mono_icall_unlock ();
8387 /* Fail only when the result is actually used */
8388 /* mono_marshal_get_native_wrapper () depends on this */
8389 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8390 return ves_icall_System_String_ctor_RedirectToCreateString;
8392 return no_icall_table;
8394 /* it wasn't found in the static call tables */
8396 mono_icall_unlock ();
8399 res = find_method_icall (imap, sigstart - mlen);
8401 mono_icall_unlock ();
8404 /* try _with_ signature */
8406 res = find_method_icall (imap, sigstart - mlen);
8408 mono_icall_unlock ();
8412 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8413 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8414 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8415 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8416 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");
8417 g_print ("If you see other errors or faults after this message they are probably related\n");
8418 g_print ("and you need to fix your mono install first.\n");
8420 mono_icall_unlock ();
8426 #ifdef ENABLE_ICALL_SYMBOL_MAP
8428 func_cmp (gconstpointer key, gconstpointer p)
8430 return (gsize)key - (gsize)*(gsize*)p;
8435 * mono_lookup_icall_symbol:
8437 * Given the icall METHOD, returns its C symbol.
8440 mono_lookup_icall_symbol (MonoMethod *m)
8442 #ifdef DISABLE_ICALL_TABLES
8443 g_assert_not_reached ();
8446 #ifdef ENABLE_ICALL_SYMBOL_MAP
8450 static gconstpointer *functions_sorted;
8451 static const char**symbols_sorted;
8452 static gboolean inited;
8457 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8458 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8459 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8460 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8461 /* Bubble sort the two arrays */
8465 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8466 if (functions_sorted [i] > functions_sorted [i + 1]) {
8469 tmp = functions_sorted [i];
8470 functions_sorted [i] = functions_sorted [i + 1];
8471 functions_sorted [i + 1] = tmp;
8472 tmp = symbols_sorted [i];
8473 symbols_sorted [i] = symbols_sorted [i + 1];
8474 symbols_sorted [i + 1] = tmp;
8481 func = mono_lookup_internal_call (m);
8484 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8488 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8490 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8491 g_assert_not_reached ();
8498 type_from_typename (char *type_name)
8500 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8502 if (!strcmp (type_name, "int"))
8503 klass = mono_defaults.int_class;
8504 else if (!strcmp (type_name, "ptr"))
8505 klass = mono_defaults.int_class;
8506 else if (!strcmp (type_name, "void"))
8507 klass = mono_defaults.void_class;
8508 else if (!strcmp (type_name, "int32"))
8509 klass = mono_defaults.int32_class;
8510 else if (!strcmp (type_name, "uint32"))
8511 klass = mono_defaults.uint32_class;
8512 else if (!strcmp (type_name, "int8"))
8513 klass = mono_defaults.sbyte_class;
8514 else if (!strcmp (type_name, "uint8"))
8515 klass = mono_defaults.byte_class;
8516 else if (!strcmp (type_name, "int16"))
8517 klass = mono_defaults.int16_class;
8518 else if (!strcmp (type_name, "uint16"))
8519 klass = mono_defaults.uint16_class;
8520 else if (!strcmp (type_name, "long"))
8521 klass = mono_defaults.int64_class;
8522 else if (!strcmp (type_name, "ulong"))
8523 klass = mono_defaults.uint64_class;
8524 else if (!strcmp (type_name, "float"))
8525 klass = mono_defaults.single_class;
8526 else if (!strcmp (type_name, "double"))
8527 klass = mono_defaults.double_class;
8528 else if (!strcmp (type_name, "object"))
8529 klass = mono_defaults.object_class;
8530 else if (!strcmp (type_name, "obj"))
8531 klass = mono_defaults.object_class;
8532 else if (!strcmp (type_name, "string"))
8533 klass = mono_defaults.string_class;
8534 else if (!strcmp (type_name, "bool"))
8535 klass = mono_defaults.boolean_class;
8536 else if (!strcmp (type_name, "boolean"))
8537 klass = mono_defaults.boolean_class;
8539 g_error ("%s", type_name);
8540 g_assert_not_reached ();
8542 return &klass->byval_arg;
8546 * LOCKING: Take the corlib image lock.
8548 MonoMethodSignature*
8549 mono_create_icall_signature (const char *sigstr)
8554 MonoMethodSignature *res, *res2;
8555 MonoImage *corlib = mono_defaults.corlib;
8557 mono_image_lock (corlib);
8558 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8559 mono_image_unlock (corlib);
8564 parts = g_strsplit (sigstr, " ", 256);
8573 res = mono_metadata_signature_alloc (corlib, len - 1);
8578 * Under windows, the default pinvoke calling convention is STDCALL but
8581 res->call_convention = MONO_CALL_C;
8584 res->ret = type_from_typename (parts [0]);
8585 for (i = 1; i < len; ++i) {
8586 res->params [i - 1] = type_from_typename (parts [i]);
8591 mono_image_lock (corlib);
8592 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8594 res = res2; /*Value is allocated in the image pool*/
8596 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8597 mono_image_unlock (corlib);
8603 mono_find_jit_icall_by_name (const char *name)
8605 MonoJitICallInfo *info;
8606 g_assert (jit_icall_hash_name);
8609 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8610 mono_icall_unlock ();
8615 mono_find_jit_icall_by_addr (gconstpointer addr)
8617 MonoJitICallInfo *info;
8618 g_assert (jit_icall_hash_addr);
8621 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8622 mono_icall_unlock ();
8628 * mono_get_jit_icall_info:
8630 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8631 * caller should access it while holding the icall lock.
8634 mono_get_jit_icall_info (void)
8636 return jit_icall_hash_name;
8640 * mono_lookup_jit_icall_symbol:
8642 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8645 mono_lookup_jit_icall_symbol (const char *name)
8647 MonoJitICallInfo *info;
8648 const char *res = NULL;
8651 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8653 res = info->c_symbol;
8654 mono_icall_unlock ();
8659 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8662 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8663 mono_icall_unlock ();
8667 * 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
8668 * icalls without wrappers in some cases.
8671 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8673 MonoJitICallInfo *info;
8680 if (!jit_icall_hash_name) {
8681 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8682 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8685 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8686 g_warning ("jit icall already defined \"%s\"\n", name);
8687 g_assert_not_reached ();
8690 info = g_new0 (MonoJitICallInfo, 1);
8695 info->c_symbol = c_symbol;
8696 info->no_raise = no_raise;
8699 info->wrapper = func;
8701 info->wrapper = NULL;
8704 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8705 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8707 mono_icall_unlock ();
8712 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8714 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);