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 ();
1236 ICALL_EXPORT MonoReflectionModule*
1237 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1240 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1241 mono_error_set_pending_exception (&error);
1246 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1248 MonoMethod **dest = (MonoMethod **)data;
1250 /* skip unmanaged frames */
1266 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1268 MonoMethod **dest = (MonoMethod **)data;
1270 /* skip unmanaged frames */
1275 if (!strcmp (m->klass->name_space, "System.Reflection"))
1284 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1286 MonoMethod **dest = (MonoMethod **)data;
1288 /* skip unmanaged frames */
1292 if (m->wrapper_type != MONO_WRAPPER_NONE)
1295 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1309 static MonoReflectionType *
1310 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1312 MonoMethod *m, *dest;
1314 MonoType *type = NULL;
1315 MonoAssembly *assembly = NULL;
1316 gboolean type_resolve = FALSE;
1318 mono_error_init (error);
1321 * We must compute the calling assembly as type loading must happen under a metadata context.
1322 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1323 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1325 m = mono_method_get_last_managed ();
1328 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1333 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1334 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1335 * to crash. This only seems to happen in some strange remoting
1336 * scenarios and I was unable to figure out what's happening there.
1337 * Dec 10, 2005 - Martin.
1341 assembly = dest->klass->image->assembly;
1342 type_resolve = TRUE;
1344 g_warning (G_STRLOC);
1347 if (info->assembly.name)
1348 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1352 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1353 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1356 if (!info->assembly.name && !type) /* try mscorlib */
1357 type = mono_reflection_get_type (NULL, info, ignoreCase, &type_resolve);
1359 if (assembly && !type && type_resolve) {
1360 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1361 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1367 return mono_type_get_object_checked (mono_domain_get (), type, error);
1370 ICALL_EXPORT MonoReflectionType*
1371 ves_icall_System_Type_internal_from_name (MonoString *name,
1372 MonoBoolean throwOnError,
1373 MonoBoolean ignoreCase)
1376 char *str = mono_string_to_utf8 (name);
1377 MonoTypeNameParse info;
1378 MonoReflectionType *type;
1381 parsedOk = mono_reflection_parse_type (str, &info);
1383 /* mono_reflection_parse_type() mangles the string */
1385 mono_reflection_free_type_info (&info);
1388 mono_set_pending_exception (mono_get_exception_argument("typeName", "failed parse"));
1393 type = type_from_parsed_name (&info, ignoreCase, &error);
1395 mono_reflection_free_type_info (&info);
1398 if (!mono_error_ok (&error)) {
1400 mono_error_set_pending_exception (&error);
1402 mono_error_cleanup (&error);
1407 MonoException *e = NULL;
1410 e = mono_get_exception_type_load (name, NULL);
1412 mono_loader_clear_error ();
1414 mono_set_pending_exception (e);
1423 ICALL_EXPORT MonoReflectionType*
1424 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1427 MonoReflectionType *ret;
1428 MonoDomain *domain = mono_domain_get ();
1430 ret = mono_type_get_object_checked (domain, handle, &error);
1431 mono_error_raise_exception (&error);
1436 /* System.TypeCode */
1455 TYPECODE_STRING = 18
1458 ICALL_EXPORT guint32
1459 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1461 int t = type->type->type;
1463 if (type->type->byref)
1464 return TYPECODE_OBJECT;
1468 case MONO_TYPE_VOID:
1469 return TYPECODE_OBJECT;
1470 case MONO_TYPE_BOOLEAN:
1471 return TYPECODE_BOOLEAN;
1473 return TYPECODE_BYTE;
1475 return TYPECODE_SBYTE;
1477 return TYPECODE_UINT16;
1479 return TYPECODE_INT16;
1480 case MONO_TYPE_CHAR:
1481 return TYPECODE_CHAR;
1485 return TYPECODE_OBJECT;
1487 return TYPECODE_UINT32;
1489 return TYPECODE_INT32;
1491 return TYPECODE_UINT64;
1493 return TYPECODE_INT64;
1495 return TYPECODE_SINGLE;
1497 return TYPECODE_DOUBLE;
1498 case MONO_TYPE_VALUETYPE: {
1499 MonoClass *klass = type->type->data.klass;
1501 if (klass->enumtype) {
1502 t = mono_class_enum_basetype (klass)->type;
1504 } else if (mono_is_corlib_image (klass->image)) {
1505 if (strcmp (klass->name_space, "System") == 0) {
1506 if (strcmp (klass->name, "Decimal") == 0)
1507 return TYPECODE_DECIMAL;
1508 else if (strcmp (klass->name, "DateTime") == 0)
1509 return TYPECODE_DATETIME;
1512 return TYPECODE_OBJECT;
1514 case MONO_TYPE_STRING:
1515 return TYPECODE_STRING;
1516 case MONO_TYPE_SZARRAY:
1517 case MONO_TYPE_ARRAY:
1518 case MONO_TYPE_OBJECT:
1520 case MONO_TYPE_MVAR:
1521 case MONO_TYPE_TYPEDBYREF:
1522 return TYPECODE_OBJECT;
1523 case MONO_TYPE_CLASS:
1525 MonoClass *klass = type->type->data.klass;
1526 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1527 if (strcmp (klass->name, "DBNull") == 0)
1528 return TYPECODE_DBNULL;
1531 return TYPECODE_OBJECT;
1532 case MONO_TYPE_GENERICINST:
1533 return TYPECODE_OBJECT;
1535 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1541 mono_type_is_primitive (MonoType *type)
1543 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1544 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1548 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1550 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1551 return mono_class_enum_basetype (type->data.klass);
1552 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1553 return mono_class_enum_basetype (type->data.generic_class->container_class);
1557 ICALL_EXPORT guint32
1558 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1563 g_assert (type != NULL);
1565 klass = mono_class_from_mono_type (type->type);
1566 klassc = mono_class_from_mono_type (c->type);
1568 if (type->type->byref ^ c->type->byref)
1571 if (type->type->byref) {
1572 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1573 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1575 klass = mono_class_from_mono_type (t);
1576 klassc = mono_class_from_mono_type (ot);
1578 if (mono_type_is_primitive (t)) {
1579 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1580 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1581 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1582 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1583 return t->type == ot->type;
1585 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1588 if (klass->valuetype)
1589 return klass == klassc;
1590 return klass->valuetype == klassc->valuetype;
1593 return mono_class_is_assignable_from (klass, klassc);
1596 ICALL_EXPORT guint32
1597 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1600 MonoClass *klass = mono_class_from_mono_type (type->type);
1601 mono_class_init_checked (klass, &error);
1602 mono_error_raise_exception (&error);
1603 return mono_object_isinst (obj, klass) != NULL;
1606 ICALL_EXPORT guint32
1607 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1609 MonoClass *klass = mono_class_from_mono_type (type->type);
1610 return klass->flags;
1613 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1614 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1617 MonoClass *klass = field->field->parent;
1618 MonoMarshalType *info;
1622 if (klass->generic_container ||
1623 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1626 ftype = mono_field_get_type (field->field);
1627 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1630 info = mono_marshal_load_type_info (klass);
1632 for (i = 0; i < info->num_fields; ++i) {
1633 if (info->fields [i].field == field->field) {
1634 if (!info->fields [i].mspec)
1637 MonoReflectionMarshalAsAttribute* obj;
1638 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1639 if (!mono_error_ok (&error))
1640 mono_error_set_pending_exception (&error);
1649 ICALL_EXPORT MonoReflectionField*
1650 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1653 gboolean found = FALSE;
1660 klass = handle->parent;
1662 klass = mono_class_from_mono_type (type);
1664 /* Check that the field belongs to the class */
1665 for (k = klass; k; k = k->parent) {
1666 if (k == handle->parent) {
1673 /* The managed code will throw the exception */
1677 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1678 mono_error_raise_exception (&error);
1682 ICALL_EXPORT MonoArray*
1683 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1686 MonoType *type = mono_field_get_type_checked (field->field, &error);
1689 if (!mono_error_ok (&error)) {
1690 mono_error_set_pending_exception (&error);
1694 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1695 mono_error_raise_exception (&error);
1700 vell_icall_get_method_attributes (MonoMethod *method)
1702 return method->flags;
1706 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1709 MonoReflectionType *rt;
1710 MonoDomain *domain = mono_domain_get ();
1711 MonoMethodSignature* sig;
1713 sig = mono_method_signature_checked (method, &error);
1714 if (!mono_error_ok (&error)) {
1715 mono_error_set_pending_exception (&error);
1719 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1720 if (!mono_error_ok (&error)) {
1721 mono_error_set_pending_exception (&error);
1725 MONO_STRUCT_SETREF (info, parent, rt);
1727 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1728 if (!mono_error_ok (&error)) {
1729 mono_error_set_pending_exception (&error);
1733 MONO_STRUCT_SETREF (info, ret, rt);
1735 info->attrs = method->flags;
1736 info->implattrs = method->iflags;
1737 if (sig->call_convention == MONO_CALL_DEFAULT)
1738 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1740 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1745 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1748 ICALL_EXPORT MonoArray*
1749 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1751 MonoDomain *domain = mono_domain_get ();
1753 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1756 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1757 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1760 MonoDomain *domain = mono_domain_get ();
1761 MonoReflectionMarshalAsAttribute* res = NULL;
1762 MonoMarshalSpec **mspecs;
1765 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1766 mono_method_get_marshal_info (method, mspecs);
1769 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1770 if (!mono_error_ok (&error)) {
1771 mono_error_set_pending_exception (&error);
1776 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1778 mono_metadata_free_marshal_spec (mspecs [i]);
1785 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1787 MonoClass *parent = field->field->parent;
1788 if (!parent->size_inited)
1789 mono_class_init (parent);
1790 mono_class_setup_fields_locking (parent);
1792 return field->field->offset - sizeof (MonoObject);
1795 ICALL_EXPORT MonoReflectionType*
1796 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1799 MonoReflectionType *ret;
1802 parent = declaring? field->field->parent: field->klass;
1804 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1805 mono_error_raise_exception (&error);
1811 ICALL_EXPORT MonoObject *
1812 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1814 MonoClass *fklass = field->klass;
1815 MonoClassField *cf = field->field;
1816 MonoDomain *domain = mono_object_domain (field);
1818 if (fklass->image->assembly->ref_only) {
1819 mono_set_pending_exception (mono_get_exception_invalid_operation (
1820 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1824 if (mono_security_core_clr_enabled ())
1825 mono_security_core_clr_ensure_reflection_access_field (cf);
1827 return mono_field_get_value_object (domain, cf, obj);
1831 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1834 MonoClassField *cf = field->field;
1838 if (field->klass->image->assembly->ref_only) {
1839 mono_set_pending_exception (mono_get_exception_invalid_operation (
1840 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1844 if (mono_security_core_clr_enabled ())
1845 mono_security_core_clr_ensure_reflection_access_field (cf);
1847 type = mono_field_get_type_checked (cf, &error);
1848 if (!mono_error_ok (&error)) {
1849 mono_error_set_pending_exception (&error);
1853 v = (gchar *) value;
1855 switch (type->type) {
1858 case MONO_TYPE_BOOLEAN:
1861 case MONO_TYPE_CHAR:
1870 case MONO_TYPE_VALUETYPE:
1873 v += sizeof (MonoObject);
1875 case MONO_TYPE_STRING:
1876 case MONO_TYPE_OBJECT:
1877 case MONO_TYPE_CLASS:
1878 case MONO_TYPE_ARRAY:
1879 case MONO_TYPE_SZARRAY:
1882 case MONO_TYPE_GENERICINST: {
1883 MonoGenericClass *gclass = type->data.generic_class;
1884 g_assert (!gclass->context.class_inst->is_open);
1886 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1887 MonoClass *nklass = mono_class_from_mono_type (type);
1888 MonoObject *nullable;
1891 * Convert the boxed vtype into a Nullable structure.
1892 * This is complicated by the fact that Nullables have
1893 * a variable structure.
1895 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1896 if (!mono_error_ok (&error)) {
1897 mono_error_set_pending_exception (&error);
1901 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1903 v = (gchar *)mono_object_unbox (nullable);
1906 if (gclass->container_class->valuetype && (v != NULL))
1907 v += sizeof (MonoObject);
1911 g_error ("type 0x%x not handled in "
1912 "ves_icall_FieldInfo_SetValueInternal", type->type);
1917 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1918 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
1919 if (!is_ok (&error)) {
1920 mono_error_set_pending_exception (&error);
1923 if (!vtable->initialized) {
1924 if (!mono_runtime_class_init_full (vtable, &error)) {
1925 mono_error_set_pending_exception (&error);
1929 mono_field_static_set_value (vtable, cf, v);
1931 mono_field_set_value (obj, cf, v);
1936 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1945 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1946 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1950 if (MONO_TYPE_IS_REFERENCE (f->type))
1951 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1953 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1956 ICALL_EXPORT MonoObject *
1957 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1959 MonoObject *o = NULL;
1960 MonoClassField *field = rfield->field;
1962 MonoDomain *domain = mono_object_domain (rfield);
1964 MonoTypeEnum def_type;
1965 const char *def_value;
1969 mono_class_init (field->parent);
1971 t = mono_field_get_type_checked (field, &error);
1972 if (!mono_error_ok (&error)) {
1973 mono_error_set_pending_exception (&error);
1977 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
1978 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1982 if (image_is_dynamic (field->parent->image)) {
1983 MonoClass *klass = field->parent;
1984 int fidx = field - klass->fields;
1986 g_assert (fidx >= 0 && fidx < klass->field.count);
1987 g_assert (klass->ext);
1988 g_assert (klass->ext->field_def_values);
1989 def_type = klass->ext->field_def_values [fidx].def_type;
1990 def_value = klass->ext->field_def_values [fidx].data;
1991 if (def_type == MONO_TYPE_END) {
1992 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1996 def_value = mono_class_get_field_default_value (field, &def_type);
1997 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
1999 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2004 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2008 case MONO_TYPE_BOOLEAN:
2011 case MONO_TYPE_CHAR:
2019 case MONO_TYPE_R8: {
2022 /* boxed value type */
2023 t = g_new0 (MonoType, 1);
2025 klass = mono_class_from_mono_type (t);
2027 o = mono_object_new_checked (domain, klass, &error);
2028 if (!mono_error_ok (&error)) {
2029 mono_error_set_pending_exception (&error);
2032 v = ((gchar *) o) + sizeof (MonoObject);
2033 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2036 case MONO_TYPE_STRING:
2037 case MONO_TYPE_CLASS:
2038 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2041 g_assert_not_reached ();
2047 ICALL_EXPORT MonoReflectionType*
2048 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2051 MonoReflectionType *ret;
2054 type = mono_field_get_type_checked (ref_field->field, &error);
2055 if (!mono_error_ok (&error)) {
2056 mono_error_set_pending_exception (&error);
2060 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2061 if (!mono_error_ok (&error)) {
2062 mono_error_set_pending_exception (&error);
2069 /* From MonoProperty.cs */
2071 PInfo_Attributes = 1,
2072 PInfo_GetMethod = 1 << 1,
2073 PInfo_SetMethod = 1 << 2,
2074 PInfo_ReflectedType = 1 << 3,
2075 PInfo_DeclaringType = 1 << 4,
2080 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2083 MonoReflectionType *rt;
2084 MonoReflectionMethod *rm;
2085 MonoDomain *domain = mono_object_domain (property);
2086 const MonoProperty *pproperty = property->property;
2088 if ((req_info & PInfo_ReflectedType) != 0) {
2089 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2090 mono_error_raise_exception (&error);
2092 MONO_STRUCT_SETREF (info, parent, rt);
2094 if ((req_info & PInfo_DeclaringType) != 0) {
2095 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2096 mono_error_raise_exception (&error);
2098 MONO_STRUCT_SETREF (info, declaring_type, rt);
2101 if ((req_info & PInfo_Name) != 0)
2102 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2104 if ((req_info & PInfo_Attributes) != 0)
2105 info->attrs = pproperty->attrs;
2107 if ((req_info & PInfo_GetMethod) != 0) {
2108 if (pproperty->get &&
2109 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2110 pproperty->get->klass == property->klass)) {
2111 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2112 mono_error_raise_exception (&error);
2117 MONO_STRUCT_SETREF (info, get, rm);
2119 if ((req_info & PInfo_SetMethod) != 0) {
2120 if (pproperty->set &&
2121 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2122 pproperty->set->klass == property->klass)) {
2123 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2124 mono_error_raise_exception (&error);
2129 MONO_STRUCT_SETREF (info, set, rm);
2132 * There may be other methods defined for properties, though, it seems they are not exposed
2133 * in the reflection API
2138 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2141 MonoReflectionType *rt;
2142 MonoReflectionMethod *rm;
2143 MonoDomain *domain = mono_object_domain (event);
2145 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2146 mono_error_raise_exception (&error);
2148 MONO_STRUCT_SETREF (info, reflected_type, rt);
2150 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2151 mono_error_raise_exception (&error);
2153 MONO_STRUCT_SETREF (info, declaring_type, rt);
2155 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2156 info->attrs = event->event->attrs;
2158 if (event->event->add) {
2159 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2160 mono_error_raise_exception (&error);
2165 MONO_STRUCT_SETREF (info, add_method, rm);
2167 if (event->event->remove) {
2168 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2169 mono_error_raise_exception (&error);
2174 MONO_STRUCT_SETREF (info, remove_method, rm);
2176 if (event->event->raise) {
2177 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2178 mono_error_raise_exception (&error);
2183 MONO_STRUCT_SETREF (info, raise_method, rm);
2185 #ifndef MONO_SMALL_CONFIG
2186 if (event->event->other) {
2188 while (event->event->other [n])
2190 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2192 for (i = 0; i < n; i++) {
2193 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2194 mono_error_raise_exception (&error);
2195 mono_array_setref (info->other_methods, i, rm);
2202 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2207 mono_class_setup_interfaces (klass, error);
2208 if (!mono_error_ok (error))
2211 for (i = 0; i < klass->interface_count; i++) {
2212 ic = klass->interfaces [i];
2213 g_hash_table_insert (ifaces, ic, ic);
2215 collect_interfaces (ic, ifaces, error);
2216 if (!mono_error_ok (error))
2222 MonoArray *iface_array;
2223 MonoGenericContext *context;
2227 } FillIfaceArrayData;
2230 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2232 MonoReflectionType *rt;
2233 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2234 MonoClass *ic = (MonoClass *)key;
2235 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2237 if (!mono_error_ok (data->error))
2240 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2241 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2242 if (!mono_error_ok (data->error))
2246 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2247 if (!mono_error_ok (data->error))
2250 mono_array_setref (data->iface_array, data->next_idx++, rt);
2253 mono_metadata_free_type (inflated);
2257 get_interfaces_hash (gconstpointer v1)
2259 MonoClass *k = (MonoClass*)v1;
2261 return k->type_token;
2264 ICALL_EXPORT MonoArray*
2265 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2268 MonoClass *klass = mono_class_from_mono_type (type->type);
2270 FillIfaceArrayData data = { 0 };
2273 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2275 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2276 data.context = mono_class_get_context (klass);
2277 klass = klass->generic_class->container_class;
2280 for (parent = klass; parent; parent = parent->parent) {
2281 mono_class_setup_interfaces (parent, &error);
2282 if (!mono_error_ok (&error))
2284 collect_interfaces (parent, iface_hash, &error);
2285 if (!mono_error_ok (&error))
2289 data.error = &error;
2290 data.domain = mono_object_domain (type);
2292 len = g_hash_table_size (iface_hash);
2294 g_hash_table_destroy (iface_hash);
2295 if (!data.domain->empty_types)
2296 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2297 return data.domain->empty_types;
2300 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2301 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2302 if (!mono_error_ok (&error))
2305 g_hash_table_destroy (iface_hash);
2306 return data.iface_array;
2309 g_hash_table_destroy (iface_hash);
2310 mono_error_set_pending_exception (&error);
2315 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2317 gboolean variance_used;
2318 MonoClass *klass = mono_class_from_mono_type (type->type);
2319 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2320 MonoReflectionMethod *member;
2323 int i = 0, len, ioffset;
2327 mono_class_init_checked (klass, &error);
2328 mono_error_raise_exception (&error);
2329 mono_class_init_checked (iclass, &error);
2330 mono_error_raise_exception (&error);
2332 mono_class_setup_vtable (klass);
2334 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2338 len = mono_class_num_methods (iclass);
2339 domain = mono_object_domain (type);
2340 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2341 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2343 while ((method = mono_class_get_methods (iclass, &iter))) {
2344 member = mono_method_get_object_checked (domain, method, iclass, &error);
2345 mono_error_raise_exception (&error);
2346 mono_array_setref (*methods, i, member);
2347 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2348 mono_error_raise_exception (&error);
2349 mono_array_setref (*targets, i, member);
2356 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2359 MonoClass *klass = mono_class_from_mono_type (type->type);
2361 mono_class_init_checked (klass, &error);
2362 mono_error_raise_exception (&error);
2364 if (image_is_dynamic (klass->image)) {
2365 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2366 *packing = tb->packing_size;
2367 *size = tb->class_size;
2369 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2373 ICALL_EXPORT MonoReflectionType*
2374 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2377 MonoReflectionType *ret;
2380 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2381 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2382 mono_error_raise_exception (&error);
2387 klass = mono_class_from_mono_type (type->type);
2388 mono_class_init_checked (klass, &error);
2389 mono_error_raise_exception (&error);
2391 // GetElementType should only return a type for:
2392 // Array Pointer PassedByRef
2393 if (type->type->byref)
2394 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2395 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2396 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2397 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2398 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2402 mono_error_raise_exception (&error);
2407 ICALL_EXPORT MonoReflectionType*
2408 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2411 MonoReflectionType *ret;
2413 if (type->type->byref)
2416 MonoClass *klass = mono_class_from_mono_type (type->type);
2420 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2421 mono_error_raise_exception (&error);
2426 ICALL_EXPORT MonoBoolean
2427 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2429 return type->type->type == MONO_TYPE_PTR;
2432 ICALL_EXPORT MonoBoolean
2433 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2435 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)));
2438 ICALL_EXPORT MonoBoolean
2439 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2441 return type->type->byref;
2444 ICALL_EXPORT MonoBoolean
2445 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2448 MonoClass *klass = mono_class_from_mono_type (type->type);
2449 mono_class_init_checked (klass, &error);
2450 mono_error_raise_exception (&error);
2452 return mono_class_is_com_object (klass);
2455 ICALL_EXPORT guint32
2456 ves_icall_RuntimeTypeHandle_GetMetadataToken (MonoReflectionType *obj)
2458 return mono_reflection_get_token ((MonoObject*)obj);
2461 ICALL_EXPORT MonoReflectionModule*
2462 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2465 MonoReflectionModule *result = NULL;
2466 MonoClass *klass = mono_class_from_mono_type (type->type);
2467 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2468 if (!mono_error_ok (&error))
2469 mono_error_set_pending_exception (&error);
2473 ICALL_EXPORT MonoReflectionAssembly*
2474 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2477 MonoDomain *domain = mono_domain_get ();
2478 MonoClass *klass = mono_class_from_mono_type (type->type);
2479 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2481 mono_error_set_pending_exception (&error);
2485 ICALL_EXPORT MonoReflectionType*
2486 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2489 MonoReflectionType *ret;
2490 MonoDomain *domain = mono_domain_get ();
2493 if (type->type->byref)
2495 if (type->type->type == MONO_TYPE_VAR) {
2496 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2497 klass = param ? param->owner.klass : NULL;
2498 } else if (type->type->type == MONO_TYPE_MVAR) {
2499 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2500 klass = param ? param->owner.method->klass : NULL;
2502 klass = mono_class_from_mono_type (type->type)->nested_in;
2508 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2509 mono_error_raise_exception (&error);
2514 ICALL_EXPORT MonoString*
2515 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2517 MonoDomain *domain = mono_domain_get ();
2518 MonoClass *klass = mono_class_from_mono_type (type->type);
2520 if (type->type->byref) {
2521 char *n = g_strdup_printf ("%s&", klass->name);
2522 MonoString *res = mono_string_new (domain, n);
2528 return mono_string_new (domain, klass->name);
2532 ICALL_EXPORT MonoString*
2533 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2535 MonoDomain *domain = mono_domain_get ();
2536 MonoClass *klass = mono_class_from_mono_type (type->type);
2538 while (klass->nested_in)
2539 klass = klass->nested_in;
2541 if (klass->name_space [0] == '\0')
2544 return mono_string_new (domain, klass->name_space);
2548 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2552 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2553 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2557 klass = mono_class_from_mono_type (type->type);
2563 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2566 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2570 ICALL_EXPORT MonoArray*
2571 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2574 MonoReflectionType *rt;
2576 MonoClass *klass, *pklass;
2577 MonoDomain *domain = mono_object_domain (type);
2580 klass = mono_class_from_mono_type (type->type);
2582 if (klass->generic_container) {
2583 MonoGenericContainer *container = klass->generic_container;
2584 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2585 for (i = 0; i < container->type_argc; ++i) {
2586 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2588 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2589 mono_error_raise_exception (&error);
2591 mono_array_setref (res, i, rt);
2593 } else if (klass->generic_class) {
2594 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2595 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2596 for (i = 0; i < inst->type_argc; ++i) {
2597 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2598 mono_error_raise_exception (&error);
2600 mono_array_setref (res, i, rt);
2608 ICALL_EXPORT gboolean
2609 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2613 if (!IS_MONOTYPE (type))
2616 if (type->type->byref)
2619 klass = mono_class_from_mono_type (type->type);
2620 return klass->generic_container != NULL;
2623 ICALL_EXPORT MonoReflectionType*
2624 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2627 MonoReflectionType *ret;
2630 if (type->type->byref)
2633 klass = mono_class_from_mono_type (type->type);
2635 if (klass->generic_container) {
2636 return type; /* check this one */
2638 if (klass->generic_class) {
2639 MonoClass *generic_class = klass->generic_class->container_class;
2642 tb = mono_class_get_ref_info (generic_class);
2644 if (generic_class->wastypebuilder && tb)
2645 return (MonoReflectionType *)tb;
2647 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2648 mono_error_raise_exception (&error);
2656 ICALL_EXPORT MonoReflectionType*
2657 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2660 MonoReflectionType *ret;
2662 MonoType *geninst, **types;
2665 g_assert (IS_MONOTYPE (type));
2666 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2667 mono_error_raise_exception (&error);
2669 count = mono_array_length (type_array);
2670 types = g_new0 (MonoType *, count);
2672 for (i = 0; i < count; i++) {
2673 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2674 types [i] = t->type;
2677 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2682 klass = mono_class_from_mono_type (geninst);
2684 /*we might inflate to the GTD*/
2685 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2686 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2690 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2691 mono_error_raise_exception (&error);
2696 ICALL_EXPORT gboolean
2697 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2701 if (!IS_MONOTYPE (type))
2704 if (type->type->byref)
2707 klass = mono_class_from_mono_type (type->type);
2708 return klass->generic_class != NULL || klass->generic_container != NULL;
2712 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2714 if (!IS_MONOTYPE (type))
2717 if (is_generic_parameter (type->type))
2718 return mono_type_get_generic_param_num (type->type);
2722 ICALL_EXPORT GenericParameterAttributes
2723 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2725 g_assert (IS_MONOTYPE (type));
2726 g_assert (is_generic_parameter (type->type));
2727 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2730 ICALL_EXPORT MonoArray *
2731 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2734 MonoReflectionType *rt;
2735 MonoGenericParamInfo *param_info;
2741 g_assert (IS_MONOTYPE (type));
2743 domain = mono_object_domain (type);
2744 param_info = mono_generic_param_info (type->type->data.generic_param);
2745 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2748 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2749 for (i = 0; i < count; i++) {
2750 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2751 mono_error_raise_exception (&error);
2753 mono_array_setref (res, i, rt);
2760 ICALL_EXPORT MonoBoolean
2761 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2763 return is_generic_parameter (type->type);
2766 ICALL_EXPORT MonoBoolean
2767 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2769 return is_generic_parameter (tb->type.type);
2773 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2774 MonoReflectionType *t)
2776 enumtype->type = t->type;
2779 ICALL_EXPORT MonoReflectionMethod*
2780 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2781 MonoReflectionMethod* generic)
2788 MonoReflectionMethod *ret = NULL;
2790 domain = ((MonoObject *)type)->vtable->domain;
2792 klass = mono_class_from_mono_type (type->type);
2793 mono_class_init_checked (klass, &error);
2794 mono_error_raise_exception (&error);
2797 while ((method = mono_class_get_methods (klass, &iter))) {
2798 if (method->token == generic->method->token) {
2799 ret = mono_method_get_object_checked (domain, method, klass, &error);
2800 mono_error_raise_exception (&error);
2807 ICALL_EXPORT MonoReflectionMethod *
2808 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2811 MonoType *type = ref_type->type;
2813 MonoReflectionMethod *ret = NULL;
2815 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2816 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2819 if (type->type == MONO_TYPE_VAR)
2822 method = mono_type_get_generic_param_owner (type)->owner.method;
2825 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2826 if (!mono_error_ok (&error))
2827 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2831 ICALL_EXPORT MonoBoolean
2832 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2834 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2838 ICALL_EXPORT MonoBoolean
2839 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2841 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2846 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2848 MonoDomain *domain = mono_domain_get ();
2849 MonoImage *image = method->method->klass->image;
2850 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2851 MonoTableInfo *tables = image->tables;
2852 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2853 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2854 guint32 im_cols [MONO_IMPLMAP_SIZE];
2855 guint32 scope_token;
2856 const char *import = NULL;
2857 const char *scope = NULL;
2859 if (image_is_dynamic (image)) {
2860 MonoReflectionMethodAux *method_aux =
2861 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2863 import = method_aux->dllentry;
2864 scope = method_aux->dll;
2867 if (!import || !scope) {
2868 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2873 if (piinfo->implmap_idx) {
2874 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2876 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2877 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2878 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2879 scope = mono_metadata_string_heap (image, scope_token);
2883 *flags = piinfo->piflags;
2884 *entry_point = mono_string_new (domain, import);
2885 *dll_name = mono_string_new (domain, scope);
2888 ICALL_EXPORT MonoReflectionMethod *
2889 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2891 MonoMethodInflated *imethod;
2893 MonoReflectionMethod *ret = NULL;
2896 if (method->method->is_generic)
2899 if (!method->method->is_inflated)
2902 imethod = (MonoMethodInflated *) method->method;
2904 result = imethod->declaring;
2905 /* Not a generic method. */
2906 if (!result->is_generic)
2909 if (image_is_dynamic (method->method->klass->image)) {
2910 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2911 MonoReflectionMethod *res;
2914 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2915 * the dynamic case as well ?
2917 mono_image_lock ((MonoImage*)image);
2918 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2919 mono_image_unlock ((MonoImage*)image);
2925 if (imethod->context.class_inst) {
2926 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2927 /*Generic methods gets the context of the GTD.*/
2928 if (mono_class_get_context (klass)) {
2929 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2930 if (!mono_error_ok (&error))
2935 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2937 if (!mono_error_ok (&error))
2938 mono_error_set_pending_exception (&error);
2942 ICALL_EXPORT gboolean
2943 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2945 return mono_method_signature (method->method)->generic_param_count != 0;
2948 ICALL_EXPORT gboolean
2949 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2951 return method->method->is_generic;
2954 ICALL_EXPORT MonoArray*
2955 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2958 MonoReflectionType *rt;
2963 domain = mono_object_domain (method);
2965 if (method->method->is_inflated) {
2966 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2969 count = inst->type_argc;
2970 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2972 for (i = 0; i < count; i++) {
2973 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2974 mono_error_raise_exception (&error);
2976 mono_array_setref (res, i, rt);
2983 count = mono_method_signature (method->method)->generic_param_count;
2984 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2986 for (i = 0; i < count; i++) {
2987 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2988 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2989 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
2991 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2992 mono_error_raise_exception (&error);
2994 mono_array_setref (res, i, rt);
3000 ICALL_EXPORT MonoObject *
3001 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3005 * Invoke from reflection is supposed to always be a virtual call (the API
3006 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3007 * greater flexibility.
3009 MonoMethod *m = method->method;
3010 MonoMethodSignature *sig = mono_method_signature (m);
3013 void *obj = this_arg;
3017 if (mono_security_core_clr_enabled ())
3018 mono_security_core_clr_ensure_reflection_access_method (m);
3020 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3021 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3022 mono_error_cleanup (&error); /* FIXME does this make sense? */
3023 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3028 if (!mono_object_isinst (this_arg, m->klass)) {
3029 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3030 char *target_name = mono_type_get_full_name (m->klass);
3031 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3032 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3034 g_free (target_name);
3038 m = mono_object_get_virtual_method (this_arg, m);
3039 /* must pass the pointer to the value for valuetype methods */
3040 if (m->klass->valuetype)
3041 obj = mono_object_unbox (this_arg);
3042 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3043 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3048 if (sig->ret->byref) {
3049 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"));
3053 pcount = params? mono_array_length (params): 0;
3054 if (pcount != sig->param_count) {
3055 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3059 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3060 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."));
3064 image = m->klass->image;
3065 if (image->assembly->ref_only) {
3066 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."));
3070 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3071 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3075 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3079 intptr_t *lower_bounds;
3080 pcount = mono_array_length (params);
3081 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3082 /* Note: the synthetized array .ctors have int32 as argument type */
3083 for (i = 0; i < pcount; ++i)
3084 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3086 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3087 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3088 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3089 if (!mono_error_ok (&error)) {
3090 mono_error_set_pending_exception (&error);
3094 for (i = 0; i < mono_array_length (arr); ++i) {
3095 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3096 if (!mono_error_ok (&error)) {
3097 mono_error_set_pending_exception (&error);
3100 mono_array_setref_fast (arr, i, subarray);
3102 return (MonoObject*)arr;
3105 if (m->klass->rank == pcount) {
3106 /* Only lengths provided. */
3107 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3108 if (!mono_error_ok (&error)) {
3109 mono_error_set_pending_exception (&error);
3113 return (MonoObject*)arr;
3115 g_assert (pcount == (m->klass->rank * 2));
3116 /* The arguments are lower-bound-length pairs */
3117 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3119 for (i = 0; i < pcount / 2; ++i) {
3120 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3121 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3124 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3125 if (!mono_error_ok (&error)) {
3126 mono_error_set_pending_exception (&error);
3130 return (MonoObject*)arr;
3133 return mono_runtime_invoke_array (m, obj, params, NULL);
3136 #ifndef DISABLE_REMOTING
3137 ICALL_EXPORT MonoObject *
3138 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3140 MonoDomain *domain = mono_object_domain (method);
3141 MonoMethod *m = method->method;
3142 MonoMethodSignature *sig = mono_method_signature (m);
3143 MonoArray *out_args;
3145 int i, j, outarg_count = 0;
3147 if (m->klass == mono_defaults.object_class) {
3148 if (!strcmp (m->name, "FieldGetter")) {
3149 MonoClass *k = this_arg->vtable->klass;
3153 /* If this is a proxy, then it must be a CBO */
3154 if (k == mono_defaults.transparent_proxy_class) {
3155 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3156 this_arg = tp->rp->unwrapped_server;
3157 g_assert (this_arg);
3158 k = this_arg->vtable->klass;
3161 name = mono_array_get (params, MonoString *, 1);
3162 str = mono_string_to_utf8 (name);
3165 MonoClassField* field = mono_class_get_field_from_name (k, str);
3167 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3168 if (field_klass->valuetype)
3169 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
3171 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3173 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3174 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3175 mono_array_setref (out_args, 0, result);
3183 g_assert_not_reached ();
3185 } else if (!strcmp (m->name, "FieldSetter")) {
3186 MonoClass *k = this_arg->vtable->klass;
3192 /* If this is a proxy, then it must be a CBO */
3193 if (k == mono_defaults.transparent_proxy_class) {
3194 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3195 this_arg = tp->rp->unwrapped_server;
3196 g_assert (this_arg);
3197 k = this_arg->vtable->klass;
3200 name = mono_array_get (params, MonoString *, 1);
3201 str = mono_string_to_utf8 (name);
3204 MonoClassField* field = mono_class_get_field_from_name (k, str);
3206 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3207 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3209 if (field_klass->valuetype) {
3210 size = mono_type_size (field->type, &align);
3211 g_assert (size == mono_class_value_size (field_klass, NULL));
3212 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3214 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3217 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3218 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3228 g_assert_not_reached ();
3233 for (i = 0; i < mono_array_length (params); i++) {
3234 if (sig->params [i]->byref)
3238 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3240 /* handle constructors only for objects already allocated */
3241 if (!strcmp (method->method->name, ".ctor"))
3242 g_assert (this_arg);
3244 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3245 g_assert (!method->method->klass->valuetype);
3246 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3248 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3249 if (sig->params [i]->byref) {
3251 arg = mono_array_get (params, gpointer, i);
3252 mono_array_setref (out_args, j, arg);
3257 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3264 read_enum_value (const char *mem, int type)
3267 case MONO_TYPE_BOOLEAN:
3269 return *(guint8*)mem;
3271 return *(gint8*)mem;
3272 case MONO_TYPE_CHAR:
3274 return read16 (mem);
3276 return (gint16) read16 (mem);
3278 return read32 (mem);
3280 return (gint32) read32 (mem);
3283 return read64 (mem);
3285 g_assert_not_reached ();
3291 write_enum_value (char *mem, int type, guint64 value)
3295 case MONO_TYPE_I1: {
3296 guint8 *p = (guint8*)mem;
3301 case MONO_TYPE_I2: {
3302 guint16 *p = (guint16 *)mem;
3307 case MONO_TYPE_I4: {
3308 guint32 *p = (guint32 *)mem;
3313 case MONO_TYPE_I8: {
3314 guint64 *p = (guint64 *)mem;
3319 g_assert_not_reached ();
3324 ICALL_EXPORT MonoObject *
3325 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3333 domain = mono_object_domain (enumType);
3334 enumc = mono_class_from_mono_type (enumType->type);
3336 mono_class_init_checked (enumc, &error);
3337 mono_error_raise_exception (&error);
3339 etype = mono_class_enum_basetype (enumc);
3341 res = mono_object_new_checked (domain, enumc, &error);
3342 mono_error_raise_exception (&error);
3343 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3348 ICALL_EXPORT MonoBoolean
3349 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3351 int size = mono_class_value_size (a->vtable->klass, NULL);
3352 guint64 a_val = 0, b_val = 0;
3354 memcpy (&a_val, mono_object_unbox (a), size);
3355 memcpy (&b_val, mono_object_unbox (b), size);
3357 return (a_val & b_val) == b_val;
3360 ICALL_EXPORT MonoObject *
3361 ves_icall_System_Enum_get_value (MonoObject *eobj)
3373 g_assert (eobj->vtable->klass->enumtype);
3375 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3376 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3377 mono_error_raise_exception (&error);
3378 dst = (char *)res + sizeof (MonoObject);
3379 src = (char *)eobj + sizeof (MonoObject);
3380 size = mono_class_value_size (enumc, NULL);
3382 memcpy (dst, src, size);
3387 ICALL_EXPORT MonoReflectionType *
3388 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3391 MonoReflectionType *ret;
3395 klass = mono_class_from_mono_type (type->type);
3396 mono_class_init_checked (klass, &error);
3397 mono_error_raise_exception (&error);
3399 etype = mono_class_enum_basetype (klass);
3401 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3405 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3406 mono_error_raise_exception (&error);
3412 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3414 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3415 gpointer odata = (char *)other + sizeof (MonoObject);
3416 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3417 g_assert (basetype);
3422 if (eobj->vtable->klass != other->vtable->klass)
3425 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3426 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3427 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3430 return me > other ? 1 : -1; \
3433 switch (basetype->type) {
3435 COMPARE_ENUM_VALUES (guint8);
3437 COMPARE_ENUM_VALUES (gint8);
3438 case MONO_TYPE_CHAR:
3440 COMPARE_ENUM_VALUES (guint16);
3442 COMPARE_ENUM_VALUES (gint16);
3444 COMPARE_ENUM_VALUES (guint32);
3446 COMPARE_ENUM_VALUES (gint32);
3448 COMPARE_ENUM_VALUES (guint64);
3450 COMPARE_ENUM_VALUES (gint64);
3454 #undef COMPARE_ENUM_VALUES
3455 /* indicates that the enum was of an unsupported unerlying type */
3460 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3462 gpointer data = (char *)eobj + sizeof (MonoObject);
3463 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3464 g_assert (basetype);
3466 switch (basetype->type) {
3467 case MONO_TYPE_I1: {
3468 gint8 value = *((gint8*)data);
3469 return ((int)value ^ (int)value << 8);
3472 return *((guint8*)data);
3473 case MONO_TYPE_CHAR:
3475 return *((guint16*)data);
3477 case MONO_TYPE_I2: {
3478 gint16 value = *((gint16*)data);
3479 return ((int)(guint16)value | (((int)value) << 16));
3482 return *((guint32*)data);
3484 return *((gint32*)data);
3486 case MONO_TYPE_I8: {
3487 gint64 value = *((gint64*)data);
3488 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3491 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3496 ICALL_EXPORT MonoBoolean
3497 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3500 MonoDomain *domain = mono_object_domain (type);
3501 MonoClass *enumc = mono_class_from_mono_type (type->type);
3502 guint j = 0, nvalues;
3504 MonoClassField *field;
3506 guint64 field_value, previous_value = 0;
3507 gboolean sorted = TRUE;
3509 mono_class_init_checked (enumc, &error);
3510 mono_error_raise_exception (&error);
3512 if (!enumc->enumtype) {
3513 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3517 base_type = mono_class_enum_basetype (enumc)->type;
3519 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3520 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3521 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3524 while ((field = mono_class_get_fields (enumc, &iter))) {
3526 MonoTypeEnum def_type;
3528 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3530 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3532 if (mono_field_is_deleted (field))
3534 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3536 p = mono_class_get_field_default_value (field, &def_type);
3537 /* len = */ mono_metadata_decode_blob_size (p, &p);
3539 field_value = read_enum_value (p, base_type);
3540 mono_array_set (*values, guint64, j, field_value);
3542 if (previous_value > field_value)
3545 previous_value = field_value;
3553 BFLAGS_IgnoreCase = 1,
3554 BFLAGS_DeclaredOnly = 2,
3555 BFLAGS_Instance = 4,
3557 BFLAGS_Public = 0x10,
3558 BFLAGS_NonPublic = 0x20,
3559 BFLAGS_FlattenHierarchy = 0x40,
3560 BFLAGS_InvokeMethod = 0x100,
3561 BFLAGS_CreateInstance = 0x200,
3562 BFLAGS_GetField = 0x400,
3563 BFLAGS_SetField = 0x800,
3564 BFLAGS_GetProperty = 0x1000,
3565 BFLAGS_SetProperty = 0x2000,
3566 BFLAGS_ExactBinding = 0x10000,
3567 BFLAGS_SuppressChangeType = 0x20000,
3568 BFLAGS_OptionalParamBinding = 0x40000
3571 ICALL_EXPORT MonoArray*
3572 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3576 MonoClass *startklass, *klass, *refklass;
3581 char *utf8_name = NULL;
3582 int (*compare_func) (const char *s1, const char *s2) = NULL;
3583 MonoClassField *field;
3584 MonoPtrArray tmp_array;
3586 domain = ((MonoObject *)type)->vtable->domain;
3587 if (type->type->byref)
3588 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3590 klass = startklass = mono_class_from_mono_type (type->type);
3591 refklass = mono_class_from_mono_type (reftype->type);
3593 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3596 if (mono_class_has_failure (klass)) {
3597 mono_ptr_array_destroy (tmp_array);
3598 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3603 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3604 guint32 flags = mono_field_get_flags (field);
3606 if (mono_field_is_deleted_with_flags (field, flags))
3608 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3609 if (bflags & BFLAGS_Public)
3611 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3612 if (bflags & BFLAGS_NonPublic) {
3619 if (flags & FIELD_ATTRIBUTE_STATIC) {
3620 if (bflags & BFLAGS_Static)
3621 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3624 if (bflags & BFLAGS_Instance)
3632 if (utf8_name == NULL) {
3633 utf8_name = mono_string_to_utf8 (name);
3634 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3637 if (compare_func (mono_field_get_name (field), utf8_name))
3641 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3642 if (!mono_error_ok (&error))
3644 mono_ptr_array_append (tmp_array, member);
3646 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3649 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3651 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3652 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3654 mono_ptr_array_destroy (tmp_array);
3656 if (utf8_name != NULL)
3661 mono_ptr_array_destroy (tmp_array);
3662 mono_error_raise_exception (&error);
3663 g_assert_not_reached ();
3667 method_nonpublic (MonoMethod* method, gboolean start_klass)
3669 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3670 case METHOD_ATTRIBUTE_ASSEM:
3671 return (start_klass || mono_defaults.generic_ilist_class);
3672 case METHOD_ATTRIBUTE_PRIVATE:
3674 case METHOD_ATTRIBUTE_PUBLIC:
3682 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3685 MonoClass *startklass;
3689 /*FIXME, use MonoBitSet*/
3690 guint32 method_slots_default [8];
3691 guint32 *method_slots = NULL;
3692 int (*compare_func) (const char *s1, const char *s2) = NULL;
3694 array = g_ptr_array_new ();
3699 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3701 /* An optimization for calls made from Delegate:CreateDelegate () */
3702 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3703 method = mono_get_delegate_invoke (klass);
3704 if (mono_loader_get_last_error ())
3707 g_ptr_array_add (array, method);
3711 mono_class_setup_methods (klass);
3712 mono_class_setup_vtable (klass);
3713 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3716 if (is_generic_parameter (&klass->byval_arg))
3717 nslots = mono_class_get_vtable_size (klass->parent);
3719 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3720 if (nslots >= sizeof (method_slots_default) * 8) {
3721 method_slots = g_new0 (guint32, nslots / 32 + 1);
3723 method_slots = method_slots_default;
3724 memset (method_slots, 0, sizeof (method_slots_default));
3727 mono_class_setup_methods (klass);
3728 mono_class_setup_vtable (klass);
3729 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3733 while ((method = mono_class_get_methods (klass, &iter))) {
3735 if (method->slot != -1) {
3736 g_assert (method->slot < nslots);
3737 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3739 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3740 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3743 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3745 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3746 if (bflags & BFLAGS_Public)
3748 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3754 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3755 if (bflags & BFLAGS_Static)
3756 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3759 if (bflags & BFLAGS_Instance)
3767 if (compare_func (name, method->name))
3772 g_ptr_array_add (array, method);
3774 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3776 if (method_slots != method_slots_default)
3777 g_free (method_slots);
3782 if (method_slots != method_slots_default)
3783 g_free (method_slots);
3784 g_ptr_array_free (array, TRUE);
3786 if (mono_class_has_failure (klass)) {
3787 *ex = mono_class_get_exception_for_failure (klass);
3789 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3790 mono_loader_clear_error ();
3795 ICALL_EXPORT MonoArray*
3796 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3798 static MonoClass *MethodInfo_array;
3802 MonoVTable *array_vtable;
3803 MonoException *ex = NULL;
3804 const char *mname = NULL;
3805 GPtrArray *method_array;
3806 MonoClass *klass, *refklass;
3809 mono_error_init (&error);
3811 if (!MethodInfo_array) {
3812 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3813 mono_memory_barrier ();
3814 MethodInfo_array = klass;
3817 klass = mono_class_from_mono_type (type->type);
3818 refklass = mono_class_from_mono_type (reftype->type);
3819 domain = ((MonoObject *)type)->vtable->domain;
3820 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3821 if (!is_ok (&error)) {
3822 mono_error_set_pending_exception (&error);
3825 if (type->type->byref) {
3826 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3827 mono_error_set_pending_exception (&error);
3833 mname = mono_string_to_utf8 (name);
3835 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3836 g_free ((char*)mname);
3838 mono_set_pending_exception (ex);
3842 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3843 if (!mono_error_ok (&error)) {
3844 mono_error_set_pending_exception (&error);
3848 for (i = 0; i < method_array->len; ++i) {
3849 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3850 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3851 if (!mono_error_ok (&error))
3853 mono_array_setref (res, i, rm);
3857 g_ptr_array_free (method_array, TRUE);
3858 if (!mono_error_ok (&error))
3859 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3863 ICALL_EXPORT MonoArray*
3864 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3867 MonoClass *startklass, *klass, *refklass;
3872 gpointer iter = NULL;
3873 MonoPtrArray tmp_array;
3876 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3878 domain = ((MonoObject *)type)->vtable->domain;
3879 if (type->type->byref)
3880 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3881 klass = startklass = mono_class_from_mono_type (type->type);
3882 refklass = mono_class_from_mono_type (reftype->type);
3884 mono_class_setup_methods (klass);
3885 if (mono_class_has_failure (klass)) {
3886 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3891 while ((method = mono_class_get_methods (klass, &iter))) {
3893 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3895 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3896 if (bflags & BFLAGS_Public)
3899 if (bflags & BFLAGS_NonPublic)
3905 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3906 if (bflags & BFLAGS_Static)
3907 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3910 if (bflags & BFLAGS_Instance)
3916 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3917 if (!mono_error_ok (&error)) {
3918 mono_error_set_pending_exception (&error);
3922 mono_ptr_array_append (tmp_array, member);
3925 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
3927 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3928 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3930 mono_ptr_array_destroy (tmp_array);
3936 property_hash (gconstpointer data)
3938 MonoProperty *prop = (MonoProperty*)data;
3940 return g_str_hash (prop->name);
3944 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3946 if (method1->is_inflated)
3947 method1 = ((MonoMethodInflated*) method1)->declaring;
3948 if (method2->is_inflated)
3949 method2 = ((MonoMethodInflated*) method2)->declaring;
3951 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3955 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3957 // Properties are hide-by-name-and-signature
3958 if (!g_str_equal (prop1->name, prop2->name))
3961 /* If we see a property in a generic method, we want to
3962 compare the generic signatures, not the inflated signatures
3963 because we might conflate two properties that were
3967 public T this[T t] { getter { return t; } } // method 1
3968 public U this[U u] { getter { return u; } } // method 2
3971 If we see int Foo<int,int>::Item[int] we need to know if
3972 the indexer came from method 1 or from method 2, and we
3973 shouldn't conflate them. (Bugzilla 36283)
3975 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
3978 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
3985 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3990 return method_nonpublic (accessor, start_klass);
3993 ICALL_EXPORT MonoArray*
3994 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3998 MonoClass *startklass, *klass;
4004 gchar *propname = NULL;
4005 int (*compare_func) (const char *s1, const char *s2) = NULL;
4007 GHashTable *properties = NULL;
4008 MonoPtrArray tmp_array;
4010 mono_error_init (&error);
4012 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4014 domain = ((MonoObject *)type)->vtable->domain;
4015 if (type->type->byref)
4016 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
4017 klass = startklass = mono_class_from_mono_type (type->type);
4020 propname = mono_string_to_utf8 (name);
4021 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4024 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4026 mono_class_setup_methods (klass);
4027 mono_class_setup_vtable (klass);
4028 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4032 while ((prop = mono_class_get_properties (klass, &iter))) {
4038 flags = method->flags;
4041 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4042 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4043 if (bflags & BFLAGS_Public)
4045 } else if (bflags & BFLAGS_NonPublic) {
4046 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4047 property_accessor_nonpublic(prop->set, startklass == klass)) {
4054 if (flags & METHOD_ATTRIBUTE_STATIC) {
4055 if (bflags & BFLAGS_Static)
4056 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4059 if (bflags & BFLAGS_Instance)
4068 if (compare_func (propname, prop->name))
4072 if (g_hash_table_lookup (properties, prop))
4075 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4078 mono_ptr_array_append (tmp_array, pr);
4080 g_hash_table_insert (properties, prop, prop);
4082 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4085 g_hash_table_destroy (properties);
4088 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4089 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4090 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4092 mono_ptr_array_destroy (tmp_array);
4099 if (mono_class_has_failure (klass)) {
4100 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4102 mono_error_set_from_loader_error (&error);
4103 mono_loader_clear_error ();
4108 g_hash_table_destroy (properties);
4111 mono_ptr_array_destroy (tmp_array);
4113 mono_error_set_pending_exception (&error);
4119 event_hash (gconstpointer data)
4121 MonoEvent *event = (MonoEvent*)data;
4123 return g_str_hash (event->name);
4127 event_equal (MonoEvent *event1, MonoEvent *event2)
4129 // Events are hide-by-name
4130 return g_str_equal (event1->name, event2->name);
4133 ICALL_EXPORT MonoArray*
4134 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4138 MonoClass *startklass, *klass;
4144 char *utf8_name = NULL;
4145 int (*compare_func) (const char *s1, const char *s2) = NULL;
4146 GHashTable *events = NULL;
4147 MonoPtrArray tmp_array;
4149 mono_error_init (&error);
4151 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4153 domain = mono_object_domain (type);
4154 if (type->type->byref)
4155 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4156 klass = startklass = mono_class_from_mono_type (type->type);
4158 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4160 mono_class_setup_methods (klass);
4161 mono_class_setup_vtable (klass);
4162 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4166 while ((event = mono_class_get_events (klass, &iter))) {
4168 method = event->add;
4170 method = event->remove;
4172 method = event->raise;
4174 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4175 if (bflags & BFLAGS_Public)
4177 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4178 if (bflags & BFLAGS_NonPublic)
4183 if (bflags & BFLAGS_NonPublic)
4189 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4190 if (bflags & BFLAGS_Static)
4191 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4194 if (bflags & BFLAGS_Instance)
4199 if (bflags & BFLAGS_Instance)
4205 if (utf8_name == NULL) {
4206 utf8_name = mono_string_to_utf8 (name);
4207 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4210 if (compare_func (event->name, utf8_name))
4214 if (g_hash_table_lookup (events, event))
4217 MonoReflectionEvent *ev_obj;
4218 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4221 mono_ptr_array_append (tmp_array, ev_obj);
4223 g_hash_table_insert (events, event, event);
4225 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4228 g_hash_table_destroy (events);
4230 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4232 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4233 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4235 mono_ptr_array_destroy (tmp_array);
4237 if (utf8_name != NULL)
4243 if (mono_class_has_failure (klass)) {
4244 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4246 mono_error_set_from_loader_error (&error);
4247 mono_loader_clear_error ();
4253 g_hash_table_destroy (events);
4254 if (utf8_name != NULL)
4257 mono_ptr_array_destroy (tmp_array);
4259 mono_error_set_pending_exception (&error);
4263 ICALL_EXPORT MonoArray*
4264 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4267 MonoReflectionType *rt;
4275 MonoPtrArray tmp_array;
4277 domain = ((MonoObject *)type)->vtable->domain;
4278 if (type->type->byref)
4279 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4280 klass = mono_class_from_mono_type (type->type);
4283 * If a nested type is generic, return its generic type definition.
4284 * Note that this means that the return value is essentially the set
4285 * of nested types of the generic type definition of @klass.
4287 * A note in MSDN claims that a generic type definition can have
4288 * nested types that aren't generic. In any case, the container of that
4289 * nested type would be the generic type definition.
4291 if (klass->generic_class)
4292 klass = klass->generic_class->container_class;
4294 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4296 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4298 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4299 if (bflags & BFLAGS_Public)
4302 if (bflags & BFLAGS_NonPublic)
4310 str = mono_string_to_utf8 (name);
4311 mono_identifier_unescape_type_name_chars (str);
4314 if (strcmp (nested->name, str))
4318 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4319 mono_error_raise_exception (&error);
4321 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4324 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4326 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4327 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4329 mono_ptr_array_destroy (tmp_array);
4337 ICALL_EXPORT MonoReflectionType*
4338 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4341 MonoReflectionType *ret;
4343 MonoType *type = NULL;
4344 MonoTypeNameParse info;
4345 gboolean type_resolve;
4347 /* On MS.NET, this does not fire a TypeResolve event */
4348 type_resolve = TRUE;
4349 str = mono_string_to_utf8 (name);
4350 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4351 if (!mono_reflection_parse_type (str, &info)) {
4353 mono_reflection_free_type_info (&info);
4355 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4358 /*g_print ("failed parse\n");*/
4362 if (info.assembly.name) {
4364 mono_reflection_free_type_info (&info);
4366 /* 1.0 and 2.0 throw different exceptions */
4367 if (mono_defaults.generic_ilist_class)
4368 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4370 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4376 if (module != NULL) {
4378 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4383 if (assembly_is_dynamic (assembly->assembly)) {
4384 /* Enumerate all modules */
4385 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4389 if (abuilder->modules) {
4390 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4391 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4392 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4398 if (!type && abuilder->loaded_modules) {
4399 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4400 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4401 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4408 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4410 mono_reflection_free_type_info (&info);
4412 MonoException *e = NULL;
4415 e = mono_get_exception_type_load (name, NULL);
4417 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4418 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4420 mono_loader_clear_error ();
4423 mono_set_pending_exception (e);
4425 } else if (mono_loader_get_last_error ()) {
4427 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4430 mono_loader_clear_error ();
4433 if (type->type == MONO_TYPE_CLASS) {
4434 MonoClass *klass = mono_type_get_class (type);
4436 /* need to report exceptions ? */
4437 if (throwOnError && mono_class_has_failure (klass)) {
4438 /* report SecurityException (or others) that occured when loading the assembly */
4439 MonoException *exc = mono_class_get_exception_for_failure (klass);
4440 mono_loader_clear_error ();
4441 mono_set_pending_exception (exc);
4446 /* g_print ("got it\n"); */
4447 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4448 mono_error_raise_exception (&error);
4454 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4457 gchar *shadow_ini_file;
4460 /* Check for shadow-copied assembly */
4461 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4462 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4464 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4465 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4471 g_free (shadow_ini_file);
4472 if (content != NULL) {
4475 *filename = content;
4482 ICALL_EXPORT MonoString *
4483 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4485 MonoDomain *domain = mono_object_domain (assembly);
4486 MonoAssembly *mass = assembly->assembly;
4487 MonoString *res = NULL;
4492 if (g_path_is_absolute (mass->image->name)) {
4493 absolute = g_strdup (mass->image->name);
4494 dirname = g_path_get_dirname (absolute);
4496 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4497 dirname = g_strdup (mass->basedir);
4500 replace_shadow_path (domain, dirname, &absolute);
4505 for (i = strlen (absolute) - 1; i >= 0; i--)
4506 if (absolute [i] == '\\')
4511 uri = g_filename_to_uri (absolute, NULL, NULL);
4513 const char *prepend = "file://";
4515 if (*absolute == '/' && *(absolute + 1) == '/') {
4518 prepend = "file:///";
4521 uri = g_strconcat (prepend, absolute, NULL);
4525 res = mono_string_new (domain, uri);
4532 ICALL_EXPORT MonoBoolean
4533 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4535 MonoAssembly *mass = assembly->assembly;
4537 return mass->in_gac;
4540 ICALL_EXPORT MonoReflectionAssembly*
4541 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4546 MonoImageOpenStatus status;
4547 MonoReflectionAssembly* result = NULL;
4549 name = mono_string_to_utf8 (mname);
4550 res = mono_assembly_load_with_partial_name (name, &status);
4556 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4558 mono_error_set_pending_exception (&error);
4562 ICALL_EXPORT MonoString *
4563 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4565 MonoDomain *domain = mono_object_domain (assembly);
4568 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4573 ICALL_EXPORT MonoBoolean
4574 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4576 return assembly->assembly->ref_only;
4579 ICALL_EXPORT MonoString *
4580 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4582 MonoDomain *domain = mono_object_domain (assembly);
4584 return mono_string_new (domain, assembly->assembly->image->version);
4587 ICALL_EXPORT MonoReflectionMethod*
4588 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4591 MonoReflectionMethod *res = NULL;
4594 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4598 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4599 if (!mono_error_ok (&error))
4602 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4605 if (!mono_error_ok (&error))
4606 mono_error_set_pending_exception (&error);
4610 ICALL_EXPORT MonoReflectionModule*
4611 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4614 MonoReflectionModule *result = NULL;
4615 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4616 if (!mono_error_ok (&error))
4617 mono_error_set_pending_exception (&error);
4621 ICALL_EXPORT MonoArray*
4622 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4624 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4625 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4629 for (i = 0; i < table->rows; ++i) {
4630 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4631 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4637 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4639 static MonoMethod *create_version = NULL;
4643 mono_error_init (error);
4646 if (!create_version) {
4647 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4648 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4649 g_assert (create_version);
4650 mono_method_desc_free (desc);
4656 args [3] = &revision;
4657 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4658 return_val_if_nok (error, NULL);
4660 mono_runtime_invoke_checked (create_version, result, args, error);
4661 return_val_if_nok (error, NULL);
4666 ICALL_EXPORT MonoArray*
4667 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4671 MonoDomain *domain = mono_object_domain (assembly);
4673 static MonoMethod *create_culture = NULL;
4674 MonoImage *image = assembly->assembly->image;
4678 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4681 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4683 if (count > 0 && !create_culture) {
4684 MonoMethodDesc *desc = mono_method_desc_new (
4685 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4686 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4687 g_assert (create_culture);
4688 mono_method_desc_free (desc);
4691 for (i = 0; i < count; i++) {
4692 MonoObject *version;
4693 MonoReflectionAssemblyName *aname;
4694 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4696 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4698 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4699 domain, mono_class_get_assembly_name_class (), &error);
4700 mono_error_raise_exception (&error);
4702 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4704 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4705 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4706 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4707 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4708 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4709 aname->versioncompat = 1; /* SameMachine (default) */
4710 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4712 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4713 mono_error_raise_exception (&error);
4715 MONO_OBJECT_SETREF (aname, version, version);
4717 if (create_culture) {
4719 MonoBoolean assembly_ref = 1;
4720 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4721 args [1] = &assembly_ref;
4723 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4724 mono_error_raise_exception (&error);
4726 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4729 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4730 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4731 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4733 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4734 /* public key token isn't copied - the class library will
4735 automatically generate it from the public key if required */
4736 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4737 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4739 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4740 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4743 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4746 /* note: this function doesn't return the codebase on purpose (i.e. it can
4747 be used under partial trust as path information isn't present). */
4749 mono_array_setref (result, i, aname);
4754 /* move this in some file in mono/util/ */
4756 g_concat_dir_and_file (const char *dir, const char *file)
4758 g_return_val_if_fail (dir != NULL, NULL);
4759 g_return_val_if_fail (file != NULL, NULL);
4762 * If the directory name doesn't have a / on the end, we need
4763 * to add one so we get a proper path to the file
4765 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4766 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4768 return g_strconcat (dir, file, NULL);
4772 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4775 char *n = mono_string_to_utf8 (name);
4776 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4778 guint32 cols [MONO_MANIFEST_SIZE];
4779 guint32 impl, file_idx;
4783 for (i = 0; i < table->rows; ++i) {
4784 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4785 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4786 if (strcmp (val, n) == 0)
4790 if (i == table->rows)
4793 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4796 * this code should only be called after obtaining the
4797 * ResourceInfo and handling the other cases.
4799 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4800 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4802 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4807 module = assembly->assembly->image;
4810 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4811 mono_error_raise_exception (&error);
4812 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4814 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4817 ICALL_EXPORT gboolean
4818 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4821 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4823 guint32 cols [MONO_MANIFEST_SIZE];
4824 guint32 file_cols [MONO_FILE_SIZE];
4828 n = mono_string_to_utf8 (name);
4829 for (i = 0; i < table->rows; ++i) {
4830 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4831 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4832 if (strcmp (val, n) == 0)
4836 if (i == table->rows)
4839 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4840 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4843 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4844 case MONO_IMPLEMENTATION_FILE:
4845 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4846 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4847 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4848 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4849 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4850 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4853 info->location = RESOURCE_LOCATION_EMBEDDED;
4856 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4857 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4858 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4859 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4860 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4861 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4863 mono_set_pending_exception (ex);
4866 MonoReflectionAssembly *assm_obj;
4867 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4869 mono_error_set_pending_exception (&error);
4872 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4874 /* Obtain info recursively */
4875 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4876 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4879 case MONO_IMPLEMENTATION_EXP_TYPE:
4880 g_assert_not_reached ();
4888 ICALL_EXPORT MonoObject*
4889 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4891 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4892 MonoArray *result = NULL;
4897 /* check hash if needed */
4899 n = mono_string_to_utf8 (name);
4900 for (i = 0; i < table->rows; ++i) {
4901 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4902 if (strcmp (val, n) == 0) {
4905 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4906 fn = mono_string_new (mono_object_domain (assembly), n);
4908 return (MonoObject*)fn;
4916 for (i = 0; i < table->rows; ++i) {
4917 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4921 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4924 for (i = 0; i < table->rows; ++i) {
4925 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4926 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4927 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4928 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4933 return (MonoObject*)result;
4936 ICALL_EXPORT MonoArray*
4937 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4940 MonoDomain *domain = mono_domain_get();
4943 int i, j, file_count = 0;
4944 MonoImage **modules;
4945 guint32 module_count, real_module_count;
4946 MonoTableInfo *table;
4947 guint32 cols [MONO_FILE_SIZE];
4948 MonoImage *image = assembly->assembly->image;
4950 g_assert (image != NULL);
4951 g_assert (!assembly_is_dynamic (assembly->assembly));
4953 table = &image->tables [MONO_TABLE_FILE];
4954 file_count = table->rows;
4956 modules = image->modules;
4957 module_count = image->module_count;
4959 real_module_count = 0;
4960 for (i = 0; i < module_count; ++i)
4962 real_module_count ++;
4964 klass = mono_class_get_module_class ();
4965 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4967 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
4968 mono_error_raise_exception (&error);
4969 mono_array_setref (res, 0, image_obj);
4971 for (i = 0; i < module_count; ++i)
4973 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
4974 mono_error_raise_exception (&error);
4975 mono_array_setref (res, j, rm);
4979 for (i = 0; i < file_count; ++i, ++j) {
4980 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4981 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
4982 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
4983 mono_error_raise_exception (&error);
4984 mono_array_setref (res, j, rm);
4987 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4989 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4990 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
4993 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
4994 mono_error_raise_exception (&error);
4995 mono_array_setref (res, j, rm);
5002 ICALL_EXPORT MonoReflectionMethod*
5003 ves_icall_GetCurrentMethod (void)
5005 MonoReflectionMethod *res = NULL;
5008 MonoMethod *m = mono_method_get_last_managed ();
5011 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5015 while (m->is_inflated)
5016 m = ((MonoMethodInflated*)m)->declaring;
5018 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5019 mono_error_raise_exception (&error);
5025 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5028 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5031 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5032 //method is inflated, we should inflate it on the other class
5033 MonoGenericContext ctx;
5034 ctx.method_inst = inflated->context.method_inst;
5035 ctx.class_inst = inflated->context.class_inst;
5036 if (klass->generic_class)
5037 ctx.class_inst = klass->generic_class->context.class_inst;
5038 else if (klass->generic_container)
5039 ctx.class_inst = klass->generic_container->context.class_inst;
5040 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5041 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5045 mono_class_setup_methods (method->klass);
5046 if (mono_class_has_failure (method->klass))
5048 for (i = 0; i < method->klass->method.count; ++i) {
5049 if (method->klass->methods [i] == method) {
5054 mono_class_setup_methods (klass);
5055 if (mono_class_has_failure (klass))
5057 g_assert (offset >= 0 && offset < klass->method.count);
5058 return klass->methods [offset];
5061 ICALL_EXPORT MonoReflectionMethod*
5062 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5064 MonoReflectionMethod *res = NULL;
5068 klass = mono_class_from_mono_type (type);
5069 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5071 if (method->klass != klass) {
5072 method = mono_method_get_equivalent_method (method, klass);
5077 klass = method->klass;
5078 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5079 mono_error_raise_exception (&error);
5083 ICALL_EXPORT MonoReflectionMethodBody*
5084 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5086 return mono_method_body_get_object (mono_domain_get (), method);
5089 ICALL_EXPORT MonoReflectionAssembly*
5090 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5093 MonoReflectionAssembly *result;
5094 MonoMethod *dest = NULL;
5096 mono_stack_walk_no_il (get_executing, &dest);
5098 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5100 mono_error_set_pending_exception (&error);
5105 ICALL_EXPORT MonoReflectionAssembly*
5106 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5109 MonoReflectionAssembly *result;
5110 MonoDomain* domain = mono_domain_get ();
5112 if (!domain->entry_assembly)
5115 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5117 mono_error_set_pending_exception (&error);
5121 ICALL_EXPORT MonoReflectionAssembly*
5122 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5127 MonoReflectionAssembly *result;
5130 mono_stack_walk_no_il (get_executing, &dest);
5132 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5136 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5139 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5141 mono_error_set_pending_exception (&error);
5145 ICALL_EXPORT MonoString *
5146 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5147 gboolean assembly_qualified)
5149 MonoDomain *domain = mono_object_domain (object);
5150 MonoTypeNameFormat format;
5155 format = assembly_qualified ?
5156 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5157 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5159 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5161 name = mono_type_get_name_full (object->type, format);
5165 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5170 res = mono_string_new (domain, name);
5177 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5180 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5182 mono_class_init_checked (klass, &error);
5183 mono_error_raise_exception (&error);
5184 return mono_security_core_clr_class_level (klass);
5188 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5190 MonoClassField *field = rfield->field;
5191 return mono_security_core_clr_field_level (field, TRUE);
5195 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5197 MonoMethod *method = rfield->method;
5198 return mono_security_core_clr_method_level (method, TRUE);
5202 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)
5204 static MonoMethod *create_culture = NULL;
5208 const char *pkey_ptr;
5210 MonoBoolean assembly_ref = 0;
5212 mono_error_init (error);
5214 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5215 aname->major = name->major;
5216 aname->minor = name->minor;
5217 aname->build = name->build;
5218 aname->flags = name->flags;
5219 aname->revision = name->revision;
5220 aname->hashalg = name->hash_alg;
5221 aname->versioncompat = 1; /* SameMachine (default) */
5222 aname->processor_architecture = name->arch;
5224 if (by_default_version) {
5225 MonoObject *version;
5227 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5228 return_if_nok (error);
5230 MONO_OBJECT_SETREF (aname, version, version);
5234 if (absolute != NULL && *absolute != '\0') {
5235 const gchar *prepend = "file://";
5238 codebase = g_strdup (absolute);
5243 for (i = strlen (codebase) - 1; i >= 0; i--)
5244 if (codebase [i] == '\\')
5247 if (*codebase == '/' && *(codebase + 1) == '/') {
5250 prepend = "file:///";
5254 result = g_strconcat (prepend, codebase, NULL);
5260 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5264 if (!create_culture) {
5265 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5266 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5267 g_assert (create_culture);
5268 mono_method_desc_free (desc);
5271 if (name->culture) {
5272 args [0] = mono_string_new (domain, name->culture);
5273 args [1] = &assembly_ref;
5275 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5276 return_if_nok (error);
5278 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5281 if (name->public_key) {
5282 pkey_ptr = (char*)name->public_key;
5283 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5285 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5286 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5287 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5288 } else if (default_publickey) {
5289 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5290 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5293 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5294 if (name->public_key_token [0]) {
5298 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5299 p = mono_array_addr (aname->keyToken, char, 0);
5301 for (i = 0, j = 0; i < 8; i++) {
5302 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5303 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5306 } else if (default_token) {
5307 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5311 ICALL_EXPORT MonoString *
5312 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5314 MonoDomain *domain = mono_object_domain (assembly);
5315 MonoAssembly *mass = assembly->assembly;
5319 name = mono_stringify_assembly_name (&mass->aname);
5320 res = mono_string_new (domain, name);
5327 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5331 MonoAssembly *mass = assembly->assembly;
5333 if (g_path_is_absolute (mass->image->name)) {
5334 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5335 mono_error_set_pending_exception (&error);
5338 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5340 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5341 mono_error_set_pending_exception (&error);
5347 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5351 MonoImageOpenStatus status = MONO_IMAGE_OK;
5354 MonoAssemblyName name;
5357 filename = mono_string_to_utf8 (fname);
5359 dirname = g_path_get_dirname (filename);
5360 replace_shadow_path (mono_domain_get (), dirname, &filename);
5363 image = mono_image_open (filename, &status);
5369 if (status == MONO_IMAGE_IMAGE_INVALID)
5370 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5372 exc = mono_get_exception_file_not_found2 (NULL, fname);
5373 mono_set_pending_exception (exc);
5377 res = mono_assembly_fill_assembly_name (image, &name);
5379 mono_image_close (image);
5381 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5385 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5386 mono_error_set_pending_exception (&error);
5388 mono_image_close (image);
5392 ICALL_EXPORT MonoBoolean
5393 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5394 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5396 MonoBoolean result = FALSE;
5397 MonoDeclSecurityEntry entry;
5399 /* SecurityAction.RequestMinimum */
5400 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5401 *minimum = entry.blob;
5402 *minLength = entry.size;
5405 /* SecurityAction.RequestOptional */
5406 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5407 *optional = entry.blob;
5408 *optLength = entry.size;
5411 /* SecurityAction.RequestRefuse */
5412 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5413 *refused = entry.blob;
5414 *refLength = entry.size;
5422 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5424 guint32 attrs, visibility;
5426 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5427 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5428 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5431 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5437 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5439 MonoReflectionType *rt;
5442 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5445 mono_error_init (error);
5447 /* we start the count from 1 because we skip the special type <Module> */
5450 for (i = 1; i < tdef->rows; ++i) {
5451 if (mono_module_type_is_visible (tdef, image, i + 1))
5455 count = tdef->rows - 1;
5457 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5458 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5460 for (i = 1; i < tdef->rows; ++i) {
5461 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5462 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5463 mono_loader_assert_no_error (); /* Plug any leaks */
5464 mono_error_assert_ok (error);
5467 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5468 return_val_if_nok (error, NULL);
5470 mono_array_setref (res, count, rt);
5472 MonoException *ex = mono_error_convert_to_exception (error);
5473 mono_array_setref (*exceptions, count, ex);
5482 ICALL_EXPORT MonoArray*
5483 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5486 MonoArray *res = NULL;
5487 MonoArray *exceptions = NULL;
5488 MonoImage *image = NULL;
5489 MonoTableInfo *table = NULL;
5492 int i, len, ex_count;
5494 domain = mono_object_domain (assembly);
5496 g_assert (!assembly_is_dynamic (assembly->assembly));
5497 image = assembly->assembly->image;
5498 table = &image->tables [MONO_TABLE_FILE];
5499 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5500 mono_error_raise_exception (&error);
5502 /* Append data from all modules in the assembly */
5503 for (i = 0; i < table->rows; ++i) {
5504 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5505 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5510 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5511 mono_error_raise_exception (&error);
5513 /* Append the new types to the end of the array */
5514 if (mono_array_length (res2) > 0) {
5516 MonoArray *res3, *ex3;
5518 len1 = mono_array_length (res);
5519 len2 = mono_array_length (res2);
5521 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5522 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5523 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5526 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5527 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5528 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5535 /* the ReflectionTypeLoadException must have all the types (Types property),
5536 * NULL replacing types which throws an exception. The LoaderException must
5537 * contain all exceptions for NULL items.
5540 len = mono_array_length (res);
5543 for (i = 0; i < len; i++) {
5544 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5548 klass = mono_type_get_class (t->type);
5549 if ((klass != NULL) && mono_class_has_failure (klass)) {
5550 /* keep the class in the list */
5551 list = g_list_append (list, klass);
5552 /* and replace Type with NULL */
5553 mono_array_setref (res, i, NULL);
5560 if (list || ex_count) {
5562 MonoException *exc = NULL;
5563 MonoArray *exl = NULL;
5564 int j, length = g_list_length (list) + ex_count;
5566 mono_loader_clear_error ();
5568 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5569 /* Types for which mono_class_get_checked () succeeded */
5570 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5571 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5572 mono_array_setref (exl, i, exc);
5574 /* Types for which it don't */
5575 for (j = 0; j < mono_array_length (exceptions); ++j) {
5576 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5578 g_assert (i < length);
5579 mono_array_setref (exl, i, exc);
5586 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5587 if (!is_ok (&error)) {
5588 mono_error_set_pending_exception (&error);
5591 mono_loader_clear_error ();
5592 mono_set_pending_exception (exc);
5599 ICALL_EXPORT gboolean
5600 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5603 MonoAssemblyName aname;
5604 MonoDomain *domain = mono_object_domain (name);
5606 gboolean is_version_defined;
5607 gboolean is_token_defined;
5609 aname.public_key = NULL;
5610 val = mono_string_to_utf8 (assname);
5611 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5612 g_free ((guint8*) aname.public_key);
5617 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5618 mono_error_set_pending_exception (&error);
5620 mono_assembly_name_free (&aname);
5621 g_free ((guint8*) aname.public_key);
5627 ICALL_EXPORT MonoReflectionType*
5628 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5631 MonoReflectionType *ret;
5632 MonoDomain *domain = mono_object_domain (module);
5635 g_assert (module->image);
5637 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5638 /* These images do not have a global type */
5641 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5642 if (!mono_error_ok (&error)) {
5643 mono_error_set_pending_exception (&error);
5647 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5648 if (!mono_error_ok (&error)) {
5649 mono_error_set_pending_exception (&error);
5657 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5659 /*if (module->image)
5660 mono_image_close (module->image);*/
5663 ICALL_EXPORT MonoString*
5664 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5666 MonoDomain *domain = mono_object_domain (module);
5668 g_assert (module->image);
5669 return mono_string_new (domain, module->image->guid);
5672 ICALL_EXPORT gpointer
5673 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5676 if (module->image && module->image->is_module_handle)
5677 return module->image->raw_data;
5680 return (gpointer) (-1);
5684 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5686 if (image_is_dynamic (image)) {
5687 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5688 *pe_kind = dyn->pe_kind;
5689 *machine = dyn->machine;
5692 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5693 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5698 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5700 return (image->md_version_major << 16) | (image->md_version_minor);
5703 ICALL_EXPORT MonoArray*
5704 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5707 MonoArray *exceptions;
5711 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5715 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5716 mono_error_raise_exception (&error);
5718 for (i = 0; i < mono_array_length (exceptions); ++i) {
5719 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5721 mono_set_pending_exception (ex);
5730 mono_memberref_is_method (MonoImage *image, guint32 token)
5732 if (!image_is_dynamic (image)) {
5733 guint32 cols [MONO_MEMBERREF_SIZE];
5735 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5736 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5737 mono_metadata_decode_blob_size (sig, &sig);
5738 return (*sig != 0x6);
5740 MonoClass *handle_class;
5742 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5745 return mono_defaults.methodhandle_class == handle_class;
5750 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5753 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5754 mono_array_addr (type_args, MonoType*, 0));
5756 context->class_inst = NULL;
5758 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5759 mono_array_addr (method_args, MonoType*, 0));
5761 context->method_inst = NULL;
5764 ICALL_EXPORT MonoType*
5765 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5768 int table = mono_metadata_token_table (token);
5769 int index = mono_metadata_token_index (token);
5770 MonoGenericContext context;
5773 *resolve_error = ResolveTokenError_Other;
5775 /* Validate token */
5776 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5777 (table != MONO_TABLE_TYPESPEC)) {
5778 *resolve_error = ResolveTokenError_BadTable;
5782 if (image_is_dynamic (image)) {
5783 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5784 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5785 return klass ? &klass->byval_arg : NULL;
5788 init_generic_context_from_args (&context, type_args, method_args);
5789 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5790 return klass ? &klass->byval_arg : NULL;
5793 if ((index <= 0) || (index > image->tables [table].rows)) {
5794 *resolve_error = ResolveTokenError_OutOfRange;
5798 init_generic_context_from_args (&context, type_args, method_args);
5799 klass = mono_class_get_checked (image, token, &error);
5801 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5802 if (!mono_error_ok (&error)) {
5803 mono_error_set_pending_exception (&error);
5808 return &klass->byval_arg;
5813 ICALL_EXPORT MonoMethod*
5814 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5817 int table = mono_metadata_token_table (token);
5818 int index = mono_metadata_token_index (token);
5819 MonoGenericContext context;
5822 *resolve_error = ResolveTokenError_Other;
5824 /* Validate token */
5825 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5826 (table != MONO_TABLE_MEMBERREF)) {
5827 *resolve_error = ResolveTokenError_BadTable;
5831 if (image_is_dynamic (image)) {
5832 if (table == MONO_TABLE_METHOD)
5833 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5835 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5836 *resolve_error = ResolveTokenError_BadTable;
5840 init_generic_context_from_args (&context, type_args, method_args);
5841 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5844 if ((index <= 0) || (index > image->tables [table].rows)) {
5845 *resolve_error = ResolveTokenError_OutOfRange;
5848 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5849 *resolve_error = ResolveTokenError_BadTable;
5853 init_generic_context_from_args (&context, type_args, method_args);
5854 method = mono_get_method_checked (image, token, NULL, &context, &error);
5855 mono_error_set_pending_exception (&error);
5860 ICALL_EXPORT MonoString*
5861 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5863 int index = mono_metadata_token_index (token);
5865 *error = ResolveTokenError_Other;
5867 /* Validate token */
5868 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5869 *error = ResolveTokenError_BadTable;
5873 if (image_is_dynamic (image))
5874 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5876 if ((index <= 0) || (index >= image->heap_us.size)) {
5877 *error = ResolveTokenError_OutOfRange;
5881 /* FIXME: What to do if the index points into the middle of a string ? */
5883 return mono_ldstr (mono_domain_get (), image, index);
5886 ICALL_EXPORT MonoClassField*
5887 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5891 int table = mono_metadata_token_table (token);
5892 int index = mono_metadata_token_index (token);
5893 MonoGenericContext context;
5894 MonoClassField *field;
5896 *resolve_error = ResolveTokenError_Other;
5898 /* Validate token */
5899 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5900 *resolve_error = ResolveTokenError_BadTable;
5904 if (image_is_dynamic (image)) {
5905 if (table == MONO_TABLE_FIELD)
5906 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5908 if (mono_memberref_is_method (image, token)) {
5909 *resolve_error = ResolveTokenError_BadTable;
5913 init_generic_context_from_args (&context, type_args, method_args);
5914 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5917 if ((index <= 0) || (index > image->tables [table].rows)) {
5918 *resolve_error = ResolveTokenError_OutOfRange;
5921 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5922 *resolve_error = ResolveTokenError_BadTable;
5926 init_generic_context_from_args (&context, type_args, method_args);
5927 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5928 mono_error_set_pending_exception (&error);
5934 ICALL_EXPORT MonoObject*
5935 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5939 int table = mono_metadata_token_table (token);
5941 *error = ResolveTokenError_Other;
5944 case MONO_TABLE_TYPEDEF:
5945 case MONO_TABLE_TYPEREF:
5946 case MONO_TABLE_TYPESPEC: {
5947 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5949 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
5950 mono_error_raise_exception (&merror);
5957 case MONO_TABLE_METHOD:
5958 case MONO_TABLE_METHODSPEC: {
5959 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5961 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5962 mono_error_raise_exception (&merror);
5968 case MONO_TABLE_FIELD: {
5969 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5971 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5972 mono_error_raise_exception (&merror);
5978 case MONO_TABLE_MEMBERREF:
5979 if (mono_memberref_is_method (image, token)) {
5980 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5982 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5983 mono_error_raise_exception (&merror);
5990 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5992 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5993 mono_error_raise_exception (&merror);
6002 *error = ResolveTokenError_BadTable;
6008 ICALL_EXPORT MonoArray*
6009 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
6011 int table = mono_metadata_token_table (token);
6012 int idx = mono_metadata_token_index (token);
6013 MonoTableInfo *tables = image->tables;
6018 *error = ResolveTokenError_OutOfRange;
6020 /* FIXME: Support other tables ? */
6021 if (table != MONO_TABLE_STANDALONESIG)
6024 if (image_is_dynamic (image))
6027 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6030 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6032 ptr = mono_metadata_blob_heap (image, sig);
6033 len = mono_metadata_decode_blob_size (ptr, &ptr);
6035 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
6036 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6040 ICALL_EXPORT MonoReflectionType*
6041 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6044 MonoReflectionType *ret;
6046 int isbyref = 0, rank;
6047 char *str = mono_string_to_utf8 (smodifiers);
6050 klass = mono_class_from_mono_type (tb->type.type);
6052 /* logic taken from mono_reflection_parse_type(): keep in sync */
6056 if (isbyref) { /* only one level allowed by the spec */
6065 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6066 mono_error_raise_exception (&error);
6070 klass = mono_ptr_class_get (&klass->byval_arg);
6071 mono_class_init (klass);
6082 else if (*p != '*') { /* '*' means unknown lower bound */
6093 klass = mono_array_class_get (klass, rank);
6094 mono_class_init (klass);
6103 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6104 mono_error_raise_exception (&error);
6109 ICALL_EXPORT MonoBoolean
6110 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6116 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6122 check_for_invalid_type (MonoClass *klass, MonoError *error)
6127 mono_error_init (error);
6129 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6132 name = mono_type_get_full_name (klass);
6133 str = mono_string_new (mono_domain_get (), name);
6135 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6138 ICALL_EXPORT MonoReflectionType *
6139 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6142 MonoReflectionType *ret;
6143 MonoClass *klass, *aklass;
6145 klass = mono_class_from_mono_type (type->type);
6146 check_for_invalid_type (klass, &error);
6147 mono_error_raise_exception (&error);
6149 if (rank == 0) //single dimentional array
6150 aklass = mono_array_class_get (klass, 1);
6152 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6154 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6155 mono_error_raise_exception (&error);
6160 ICALL_EXPORT MonoReflectionType *
6161 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6164 MonoReflectionType *ret;
6167 klass = mono_class_from_mono_type (type->type);
6168 mono_class_init_checked (klass, &error);
6169 mono_error_raise_exception (&error);
6170 check_for_invalid_type (klass, &error);
6171 mono_error_raise_exception (&error);
6173 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6174 mono_error_raise_exception (&error);
6179 ICALL_EXPORT MonoReflectionType *
6180 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6183 MonoReflectionType *ret;
6184 MonoClass *klass, *pklass;
6186 klass = mono_class_from_mono_type (type->type);
6187 mono_class_init_checked (klass, &error);
6188 mono_error_raise_exception (&error);
6189 check_for_invalid_type (klass, &error);
6190 mono_error_raise_exception (&error);
6192 pklass = mono_ptr_class_get (type->type);
6194 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6195 mono_error_raise_exception (&error);
6200 ICALL_EXPORT MonoObject *
6201 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6202 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6205 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6206 MonoObject *delegate;
6208 MonoMethod *method = info->method;
6210 mono_class_init_checked (delegate_class, &error);
6211 mono_error_raise_exception (&error);
6213 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
6215 if (mono_security_core_clr_enabled ()) {
6216 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6220 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6221 mono_error_raise_exception (&error);
6223 if (method_is_dynamic (method)) {
6224 /* Creating a trampoline would leak memory */
6225 func = mono_compile_method (method);
6227 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6228 method = mono_object_get_virtual_method (target, method);
6229 func = mono_create_ftnptr (mono_domain_get (),
6230 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6233 mono_delegate_ctor_with_method (delegate, target, func, method);
6238 ICALL_EXPORT MonoMulticastDelegate *
6239 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6242 MonoMulticastDelegate *ret;
6244 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6246 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6247 mono_error_raise_exception (&error);
6248 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6253 ICALL_EXPORT MonoReflectionMethod*
6254 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6256 MonoReflectionMethod *ret = NULL;
6258 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6259 mono_error_raise_exception (&error);
6265 static inline gint32
6266 mono_array_get_byte_length (MonoArray *array)
6272 klass = array->obj.vtable->klass;
6274 if (array->bounds == NULL)
6275 length = array->max_length;
6278 for (i = 0; i < klass->rank; ++ i)
6279 length *= array->bounds [i].length;
6282 switch (klass->element_class->byval_arg.type) {
6285 case MONO_TYPE_BOOLEAN:
6289 case MONO_TYPE_CHAR:
6297 return length * sizeof (gpointer);
6308 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6310 return mono_array_get_byte_length (array);
6314 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6316 return mono_array_get (array, gint8, idx);
6320 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6322 mono_array_set (array, gint8, idx, value);
6325 ICALL_EXPORT MonoBoolean
6326 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6328 guint8 *src_buf, *dest_buf;
6331 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6335 g_assert (count >= 0);
6337 /* This is called directly from the class libraries without going through the managed wrapper */
6338 MONO_CHECK_ARG_NULL (src, FALSE);
6339 MONO_CHECK_ARG_NULL (dest, FALSE);
6341 /* watch out for integer overflow */
6342 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6345 src_buf = (guint8 *)src->vector + src_offset;
6346 dest_buf = (guint8 *)dest->vector + dest_offset;
6349 memcpy (dest_buf, src_buf, count);
6351 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6356 #ifndef DISABLE_REMOTING
6357 ICALL_EXPORT MonoObject *
6358 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6361 MonoDomain *domain = mono_object_domain (this_obj);
6363 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6364 MonoTransparentProxy *tp;
6368 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6369 mono_error_raise_exception (&error);
6370 tp = (MonoTransparentProxy*) res;
6372 MONO_OBJECT_SETREF (tp, rp, rp);
6373 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6374 klass = mono_class_from_mono_type (type);
6376 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6377 mono_class_setup_vtable (klass);
6378 if (mono_class_has_failure (klass)) {
6379 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6383 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
6384 tp->remote_class = mono_remote_class (domain, class_name, klass);
6386 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6390 ICALL_EXPORT MonoReflectionType *
6391 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6394 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6395 mono_error_raise_exception (&error);
6401 /* System.Environment */
6404 ves_icall_System_Environment_get_UserName (void)
6406 /* using glib is more portable */
6407 return mono_string_new (mono_domain_get (), g_get_user_name ());
6411 ICALL_EXPORT MonoString *
6412 ves_icall_System_Environment_get_MachineName (void)
6414 #if defined (HOST_WIN32)
6419 len = MAX_COMPUTERNAME_LENGTH + 1;
6420 buf = g_new (gunichar2, len);
6423 if (GetComputerName (buf, (PDWORD) &len)) {
6425 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6426 mono_error_raise_exception (&error);
6431 #elif !defined(DISABLE_SOCKETS)
6435 #if defined _SC_HOST_NAME_MAX
6436 n = sysconf (_SC_HOST_NAME_MAX);
6440 buf = g_malloc (n+1);
6442 if (gethostname (buf, n) == 0){
6444 result = mono_string_new (mono_domain_get (), buf);
6451 return mono_string_new (mono_domain_get (), "mono");
6456 ves_icall_System_Environment_get_Platform (void)
6458 #if defined (TARGET_WIN32)
6461 #elif defined(__MACH__)
6464 // Notice that the value is hidden from user code, and only exposed
6465 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6466 // define and making assumptions based on Unix/128/4 values before there
6467 // was a MacOS define. Lots of code would assume that not-Unix meant
6468 // Windows, but in this case, it would be OSX.
6477 ICALL_EXPORT MonoString *
6478 ves_icall_System_Environment_get_NewLine (void)
6480 #if defined (HOST_WIN32)
6481 return mono_string_new (mono_domain_get (), "\r\n");
6483 return mono_string_new (mono_domain_get (), "\n");
6487 ICALL_EXPORT MonoBoolean
6488 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6490 #if SIZEOF_VOID_P == 8
6494 gboolean isWow64Process = FALSE;
6495 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6496 return (MonoBoolean)isWow64Process;
6498 #elif defined(HAVE_SYS_UTSNAME_H)
6499 struct utsname name;
6501 if (uname (&name) >= 0) {
6502 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6509 ICALL_EXPORT MonoString *
6510 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6518 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6519 value = g_getenv (utf8_name);
6526 return mono_string_new (mono_domain_get (), value);
6530 * There is no standard way to get at environ.
6533 #ifndef __MINGW32_VERSION
6534 #if defined(__APPLE__)
6535 #if defined (TARGET_OSX)
6536 /* Apple defines this in crt_externs.h but doesn't provide that header for
6537 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6538 * in fact exist on all implementations (so far)
6540 gchar ***_NSGetEnviron(void);
6541 #define environ (*_NSGetEnviron())
6543 static char *mono_environ[1] = { NULL };
6544 #define environ mono_environ
6545 #endif /* defined (TARGET_OSX) */
6553 ICALL_EXPORT MonoArray *
6554 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6565 env_strings = GetEnvironmentStrings();
6568 env_string = env_strings;
6569 while (*env_string != '\0') {
6570 /* weird case that MS seems to skip */
6571 if (*env_string != '=')
6573 while (*env_string != '\0')
6579 domain = mono_domain_get ();
6580 names = mono_array_new (domain, mono_defaults.string_class, n);
6584 env_string = env_strings;
6585 while (*env_string != '\0') {
6586 /* weird case that MS seems to skip */
6587 if (*env_string != '=') {
6588 equal_str = wcschr(env_string, '=');
6589 g_assert(equal_str);
6591 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6592 mono_error_raise_exception (&error);
6593 mono_array_setref (names, n, str);
6596 while (*env_string != '\0')
6601 FreeEnvironmentStrings (env_strings);
6614 for (e = environ; *e != 0; ++ e)
6617 domain = mono_domain_get ();
6618 names = mono_array_new (domain, mono_defaults.string_class, n);
6621 for (e = environ; *e != 0; ++ e) {
6622 parts = g_strsplit (*e, "=", 2);
6624 str = mono_string_new (domain, *parts);
6625 mono_array_setref (names, n, str);
6638 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6640 #if !GLIB_CHECK_VERSION(2,4,0)
6641 #define g_setenv(a,b,c) setenv(a,b,c)
6642 #define g_unsetenv(a) unsetenv(a)
6646 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6649 gunichar2 *utf16_name, *utf16_value;
6651 gchar *utf8_name, *utf8_value;
6656 utf16_name = mono_string_to_utf16 (name);
6657 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6658 SetEnvironmentVariable (utf16_name, NULL);
6659 g_free (utf16_name);
6663 utf16_value = mono_string_to_utf16 (value);
6665 SetEnvironmentVariable (utf16_name, utf16_value);
6667 g_free (utf16_name);
6668 g_free (utf16_value);
6670 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6672 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6673 g_unsetenv (utf8_name);
6678 utf8_value = mono_string_to_utf8_checked (value, &error);
6679 if (!mono_error_ok (&error)) {
6681 mono_error_set_pending_exception (&error);
6684 g_setenv (utf8_name, utf8_value, TRUE);
6687 g_free (utf8_value);
6692 ves_icall_System_Environment_Exit (int result)
6694 mono_environment_exitcode_set (result);
6696 /* FIXME: There are some cleanup hangs that should be worked out, but
6697 * if the program is going to exit, everything will be cleaned up when
6698 * NaCl exits anyway.
6700 #ifndef __native_client__
6701 if (!mono_runtime_try_shutdown ())
6702 mono_thread_exit ();
6704 /* Suspend all managed threads since the runtime is going away */
6705 mono_thread_suspend_all_other_threads ();
6707 mono_runtime_quit ();
6710 /* we may need to do some cleanup here... */
6714 ICALL_EXPORT MonoString*
6715 ves_icall_System_Environment_GetGacPath (void)
6717 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6720 ICALL_EXPORT MonoString*
6721 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6723 #if defined (HOST_WIN32)
6724 #ifndef CSIDL_FLAG_CREATE
6725 #define CSIDL_FLAG_CREATE 0x8000
6728 WCHAR path [MAX_PATH];
6729 /* Create directory if no existing */
6730 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6735 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6736 mono_error_raise_exception (&error);
6740 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6742 return mono_string_new (mono_domain_get (), "");
6745 ICALL_EXPORT MonoArray *
6746 ves_icall_System_Environment_GetLogicalDrives (void)
6749 gunichar2 buf [256], *ptr, *dname;
6751 guint initial_size = 127, size = 128;
6754 MonoString *drivestr;
6755 MonoDomain *domain = mono_domain_get ();
6761 while (size > initial_size) {
6762 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6763 if (size > initial_size) {
6766 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6767 initial_size = size;
6781 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6786 while (*u16) { u16++; len ++; }
6787 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6788 mono_error_raise_exception (&error);
6789 mono_array_setref (result, ndrives++, drivestr);
6799 ICALL_EXPORT MonoString *
6800 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6802 gunichar2 volume_name [MAX_PATH + 1];
6804 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6806 return mono_string_from_utf16 (volume_name);
6809 ICALL_EXPORT MonoString *
6810 ves_icall_System_Environment_InternalGetHome (void)
6812 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6815 static const char *encodings [] = {
6817 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6818 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6819 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6821 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6822 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6823 "x_unicode_2_0_utf_7",
6825 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6826 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6828 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6831 "unicodefffe", "utf_16be",
6838 * Returns the internal codepage, if the value of "int_code_page" is
6839 * 1 at entry, and we can not compute a suitable code page number,
6840 * returns the code page as a string
6842 ICALL_EXPORT MonoString*
6843 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6848 char *codepage = NULL;
6850 int want_name = *int_code_page;
6853 *int_code_page = -1;
6855 g_get_charset (&cset);
6856 c = codepage = strdup (cset);
6857 for (c = codepage; *c; c++){
6858 if (isascii (*c) && isalpha (*c))
6863 /* g_print ("charset: %s\n", cset); */
6865 /* handle some common aliases */
6868 for (i = 0; p != 0; ){
6871 p = encodings [++i];
6874 if (strcmp (p, codepage) == 0){
6875 *int_code_page = code;
6878 p = encodings [++i];
6881 if (strstr (codepage, "utf_8") != NULL)
6882 *int_code_page |= 0x10000000;
6885 if (want_name && *int_code_page == -1)
6886 return mono_string_new (mono_domain_get (), cset);
6891 ICALL_EXPORT MonoBoolean
6892 ves_icall_System_Environment_get_HasShutdownStarted (void)
6894 if (mono_runtime_is_shutting_down ())
6897 if (mono_domain_is_unloading (mono_domain_get ()))
6904 ves_icall_System_Environment_BroadcastSettingChange (void)
6907 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6912 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6918 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6919 MonoReflectionMethod *method,
6920 MonoArray *out_args)
6922 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6925 #ifndef DISABLE_REMOTING
6926 ICALL_EXPORT MonoBoolean
6927 ves_icall_IsTransparentProxy (MonoObject *proxy)
6932 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6938 ICALL_EXPORT MonoReflectionMethod *
6939 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6940 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6942 MonoReflectionMethod *ret = NULL;
6947 MonoMethod **vtable;
6948 MonoMethod *res = NULL;
6950 MONO_CHECK_ARG_NULL (rtype, NULL);
6951 MONO_CHECK_ARG_NULL (rmethod, NULL);
6953 method = rmethod->method;
6954 klass = mono_class_from_mono_type (rtype->type);
6955 mono_class_init_checked (klass, &error);
6956 mono_error_raise_exception (&error);
6958 if (MONO_CLASS_IS_INTERFACE (klass))
6961 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6964 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6965 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6971 mono_class_setup_vtable (klass);
6972 vtable = klass->vtable;
6974 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6975 gboolean variance_used = FALSE;
6976 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6977 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6979 res = vtable [offs + method->slot];
6981 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6984 if (method->slot != -1)
6985 res = vtable [method->slot];
6991 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
6992 mono_error_raise_exception (&error);
6997 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7003 klass = mono_class_from_mono_type (type->type);
7004 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7005 if (!is_ok (&error)) {
7006 mono_error_set_pending_exception (&error);
7010 mono_vtable_set_is_remote (vtable, enable);
7013 #else /* DISABLE_REMOTING */
7016 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7018 g_assert_not_reached ();
7023 ICALL_EXPORT MonoObject *
7024 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7031 domain = mono_object_domain (type);
7032 klass = mono_class_from_mono_type (type->type);
7033 mono_class_init_checked (klass, &error);
7034 mono_error_raise_exception (&error);
7036 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7037 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7041 if (klass->rank >= 1) {
7042 g_assert (klass->rank == 1);
7043 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7045 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7046 if (!is_ok (&error)) {
7047 mono_error_set_pending_exception (&error);
7050 /* Bypass remoting object creation check */
7051 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7052 mono_error_set_pending_exception (&error);
7058 ICALL_EXPORT MonoString *
7059 ves_icall_System_IO_get_temp_path (void)
7061 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7064 #ifndef PLATFORM_NO_DRIVEINFO
7065 ICALL_EXPORT MonoBoolean
7066 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7067 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7071 ULARGE_INTEGER wapi_free_bytes_avail;
7072 ULARGE_INTEGER wapi_total_number_of_bytes;
7073 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7075 *error = ERROR_SUCCESS;
7076 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7077 &wapi_total_number_of_free_bytes);
7080 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7081 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7082 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7084 *free_bytes_avail = 0;
7085 *total_number_of_bytes = 0;
7086 *total_number_of_free_bytes = 0;
7087 *error = GetLastError ();
7093 ICALL_EXPORT guint32
7094 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7096 return GetDriveType (mono_string_chars (root_path_name));
7100 ICALL_EXPORT gpointer
7101 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7103 return mono_compile_method (method);
7106 ICALL_EXPORT MonoString *
7107 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7112 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7114 #if defined (HOST_WIN32)
7115 /* Avoid mixing '/' and '\\' */
7118 for (i = strlen (path) - 1; i >= 0; i--)
7119 if (path [i] == '/')
7123 mcpath = mono_string_new (mono_domain_get (), path);
7130 get_bundled_app_config (void)
7132 const gchar *app_config;
7135 gchar *config_file_name, *config_file_path;
7136 gsize len, config_file_path_length, config_ext_length;
7139 domain = mono_domain_get ();
7140 file = domain->setup->configuration_file;
7141 if (!file || file->length == 0)
7144 // Retrieve config file and remove the extension
7145 config_file_name = mono_string_to_utf8 (file);
7146 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7147 if (!config_file_path)
7148 config_file_path = config_file_name;
7150 config_file_path_length = strlen (config_file_path);
7151 config_ext_length = strlen (".config");
7152 if (config_file_path_length <= config_ext_length)
7155 len = config_file_path_length - config_ext_length;
7156 module = (gchar *)g_malloc0 (len + 1);
7157 memcpy (module, config_file_path, len);
7158 // Get the config file from the module name
7159 app_config = mono_config_string_for_assembly_file (module);
7162 if (config_file_name != config_file_path)
7163 g_free (config_file_name);
7164 g_free (config_file_path);
7169 return mono_string_new (mono_domain_get (), app_config);
7173 get_bundled_machine_config (void)
7175 const gchar *machine_config;
7177 machine_config = mono_get_machine_config ();
7179 if (!machine_config)
7182 return mono_string_new (mono_domain_get (), machine_config);
7185 ICALL_EXPORT MonoString *
7186 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7191 path = g_path_get_dirname (mono_get_config_dir ());
7193 #if defined (HOST_WIN32)
7194 /* Avoid mixing '/' and '\\' */
7197 for (i = strlen (path) - 1; i >= 0; i--)
7198 if (path [i] == '/')
7202 ipath = mono_string_new (mono_domain_get (), path);
7208 ICALL_EXPORT gboolean
7209 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7211 MonoPEResourceDataEntry *entry;
7214 if (!assembly || !result || !size)
7219 image = assembly->assembly->image;
7220 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7224 *result = mono_image_rva_map (image, entry->rde_data_offset);
7229 *size = entry->rde_size;
7234 ICALL_EXPORT MonoBoolean
7235 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7237 return mono_is_debugger_attached ();
7240 ICALL_EXPORT MonoBoolean
7241 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7243 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7244 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7250 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7252 if (mono_get_runtime_callbacks ()->debug_log)
7253 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7257 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7259 #if defined (HOST_WIN32)
7260 OutputDebugString (mono_string_chars (message));
7262 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7266 /* Only used for value types */
7267 ICALL_EXPORT MonoObject *
7268 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7275 domain = mono_object_domain (type);
7276 klass = mono_class_from_mono_type (type->type);
7277 mono_class_init_checked (klass, &error);
7278 mono_error_raise_exception (&error);
7280 if (mono_class_is_nullable (klass))
7281 /* No arguments -> null */
7284 result = mono_object_new_checked (domain, klass, &error);
7285 mono_error_raise_exception (&error);
7289 ICALL_EXPORT MonoReflectionMethod *
7290 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7292 MonoReflectionMethod *ret = NULL;
7295 MonoClass *klass, *parent;
7296 MonoGenericContext *generic_inst = NULL;
7297 MonoMethod *method = m->method;
7298 MonoMethod *result = NULL;
7301 if (method->klass == NULL)
7304 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7305 MONO_CLASS_IS_INTERFACE (method->klass) ||
7306 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7309 slot = mono_method_get_vtable_slot (method);
7313 klass = method->klass;
7314 if (klass->generic_class) {
7315 generic_inst = mono_class_get_context (klass);
7316 klass = klass->generic_class->container_class;
7320 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7321 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7322 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7323 or klass is the generic container class and generic_inst is the instantiation.
7325 when we go to the parent, if the parent is an open constructed type, we need to
7326 replace the type parameters by the definitions from the generic_inst, and then take it
7327 apart again into the klass and the generic_inst.
7329 For cases like this:
7330 class C<T> : B<T, int> {
7331 public override void Foo () { ... }
7333 class B<U,V> : A<HashMap<U,V>> {
7334 public override void Foo () { ... }
7337 public virtual void Foo () { ... }
7340 if at each iteration the parent isn't open, we can skip inflating it. if at some
7341 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7344 MonoGenericContext *parent_inst = NULL;
7345 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7347 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7348 if (!mono_error_ok (&error)) {
7349 mono_error_set_pending_exception (&error);
7353 if (parent->generic_class) {
7354 parent_inst = mono_class_get_context (parent);
7355 parent = parent->generic_class->container_class;
7358 mono_class_setup_vtable (parent);
7359 if (parent->vtable_size <= slot)
7362 generic_inst = parent_inst;
7365 klass = klass->parent;
7368 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7369 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7370 if (!mono_error_ok (&error)) {
7371 mono_error_set_pending_exception (&error);
7375 generic_inst = NULL;
7377 if (klass->generic_class) {
7378 generic_inst = mono_class_get_context (klass);
7379 klass = klass->generic_class->container_class;
7385 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7386 if (!mono_error_ok (&error)) {
7387 mono_error_set_pending_exception (&error);
7392 if (klass == method->klass)
7395 /*This is possible if definition == FALSE.
7396 * Do it here to be really sure we don't read invalid memory.
7398 if (slot >= klass->vtable_size)
7401 mono_class_setup_vtable (klass);
7403 result = klass->vtable [slot];
7404 if (result == NULL) {
7405 /* It is an abstract method */
7406 gpointer iter = NULL;
7407 while ((result = mono_class_get_methods (klass, &iter)))
7408 if (result->slot == slot)
7415 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7416 mono_error_raise_exception (&error);
7420 ICALL_EXPORT MonoString*
7421 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7423 MonoMethod *method = m->method;
7425 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7430 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7432 iter->sig = *(MonoMethodSignature**)argsp;
7434 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7435 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7438 /* FIXME: it's not documented what start is exactly... */
7442 iter->args = argsp + sizeof (gpointer);
7444 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7446 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7449 ICALL_EXPORT MonoTypedRef
7450 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7452 guint32 i, arg_size;
7456 i = iter->sig->sentinelpos + iter->next_arg;
7458 g_assert (i < iter->sig->param_count);
7460 res.type = iter->sig->params [i];
7461 res.klass = mono_class_from_mono_type (res.type);
7462 arg_size = mono_type_stack_size (res.type, &align);
7463 #if defined(__arm__) || defined(__mips__)
7464 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7466 res.value = iter->args;
7467 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7468 /* Values are stored as 8 byte register sized objects, but 'value'
7469 * is dereferenced as a pointer in other routines.
7471 res.value = (char*)res.value + 4;
7473 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7474 if (arg_size <= sizeof (gpointer)) {
7476 int padding = arg_size - mono_type_size (res.type, &dummy);
7477 res.value = (guint8*)res.value + padding;
7480 iter->args = (char*)iter->args + arg_size;
7483 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7488 ICALL_EXPORT MonoTypedRef
7489 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7491 guint32 i, arg_size;
7495 i = iter->sig->sentinelpos + iter->next_arg;
7497 g_assert (i < iter->sig->param_count);
7499 while (i < iter->sig->param_count) {
7500 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7502 res.type = iter->sig->params [i];
7503 res.klass = mono_class_from_mono_type (res.type);
7504 /* FIXME: endianess issue... */
7505 arg_size = mono_type_stack_size (res.type, &align);
7506 #if defined(__arm__) || defined(__mips__)
7507 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7509 res.value = iter->args;
7510 iter->args = (char*)iter->args + arg_size;
7512 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7515 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7523 ICALL_EXPORT MonoType*
7524 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7528 i = iter->sig->sentinelpos + iter->next_arg;
7530 g_assert (i < iter->sig->param_count);
7532 return iter->sig->params [i];
7535 ICALL_EXPORT MonoObject*
7536 mono_TypedReference_ToObject (MonoTypedRef* tref)
7538 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7539 MonoObject** objp = (MonoObject **)tref->value;
7543 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
7546 ICALL_EXPORT MonoTypedRef
7547 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7550 MonoReflectionField *f;
7552 MonoType *ftype = NULL;
7556 memset (&res, 0, sizeof (res));
7559 g_assert (mono_array_length (fields) > 0);
7561 klass = target->vtable->klass;
7563 for (i = 0; i < mono_array_length (fields); ++i) {
7564 f = mono_array_get (fields, MonoReflectionField*, i);
7566 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7569 if (f->field->parent != klass) {
7570 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7574 p = (guint8*)target + f->field->offset;
7576 p += f->field->offset - sizeof (MonoObject);
7577 klass = mono_class_from_mono_type (f->field->type);
7578 ftype = f->field->type;
7582 res.klass = mono_class_from_mono_type (ftype);
7589 prelink_method (MonoMethod *method, MonoError *error)
7591 const char *exc_class, *exc_arg;
7593 mono_error_init (error);
7594 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7596 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7598 mono_error_set_exception_instance (error,
7599 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7602 /* create the wrapper, too? */
7606 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7610 prelink_method (method->method, &error);
7611 mono_error_raise_exception (&error);
7615 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7618 MonoClass *klass = mono_class_from_mono_type (type->type);
7620 gpointer iter = NULL;
7622 mono_class_init_checked (klass, &error);
7623 mono_error_raise_exception (&error);
7625 while ((m = mono_class_get_methods (klass, &iter))) {
7626 prelink_method (m, &error);
7627 mono_error_raise_exception (&error);
7631 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7633 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7634 gint32 const **exponents,
7635 gunichar2 const **digitLowerTable,
7636 gunichar2 const **digitUpperTable,
7637 gint64 const **tenPowersList,
7638 gint32 const **decHexDigits)
7640 *mantissas = Formatter_MantissaBitsTable;
7641 *exponents = Formatter_TensExponentTable;
7642 *digitLowerTable = Formatter_DigitLowerTable;
7643 *digitUpperTable = Formatter_DigitUpperTable;
7644 *tenPowersList = Formatter_TenPowersList;
7645 *decHexDigits = Formatter_DecHexDigits;
7649 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7650 * and avoid useless allocations.
7653 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7655 MonoReflectionType *rt;
7659 mono_error_init (error);
7660 for (i = 0; i < type->num_mods; ++i) {
7661 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7666 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7668 for (i = 0; i < type->num_mods; ++i) {
7669 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7670 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7671 return_val_if_nok (error, NULL);
7673 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7674 return_val_if_nok (error, NULL);
7676 mono_array_setref (res, count, rt);
7683 ICALL_EXPORT MonoArray*
7684 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7687 MonoType *type = param->ClassImpl->type;
7688 MonoClass *member_class = mono_object_class (param->MemberImpl);
7689 MonoMethod *method = NULL;
7692 MonoMethodSignature *sig;
7695 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7696 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7697 method = rmethod->method;
7698 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7699 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7700 if (!(method = prop->property->get))
7701 method = prop->property->set;
7704 char *type_name = mono_type_get_full_name (member_class);
7705 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7706 MonoException *ex = mono_get_exception_not_supported (msg);
7709 mono_set_pending_exception (ex);
7713 image = method->klass->image;
7714 pos = param->PositionImpl;
7715 sig = mono_method_signature (method);
7719 type = sig->params [pos];
7721 res = type_array_from_modifiers (image, type, optional, &error);
7722 mono_error_raise_exception (&error);
7727 get_property_type (MonoProperty *prop)
7729 MonoMethodSignature *sig;
7731 sig = mono_method_signature (prop->get);
7733 } else if (prop->set) {
7734 sig = mono_method_signature (prop->set);
7735 return sig->params [sig->param_count - 1];
7740 ICALL_EXPORT MonoArray*
7741 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7744 MonoType *type = get_property_type (property->property);
7745 MonoImage *image = property->klass->image;
7750 res = type_array_from_modifiers (image, type, optional, &error);
7751 mono_error_raise_exception (&error);
7756 *Construct a MonoType suited to be used to decode a constant blob object.
7758 * @type is the target type which will be constructed
7759 * @blob_type is the blob type, for example, that comes from the constant table
7760 * @real_type is the expected constructed type.
7763 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7765 type->type = blob_type;
7766 type->data.klass = NULL;
7767 if (blob_type == MONO_TYPE_CLASS)
7768 type->data.klass = mono_defaults.object_class;
7769 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7770 /* For enums, we need to use the base type */
7771 type->type = MONO_TYPE_VALUETYPE;
7772 type->data.klass = mono_class_from_mono_type (real_type);
7774 type->data.klass = mono_class_from_mono_type (real_type);
7777 ICALL_EXPORT MonoObject*
7778 property_info_get_default_value (MonoReflectionProperty *property)
7781 MonoProperty *prop = property->property;
7782 MonoType *type = get_property_type (prop);
7783 MonoDomain *domain = mono_object_domain (property);
7784 MonoTypeEnum def_type;
7785 const char *def_value;
7788 mono_class_init (prop->parent);
7790 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7791 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7795 def_value = mono_class_get_property_default_value (prop, &def_type);
7797 mono_type_from_blob_type (&blob_type, def_type, type);
7798 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7803 ICALL_EXPORT MonoBoolean
7804 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7807 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7808 MonoCustomAttrInfo *cinfo;
7811 mono_class_init_checked (attr_class, &error);
7812 mono_error_raise_exception (&error);
7814 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7815 if (!is_ok (&error)) {
7816 mono_error_set_pending_exception (&error);
7821 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7823 mono_custom_attrs_free (cinfo);
7827 ICALL_EXPORT MonoArray*
7828 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7830 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7835 mono_class_init_checked (attr_class, &error);
7836 mono_error_raise_exception (&error);
7839 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7840 if (!mono_error_ok (&error)) {
7841 mono_error_set_pending_exception (&error);
7845 if (mono_loader_get_last_error ()) {
7846 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7853 ICALL_EXPORT MonoArray*
7854 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7858 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7859 mono_error_set_pending_exception (&error);
7864 ICALL_EXPORT MonoString*
7865 ves_icall_Mono_Runtime_GetDisplayName (void)
7868 MonoString *display_name;
7870 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7871 display_name = mono_string_new (mono_domain_get (), info);
7873 return display_name;
7876 ICALL_EXPORT MonoString*
7877 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7880 MonoString *message;
7884 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7885 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7888 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7890 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7891 mono_error_raise_exception (&error);
7898 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7901 char *path_str = mono_string_to_utf8 (path);
7903 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7911 ICALL_EXPORT gpointer
7912 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
7914 return GetCurrentProcess ();
7917 ICALL_EXPORT MonoBoolean
7918 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
7920 return GetExitCodeProcess (handle, (guint32*) exitcode);
7923 ICALL_EXPORT MonoBoolean
7924 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
7926 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
7927 return CloseHandle (handle);
7929 return CloseProcess (handle);
7933 ICALL_EXPORT MonoBoolean
7934 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
7936 return TerminateProcess (handle, exitcode);
7940 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
7942 return WaitForInputIdle (handle, milliseconds);
7945 ICALL_EXPORT MonoBoolean
7946 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
7948 return GetProcessWorkingSetSize (handle, min, max);
7951 ICALL_EXPORT MonoBoolean
7952 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
7954 return SetProcessWorkingSetSize (handle, min, max);
7957 ICALL_EXPORT MonoBoolean
7958 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
7960 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
7964 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
7966 return mono_process_current_pid ();
7970 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
7972 return GetPriorityClass (handle);
7975 ICALL_EXPORT MonoBoolean
7976 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
7978 return SetPriorityClass (handle, priorityClass);
7981 #ifndef DISABLE_ICALL_TABLES
7983 #define ICALL_TYPE(id,name,first)
7984 #define ICALL(id,name,func) Icall_ ## id,
7987 #include "metadata/icall-def.h"
7993 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7994 #define ICALL(id,name,func)
7996 #include "metadata/icall-def.h"
8002 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8003 #define ICALL(id,name,func)
8005 guint16 first_icall;
8008 static const IcallTypeDesc
8009 icall_type_descs [] = {
8010 #include "metadata/icall-def.h"
8014 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8017 #define ICALL_TYPE(id,name,first)
8020 #ifdef HAVE_ARRAY_ELEM_INIT
8021 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8022 #define MSGSTRFIELD1(line) str##line
8024 static const struct msgstrtn_t {
8025 #define ICALL(id,name,func)
8027 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8028 #include "metadata/icall-def.h"
8030 } icall_type_names_str = {
8031 #define ICALL_TYPE(id,name,first) (name),
8032 #include "metadata/icall-def.h"
8035 static const guint16 icall_type_names_idx [] = {
8036 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8037 #include "metadata/icall-def.h"
8040 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8042 static const struct msgstr_t {
8044 #define ICALL_TYPE(id,name,first)
8045 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8046 #include "metadata/icall-def.h"
8048 } icall_names_str = {
8049 #define ICALL(id,name,func) (name),
8050 #include "metadata/icall-def.h"
8053 static const guint16 icall_names_idx [] = {
8054 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8055 #include "metadata/icall-def.h"
8058 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8064 #define ICALL_TYPE(id,name,first) name,
8065 #define ICALL(id,name,func)
8066 static const char* const
8067 icall_type_names [] = {
8068 #include "metadata/icall-def.h"
8072 #define icall_type_name_get(id) (icall_type_names [(id)])
8076 #define ICALL_TYPE(id,name,first)
8077 #define ICALL(id,name,func) name,
8078 static const char* const
8080 #include "metadata/icall-def.h"
8083 #define icall_name_get(id) icall_names [(id)]
8085 #endif /* !HAVE_ARRAY_ELEM_INIT */
8089 #define ICALL_TYPE(id,name,first)
8090 #define ICALL(id,name,func) func,
8091 static const gconstpointer
8092 icall_functions [] = {
8093 #include "metadata/icall-def.h"
8097 #ifdef ENABLE_ICALL_SYMBOL_MAP
8100 #define ICALL_TYPE(id,name,first)
8101 #define ICALL(id,name,func) #func,
8102 static const gconstpointer
8103 icall_symbols [] = {
8104 #include "metadata/icall-def.h"
8109 #endif /* DISABLE_ICALL_TABLES */
8111 static mono_mutex_t icall_mutex;
8112 static GHashTable *icall_hash = NULL;
8113 static GHashTable *jit_icall_hash_name = NULL;
8114 static GHashTable *jit_icall_hash_addr = NULL;
8117 mono_icall_init (void)
8119 #ifndef DISABLE_ICALL_TABLES
8122 /* check that tables are sorted: disable in release */
8125 const char *prev_class = NULL;
8126 const char *prev_method;
8128 for (i = 0; i < Icall_type_num; ++i) {
8129 const IcallTypeDesc *desc;
8132 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8133 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8134 prev_class = icall_type_name_get (i);
8135 desc = &icall_type_descs [i];
8136 num_icalls = icall_desc_num_icalls (desc);
8137 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8138 for (j = 0; j < num_icalls; ++j) {
8139 const char *methodn = icall_name_get (desc->first_icall + j);
8140 if (prev_method && strcmp (prev_method, methodn) >= 0)
8141 g_print ("method %s should come before method %s\n", methodn, prev_method);
8142 prev_method = methodn;
8148 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8149 mono_os_mutex_init (&icall_mutex);
8153 mono_icall_lock (void)
8155 mono_locks_os_acquire (&icall_mutex, IcallLock);
8159 mono_icall_unlock (void)
8161 mono_locks_os_release (&icall_mutex, IcallLock);
8165 mono_icall_cleanup (void)
8167 g_hash_table_destroy (icall_hash);
8168 g_hash_table_destroy (jit_icall_hash_name);
8169 g_hash_table_destroy (jit_icall_hash_addr);
8170 mono_os_mutex_destroy (&icall_mutex);
8174 * mono_add_internal_call:
8175 * @name: method specification to surface to the managed world
8176 * @method: pointer to a C method to invoke when the method is called
8178 * This method surfaces the C function pointed by @method as a method
8179 * that has been surfaced in managed code with the method specified in
8180 * @name as an internal call.
8182 * Internal calls are surfaced to all app domains loaded and they are
8183 * accessibly by a type with the specified name.
8185 * You must provide a fully qualified type name, that is namespaces
8186 * and type name, followed by a colon and the method name, with an
8187 * optional signature to bind.
8189 * For example, the following are all valid declarations:
8191 * "MyApp.Services.ScriptService:Accelerate"
8192 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8194 * You use method parameters in cases where there might be more than
8195 * one surface method to managed code. That way you can register different
8196 * internal calls for different method overloads.
8198 * The internal calls are invoked with no marshalling. This means that .NET
8199 * types like System.String are exposed as `MonoString *` parameters. This is
8200 * different than the way that strings are surfaced in P/Invoke.
8202 * For more information on how the parameters are marshalled, see the
8203 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8206 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8207 * reference for more information on the format of method descriptions.
8210 mono_add_internal_call (const char *name, gconstpointer method)
8214 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8216 mono_icall_unlock ();
8219 #ifndef DISABLE_ICALL_TABLES
8221 #ifdef HAVE_ARRAY_ELEM_INIT
8223 compare_method_imap (const void *key, const void *elem)
8225 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8226 return strcmp (key, method_name);
8230 find_method_icall (const IcallTypeDesc *imap, const char *name)
8232 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);
8235 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8239 compare_class_imap (const void *key, const void *elem)
8241 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8242 return strcmp (key, class_name);
8245 static const IcallTypeDesc*
8246 find_class_icalls (const char *name)
8248 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);
8251 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8254 #else /* HAVE_ARRAY_ELEM_INIT */
8257 compare_method_imap (const void *key, const void *elem)
8259 const char** method_name = (const char**)elem;
8260 return strcmp (key, *method_name);
8264 find_method_icall (const IcallTypeDesc *imap, const char *name)
8266 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8269 return (gpointer)icall_functions [(nameslot - icall_names)];
8273 compare_class_imap (const void *key, const void *elem)
8275 const char** class_name = (const char**)elem;
8276 return strcmp (key, *class_name);
8279 static const IcallTypeDesc*
8280 find_class_icalls (const char *name)
8282 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8285 return &icall_type_descs [nameslot - icall_type_names];
8288 #endif /* HAVE_ARRAY_ELEM_INIT */
8290 #endif /* DISABLE_ICALL_TABLES */
8293 * we should probably export this as an helper (handle nested types).
8294 * Returns the number of chars written in buf.
8297 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8299 int nspacelen, cnamelen;
8300 nspacelen = strlen (klass->name_space);
8301 cnamelen = strlen (klass->name);
8302 if (nspacelen + cnamelen + 2 > bufsize)
8305 memcpy (buf, klass->name_space, nspacelen);
8306 buf [nspacelen ++] = '.';
8308 memcpy (buf + nspacelen, klass->name, cnamelen);
8309 buf [nspacelen + cnamelen] = 0;
8310 return nspacelen + cnamelen;
8313 #ifdef DISABLE_ICALL_TABLES
8315 no_icall_table (void)
8317 g_assert_not_reached ();
8322 mono_lookup_internal_call (MonoMethod *method)
8327 int typelen = 0, mlen, siglen;
8329 #ifndef DISABLE_ICALL_TABLES
8330 const IcallTypeDesc *imap = NULL;
8333 g_assert (method != NULL);
8335 if (method->is_inflated)
8336 method = ((MonoMethodInflated *) method)->declaring;
8338 if (method->klass->nested_in) {
8339 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8343 mname [pos++] = '/';
8346 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8352 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8357 #ifndef DISABLE_ICALL_TABLES
8358 imap = find_class_icalls (mname);
8361 mname [typelen] = ':';
8362 mname [typelen + 1] = ':';
8364 mlen = strlen (method->name);
8365 memcpy (mname + typelen + 2, method->name, mlen);
8366 sigstart = mname + typelen + 2 + mlen;
8369 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8370 siglen = strlen (tmpsig);
8371 if (typelen + mlen + siglen + 6 > sizeof (mname))
8374 memcpy (sigstart + 1, tmpsig, siglen);
8375 sigstart [siglen + 1] = ')';
8376 sigstart [siglen + 2] = 0;
8381 res = g_hash_table_lookup (icall_hash, mname);
8383 mono_icall_unlock ();;
8386 /* try without signature */
8388 res = g_hash_table_lookup (icall_hash, mname);
8390 mono_icall_unlock ();
8394 #ifdef DISABLE_ICALL_TABLES
8395 mono_icall_unlock ();
8396 /* Fail only when the result is actually used */
8397 /* mono_marshal_get_native_wrapper () depends on this */
8398 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8399 return ves_icall_System_String_ctor_RedirectToCreateString;
8401 return no_icall_table;
8403 /* it wasn't found in the static call tables */
8405 mono_icall_unlock ();
8408 res = find_method_icall (imap, sigstart - mlen);
8410 mono_icall_unlock ();
8413 /* try _with_ signature */
8415 res = find_method_icall (imap, sigstart - mlen);
8417 mono_icall_unlock ();
8421 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8422 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8423 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8424 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8425 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");
8426 g_print ("If you see other errors or faults after this message they are probably related\n");
8427 g_print ("and you need to fix your mono install first.\n");
8429 mono_icall_unlock ();
8435 #ifdef ENABLE_ICALL_SYMBOL_MAP
8437 func_cmp (gconstpointer key, gconstpointer p)
8439 return (gsize)key - (gsize)*(gsize*)p;
8444 * mono_lookup_icall_symbol:
8446 * Given the icall METHOD, returns its C symbol.
8449 mono_lookup_icall_symbol (MonoMethod *m)
8451 #ifdef DISABLE_ICALL_TABLES
8452 g_assert_not_reached ();
8455 #ifdef ENABLE_ICALL_SYMBOL_MAP
8459 static gconstpointer *functions_sorted;
8460 static const char**symbols_sorted;
8461 static gboolean inited;
8466 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8467 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8468 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8469 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8470 /* Bubble sort the two arrays */
8474 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8475 if (functions_sorted [i] > functions_sorted [i + 1]) {
8478 tmp = functions_sorted [i];
8479 functions_sorted [i] = functions_sorted [i + 1];
8480 functions_sorted [i + 1] = tmp;
8481 tmp = symbols_sorted [i];
8482 symbols_sorted [i] = symbols_sorted [i + 1];
8483 symbols_sorted [i + 1] = tmp;
8490 func = mono_lookup_internal_call (m);
8493 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8497 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8499 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8500 g_assert_not_reached ();
8507 type_from_typename (char *type_name)
8509 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8511 if (!strcmp (type_name, "int"))
8512 klass = mono_defaults.int_class;
8513 else if (!strcmp (type_name, "ptr"))
8514 klass = mono_defaults.int_class;
8515 else if (!strcmp (type_name, "void"))
8516 klass = mono_defaults.void_class;
8517 else if (!strcmp (type_name, "int32"))
8518 klass = mono_defaults.int32_class;
8519 else if (!strcmp (type_name, "uint32"))
8520 klass = mono_defaults.uint32_class;
8521 else if (!strcmp (type_name, "int8"))
8522 klass = mono_defaults.sbyte_class;
8523 else if (!strcmp (type_name, "uint8"))
8524 klass = mono_defaults.byte_class;
8525 else if (!strcmp (type_name, "int16"))
8526 klass = mono_defaults.int16_class;
8527 else if (!strcmp (type_name, "uint16"))
8528 klass = mono_defaults.uint16_class;
8529 else if (!strcmp (type_name, "long"))
8530 klass = mono_defaults.int64_class;
8531 else if (!strcmp (type_name, "ulong"))
8532 klass = mono_defaults.uint64_class;
8533 else if (!strcmp (type_name, "float"))
8534 klass = mono_defaults.single_class;
8535 else if (!strcmp (type_name, "double"))
8536 klass = mono_defaults.double_class;
8537 else if (!strcmp (type_name, "object"))
8538 klass = mono_defaults.object_class;
8539 else if (!strcmp (type_name, "obj"))
8540 klass = mono_defaults.object_class;
8541 else if (!strcmp (type_name, "string"))
8542 klass = mono_defaults.string_class;
8543 else if (!strcmp (type_name, "bool"))
8544 klass = mono_defaults.boolean_class;
8545 else if (!strcmp (type_name, "boolean"))
8546 klass = mono_defaults.boolean_class;
8548 g_error ("%s", type_name);
8549 g_assert_not_reached ();
8551 return &klass->byval_arg;
8555 * LOCKING: Take the corlib image lock.
8557 MonoMethodSignature*
8558 mono_create_icall_signature (const char *sigstr)
8563 MonoMethodSignature *res, *res2;
8564 MonoImage *corlib = mono_defaults.corlib;
8566 mono_image_lock (corlib);
8567 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8568 mono_image_unlock (corlib);
8573 parts = g_strsplit (sigstr, " ", 256);
8582 res = mono_metadata_signature_alloc (corlib, len - 1);
8587 * Under windows, the default pinvoke calling convention is STDCALL but
8590 res->call_convention = MONO_CALL_C;
8593 res->ret = type_from_typename (parts [0]);
8594 for (i = 1; i < len; ++i) {
8595 res->params [i - 1] = type_from_typename (parts [i]);
8600 mono_image_lock (corlib);
8601 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8603 res = res2; /*Value is allocated in the image pool*/
8605 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8606 mono_image_unlock (corlib);
8612 mono_find_jit_icall_by_name (const char *name)
8614 MonoJitICallInfo *info;
8615 g_assert (jit_icall_hash_name);
8618 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8619 mono_icall_unlock ();
8624 mono_find_jit_icall_by_addr (gconstpointer addr)
8626 MonoJitICallInfo *info;
8627 g_assert (jit_icall_hash_addr);
8630 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8631 mono_icall_unlock ();
8637 * mono_get_jit_icall_info:
8639 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8640 * caller should access it while holding the icall lock.
8643 mono_get_jit_icall_info (void)
8645 return jit_icall_hash_name;
8649 * mono_lookup_jit_icall_symbol:
8651 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8654 mono_lookup_jit_icall_symbol (const char *name)
8656 MonoJitICallInfo *info;
8657 const char *res = NULL;
8660 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8662 res = info->c_symbol;
8663 mono_icall_unlock ();
8668 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8671 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8672 mono_icall_unlock ();
8676 * 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
8677 * icalls without wrappers in some cases.
8680 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8682 MonoJitICallInfo *info;
8689 if (!jit_icall_hash_name) {
8690 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8691 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8694 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8695 g_warning ("jit icall already defined \"%s\"\n", name);
8696 g_assert_not_reached ();
8699 info = g_new0 (MonoJitICallInfo, 1);
8704 info->c_symbol = c_symbol;
8705 info->no_raise = no_raise;
8708 info->wrapper = func;
8710 info->wrapper = NULL;
8713 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8714 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8716 mono_icall_unlock ();
8721 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8723 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);