5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
9 * Aleksey Kliger (aleksey@xamarin.com)
11 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
12 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
24 #ifdef HAVE_SYS_TIME_H
30 #if defined (HOST_WIN32)
33 #if defined (HAVE_WCHAR_H)
37 #include "mono/utils/mono-membar.h"
38 #include <mono/metadata/object.h>
39 #include <mono/metadata/threads.h>
40 #include <mono/metadata/threads-types.h>
41 #include <mono/metadata/threadpool-ms.h>
42 #include <mono/metadata/threadpool-ms-io.h>
43 #include <mono/metadata/monitor.h>
44 #include <mono/metadata/reflection.h>
45 #include <mono/metadata/assembly.h>
46 #include <mono/metadata/tabledefs.h>
47 #include <mono/metadata/exception.h>
48 #include <mono/metadata/exception-internals.h>
49 #include <mono/metadata/file-io.h>
50 #include <mono/metadata/console-io.h>
51 #include <mono/metadata/mono-route.h>
52 #include <mono/metadata/socket-io.h>
53 #include <mono/metadata/mono-endian.h>
54 #include <mono/metadata/tokentype.h>
55 #include <mono/metadata/domain-internals.h>
56 #include <mono/metadata/metadata-internals.h>
57 #include <mono/metadata/class-internals.h>
58 #include <mono/metadata/reflection-internals.h>
59 #include <mono/metadata/marshal.h>
60 #include <mono/metadata/gc-internals.h>
61 #include <mono/metadata/mono-gc.h>
62 #include <mono/metadata/rand.h>
63 #include <mono/metadata/sysmath.h>
64 #include <mono/metadata/string-icalls.h>
65 #include <mono/metadata/debug-helpers.h>
66 #include <mono/metadata/process.h>
67 #include <mono/metadata/environment.h>
68 #include <mono/metadata/profiler-private.h>
69 #include <mono/metadata/locales.h>
70 #include <mono/metadata/filewatcher.h>
71 #include <mono/metadata/security.h>
72 #include <mono/metadata/mono-config.h>
73 #include <mono/metadata/cil-coff.h>
74 #include <mono/metadata/number-formatter.h>
75 #include <mono/metadata/security-manager.h>
76 #include <mono/metadata/security-core-clr.h>
77 #include <mono/metadata/mono-perfcounters.h>
78 #include <mono/metadata/mono-debug.h>
79 #include <mono/metadata/mono-ptr-array.h>
80 #include <mono/metadata/verify-internals.h>
81 #include <mono/metadata/runtime.h>
82 #include <mono/metadata/file-mmap.h>
83 #include <mono/metadata/seq-points-data.h>
84 #include <mono/io-layer/io-layer.h>
85 #include <mono/utils/monobitset.h>
86 #include <mono/utils/mono-time.h>
87 #include <mono/utils/mono-proclib.h>
88 #include <mono/utils/mono-string.h>
89 #include <mono/utils/mono-error-internals.h>
90 #include <mono/utils/mono-mmap.h>
91 #include <mono/utils/mono-io-portability.h>
92 #include <mono/utils/mono-digest.h>
93 #include <mono/utils/bsearch.h>
94 #include <mono/utils/mono-os-mutex.h>
95 #include <mono/utils/mono-threads.h>
97 #if defined (HOST_WIN32)
101 #include "decimal-ms.h"
102 #include "number-ms.h"
104 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
105 #include <sys/utsname.h>
108 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
110 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
112 /* Lazy class loading functions */
113 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
114 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
115 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
116 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
121 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
123 static inline MonoBoolean
124 is_generic_parameter (MonoType *type)
126 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
130 mono_class_init_checked (MonoClass *klass, MonoError *error)
132 mono_error_init (error);
134 if (!mono_class_init (klass))
135 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
138 ICALL_EXPORT MonoObject *
139 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
145 ac = (MonoClass *)arr->obj.vtable->klass;
147 esize = mono_array_element_size (ac);
148 ea = (gpointer*)((char*)arr->vector + (pos * esize));
150 if (ac->element_class->valuetype)
151 return mono_value_box (arr->obj.vtable->domain, ac->element_class, ea);
153 return (MonoObject *)*ea;
156 ICALL_EXPORT MonoObject *
157 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
163 MONO_CHECK_ARG_NULL (idxs, NULL);
166 ic = (MonoClass *)io->obj.vtable->klass;
168 ac = (MonoClass *)arr->obj.vtable->klass;
170 g_assert (ic->rank == 1);
171 if (io->bounds != NULL || io->max_length != ac->rank) {
172 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
176 ind = (gint32 *)io->vector;
178 if (arr->bounds == NULL) {
179 if (*ind < 0 || *ind >= arr->max_length) {
180 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
184 return ves_icall_System_Array_GetValueImpl (arr, *ind);
187 for (i = 0; i < ac->rank; i++) {
188 if ((ind [i] < arr->bounds [i].lower_bound) ||
189 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
190 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
195 pos = ind [0] - arr->bounds [0].lower_bound;
196 for (i = 1; i < ac->rank; i++)
197 pos = pos * arr->bounds [i].length + ind [i] -
198 arr->bounds [i].lower_bound;
200 return ves_icall_System_Array_GetValueImpl (arr, pos);
204 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
206 MonoClass *ac, *vc, *ec;
216 vc = value->vtable->klass;
220 ac = arr->obj.vtable->klass;
221 ec = ac->element_class;
223 esize = mono_array_element_size (ac);
224 ea = (gpointer*)((char*)arr->vector + (pos * esize));
225 va = (gpointer*)((char*)value + sizeof (MonoObject));
227 if (mono_class_is_nullable (ec)) {
228 mono_nullable_init ((guint8*)ea, value, ec);
233 mono_gc_bzero_atomic (ea, esize);
237 #define NO_WIDENING_CONVERSION G_STMT_START{\
238 mono_set_pending_exception (mono_get_exception_argument ( \
239 "value", "not a widening conversion")); \
243 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
244 if (esize < vsize + (extra)) { \
245 mono_set_pending_exception (mono_get_exception_argument ( \
246 "value", "not a widening conversion")); \
251 #define INVALID_CAST G_STMT_START{ \
252 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
253 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
257 /* Check element (destination) type. */
258 switch (ec->byval_arg.type) {
259 case MONO_TYPE_STRING:
260 switch (vc->byval_arg.type) {
261 case MONO_TYPE_STRING:
267 case MONO_TYPE_BOOLEAN:
268 switch (vc->byval_arg.type) {
269 case MONO_TYPE_BOOLEAN:
282 NO_WIDENING_CONVERSION;
291 if (!ec->valuetype) {
292 if (!mono_object_isinst (value, ec))
294 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
298 if (mono_object_isinst (value, ec)) {
299 if (ec->has_references)
300 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
302 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
309 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
311 et = ec->byval_arg.type;
312 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
313 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
315 vt = vc->byval_arg.type;
316 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
317 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
319 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
325 case MONO_TYPE_CHAR: \
326 CHECK_WIDENING_CONVERSION(0); \
327 *(etype *) ea = (etype) u64; \
329 /* You can't assign a signed value to an unsigned array. */ \
334 /* You can't assign a floating point number to an integer array. */ \
337 NO_WIDENING_CONVERSION; \
341 #define ASSIGN_SIGNED(etype) G_STMT_START{\
347 CHECK_WIDENING_CONVERSION(0); \
348 *(etype *) ea = (etype) i64; \
350 /* You can assign an unsigned value to a signed array if the array's */ \
351 /* element size is larger than the value size. */ \
356 case MONO_TYPE_CHAR: \
357 CHECK_WIDENING_CONVERSION(1); \
358 *(etype *) ea = (etype) u64; \
360 /* You can't assign a floating point number to an integer array. */ \
363 NO_WIDENING_CONVERSION; \
367 #define ASSIGN_REAL(etype) G_STMT_START{\
371 CHECK_WIDENING_CONVERSION(0); \
372 *(etype *) ea = (etype) r64; \
374 /* All integer values fit into a floating point array, so we don't */ \
375 /* need to CHECK_WIDENING_CONVERSION here. */ \
380 *(etype *) ea = (etype) i64; \
386 case MONO_TYPE_CHAR: \
387 *(etype *) ea = (etype) u64; \
394 u64 = *(guint8 *) va;
397 u64 = *(guint16 *) va;
400 u64 = *(guint32 *) va;
403 u64 = *(guint64 *) va;
409 i64 = *(gint16 *) va;
412 i64 = *(gint32 *) va;
415 i64 = *(gint64 *) va;
418 r64 = *(gfloat *) va;
421 r64 = *(gdouble *) va;
424 u64 = *(guint16 *) va;
426 case MONO_TYPE_BOOLEAN:
427 /* Boolean is only compatible with itself. */
440 NO_WIDENING_CONVERSION;
447 /* If we can't do a direct copy, let's try a widening conversion. */
450 ASSIGN_UNSIGNED (guint16);
452 ASSIGN_UNSIGNED (guint8);
454 ASSIGN_UNSIGNED (guint16);
456 ASSIGN_UNSIGNED (guint32);
458 ASSIGN_UNSIGNED (guint64);
460 ASSIGN_SIGNED (gint8);
462 ASSIGN_SIGNED (gint16);
464 ASSIGN_SIGNED (gint32);
466 ASSIGN_SIGNED (gint64);
468 ASSIGN_REAL (gfloat);
470 ASSIGN_REAL (gdouble);
474 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
478 #undef NO_WIDENING_CONVERSION
479 #undef CHECK_WIDENING_CONVERSION
480 #undef ASSIGN_UNSIGNED
486 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
492 MONO_CHECK_ARG_NULL (idxs,);
494 ic = idxs->obj.vtable->klass;
495 ac = arr->obj.vtable->klass;
497 g_assert (ic->rank == 1);
498 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
499 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
503 ind = (gint32 *)idxs->vector;
505 if (arr->bounds == NULL) {
506 if (*ind < 0 || *ind >= arr->max_length) {
507 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
511 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
515 for (i = 0; i < ac->rank; i++)
516 if ((ind [i] < arr->bounds [i].lower_bound) ||
517 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
518 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
522 pos = ind [0] - arr->bounds [0].lower_bound;
523 for (i = 1; i < ac->rank; i++)
524 pos = pos * arr->bounds [i].length + ind [i] -
525 arr->bounds [i].lower_bound;
527 ves_icall_System_Array_SetValueImpl (arr, value, pos);
530 ICALL_EXPORT MonoArray *
531 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
534 MonoClass *aklass, *klass;
537 gboolean bounded = FALSE;
539 MONO_CHECK_ARG_NULL (type, NULL);
540 MONO_CHECK_ARG_NULL (lengths, NULL);
542 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
544 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
546 for (i = 0; i < mono_array_length (lengths); i++) {
547 if (mono_array_get (lengths, gint32, i) < 0) {
548 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
553 klass = mono_class_from_mono_type (type->type);
554 mono_class_init_checked (klass, &error);
555 mono_error_raise_exception (&error);
557 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
558 /* vectors are not the same as one dimensional arrays with no-zero bounds */
563 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
565 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
566 for (i = 0; i < aklass->rank; ++i) {
567 sizes [i] = mono_array_get (lengths, guint32, i);
569 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
571 sizes [i + aklass->rank] = 0;
574 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
575 mono_error_set_pending_exception (&error);
580 ICALL_EXPORT MonoArray *
581 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
584 MonoClass *aklass, *klass;
587 gboolean bounded = FALSE;
589 MONO_CHECK_ARG_NULL (type, NULL);
590 MONO_CHECK_ARG_NULL (lengths, NULL);
592 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
594 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
596 for (i = 0; i < mono_array_length (lengths); i++) {
597 if ((mono_array_get (lengths, gint64, i) < 0) ||
598 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
599 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
604 klass = mono_class_from_mono_type (type->type);
605 mono_class_init_checked (klass, &error);
606 mono_error_raise_exception (&error);
608 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
609 /* vectors are not the same as one dimensional arrays with no-zero bounds */
614 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
616 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
617 for (i = 0; i < aklass->rank; ++i) {
618 sizes [i] = mono_array_get (lengths, guint64, i);
620 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
622 sizes [i + aklass->rank] = 0;
625 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
626 mono_error_set_pending_exception (&error);
632 ves_icall_System_Array_GetRank (MonoObject *arr)
634 return arr->vtable->klass->rank;
638 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
640 gint32 rank = arr->obj.vtable->klass->rank;
643 if ((dimension < 0) || (dimension >= rank)) {
644 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
648 if (arr->bounds == NULL)
649 length = arr->max_length;
651 length = arr->bounds [dimension].length;
653 #ifdef MONO_BIG_ARRAYS
654 if (length > G_MAXINT32) {
655 mono_set_pending_exception (mono_get_exception_overflow ());
663 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
665 gint32 rank = arr->obj.vtable->klass->rank;
667 if ((dimension < 0) || (dimension >= rank)) {
668 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
672 if (arr->bounds == NULL)
673 return arr->max_length;
675 return arr->bounds [dimension].length;
679 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
681 gint32 rank = arr->obj.vtable->klass->rank;
683 if ((dimension < 0) || (dimension >= rank)) {
684 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
688 if (arr->bounds == NULL)
691 return arr->bounds [dimension].lower_bound;
695 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
697 int sz = mono_array_element_size (mono_object_class (arr));
698 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
701 ICALL_EXPORT gboolean
702 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
707 MonoVTable *src_vtable;
708 MonoVTable *dest_vtable;
709 MonoClass *src_class;
710 MonoClass *dest_class;
712 src_vtable = source->obj.vtable;
713 dest_vtable = dest->obj.vtable;
715 if (src_vtable->rank != dest_vtable->rank)
718 if (source->bounds || dest->bounds)
721 /* there's no integer overflow since mono_array_length returns an unsigned integer */
722 if ((dest_idx + length > mono_array_length_fast (dest)) ||
723 (source_idx + length > mono_array_length_fast (source)))
726 src_class = src_vtable->klass->element_class;
727 dest_class = dest_vtable->klass->element_class;
730 * Handle common cases.
733 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
734 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
736 if (src_class == mono_defaults.object_class && dest_class->valuetype)
739 /* Check if we're copying a char[] <==> (u)short[] */
740 if (src_class != dest_class) {
741 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
744 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
745 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
749 if (dest_class->valuetype) {
750 element_size = mono_array_element_size (source->obj.vtable->klass);
751 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
752 if (dest_class->has_references) {
753 mono_value_copy_array (dest, dest_idx, source_addr, length);
755 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
756 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
759 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
766 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
772 ac = (MonoClass *)arr->obj.vtable->klass;
774 esize = mono_array_element_size (ac);
775 ea = (gpointer*)((char*)arr->vector + (pos * esize));
777 mono_gc_memmove_atomic (value, ea, esize);
781 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
787 ac = (MonoClass *)arr->obj.vtable->klass;
788 ec = ac->element_class;
790 esize = mono_array_element_size (ac);
791 ea = (gpointer*)((char*)arr->vector + (pos * esize));
793 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
794 g_assert (esize == sizeof (gpointer));
795 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
797 g_assert (ec->inited);
798 g_assert (esize == mono_class_value_size (ec, NULL));
799 if (ec->has_references)
800 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
802 mono_gc_memmove_atomic (ea, value, esize);
807 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
809 MonoClass *klass = array->obj.vtable->klass;
810 guint32 size = mono_array_element_size (klass);
811 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
813 const char *field_data;
815 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
816 MonoException *exc = mono_get_exception_argument("array",
817 "Cannot initialize array of non-primitive type.");
818 mono_set_pending_exception (exc);
822 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
823 MonoException *exc = mono_get_exception_argument("field_handle",
824 "Field doesn't have an RVA");
825 mono_set_pending_exception (exc);
829 size *= array->max_length;
830 field_data = mono_field_get_data (field_handle);
832 if (size > mono_type_size (field_handle->type, &align)) {
833 MonoException *exc = mono_get_exception_argument("field_handle",
834 "Field not large enough to fill array");
835 mono_set_pending_exception (exc);
839 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
841 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
842 guint ## n *src = (guint ## n *) field_data; \
844 nEnt = (size / sizeof(guint ## n)); \
846 for (i = 0; i < nEnt; i++) { \
847 data[i] = read ## n (&src[i]); \
851 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
853 switch (type->type) {
870 memcpy (mono_array_addr (array, char, 0), field_data, size);
874 memcpy (mono_array_addr (array, char, 0), field_data, size);
879 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
881 return offsetof (MonoString, chars);
884 ICALL_EXPORT MonoObject *
885 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
887 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
891 MonoObject *ret = mono_object_clone_checked (obj, &error);
892 mono_error_set_pending_exception (&error);
899 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
905 MONO_CHECK_ARG_NULL (handle,);
907 klass = mono_class_from_mono_type (handle);
908 MONO_CHECK_ARG (handle, klass,);
910 if (klass->generic_container)
913 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
914 if (!is_ok (&error)) {
915 mono_error_set_pending_exception (&error);
919 /* This will call the type constructor */
920 if (!mono_runtime_class_init_full (vtable, &error))
921 mono_error_set_pending_exception (&error);
925 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
929 mono_image_check_for_module_cctor (image);
930 if (image->has_module_cctor) {
931 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
932 if (!mono_error_ok (&error)) {
933 mono_error_set_pending_exception (&error);
936 /*It's fine to raise the exception here*/
937 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
938 if (!is_ok (&error)) {
939 mono_error_set_pending_exception (&error);
942 if (!mono_runtime_class_init_full (vtable, &error))
943 mono_error_set_pending_exception (&error);
947 ICALL_EXPORT MonoBoolean
948 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
953 /* later make this configurable and per-arch */
954 int min_size = 4096 * 4 * sizeof (void*);
955 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
956 /* if we have no info we are optimistic and assume there is enough room */
960 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
964 current = (guint8 *)&stack_addr;
965 if (current > stack_addr) {
966 if ((current - stack_addr) < min_size)
969 if (current - (stack_addr - stack_size) < min_size)
975 ICALL_EXPORT MonoObject *
976 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
979 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
980 mono_error_set_pending_exception (&error);
986 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
989 MonoObject **values = NULL;
992 gint32 result = (int)(gsize)mono_defaults.int32_class;
993 MonoClassField* field;
996 klass = mono_object_class (this_obj);
998 if (mono_class_num_fields (klass) == 0)
1002 * Compute the starting value of the hashcode for fields of primitive
1003 * types, and return the remaining fields in an array to the managed side.
1004 * This way, we can avoid costly reflection operations in managed code.
1007 while ((field = mono_class_get_fields (klass, &iter))) {
1008 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1010 if (mono_field_is_deleted (field))
1012 /* FIXME: Add more types */
1013 switch (field->type->type) {
1015 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1017 case MONO_TYPE_STRING: {
1019 s = *(MonoString**)((guint8*)this_obj + field->offset);
1021 result ^= mono_string_hash (s);
1026 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1027 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1028 values [count++] = o;
1034 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1035 for (i = 0; i < count; ++i)
1036 mono_array_setref (*fields, i, values [i]);
1043 ICALL_EXPORT MonoBoolean
1044 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1047 MonoObject **values = NULL;
1049 MonoClassField* field;
1053 MONO_CHECK_ARG_NULL (that, FALSE);
1055 if (this_obj->vtable != that->vtable)
1058 klass = mono_object_class (this_obj);
1060 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1061 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1064 * Do the comparison for fields of primitive type and return a result if
1065 * possible. Otherwise, return the remaining fields in an array to the
1066 * managed side. This way, we can avoid costly reflection operations in
1071 while ((field = mono_class_get_fields (klass, &iter))) {
1072 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1074 if (mono_field_is_deleted (field))
1076 /* FIXME: Add more types */
1077 switch (field->type->type) {
1080 case MONO_TYPE_BOOLEAN:
1081 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1086 case MONO_TYPE_CHAR:
1087 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1092 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1097 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1101 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1105 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1110 case MONO_TYPE_STRING: {
1111 MonoString *s1, *s2;
1112 guint32 s1len, s2len;
1113 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1114 s2 = *(MonoString**)((guint8*)that + field->offset);
1117 if ((s1 == NULL) || (s2 == NULL))
1119 s1len = mono_string_length (s1);
1120 s2len = mono_string_length (s2);
1124 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1130 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1131 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1132 values [count++] = o;
1133 o = mono_field_get_value_object (mono_object_domain (this_obj), field, that);
1134 values [count++] = o;
1137 if (klass->enumtype)
1138 /* enums only have one non-static field */
1144 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1145 for (i = 0; i < count; ++i)
1146 mono_array_setref_fast (*fields, i, values [i]);
1153 ICALL_EXPORT MonoReflectionType *
1154 ves_icall_System_Object_GetType (MonoObject *obj)
1157 MonoReflectionType *ret;
1158 #ifndef DISABLE_REMOTING
1159 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1160 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1163 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1165 mono_error_raise_exception (&error);
1171 ves_icall_MonoType_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1173 mtype->type = &obj->vtable->klass->byval_arg;
1174 g_assert (mtype->type->type);
1178 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1180 MONO_CHECK_ARG_NULL (obj, 0);
1183 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1184 mono_error_raise_exception (&error);
1189 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1190 MonoReflectionMethod *method,
1191 MonoArray *opt_param_types)
1193 MONO_CHECK_ARG_NULL (method, 0);
1196 gint32 result = mono_image_create_method_token (
1197 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1198 mono_error_raise_exception (&error);
1203 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1206 mono_image_create_pefile (mb, file, &error);
1207 mono_error_raise_exception (&error);
1211 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1214 if (!mono_image_build_metadata (mb, &error))
1215 mono_error_raise_exception (&error);
1219 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1221 mono_image_register_token (mb->dynamic_image, token, obj);
1224 ICALL_EXPORT MonoObject*
1225 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1229 mono_loader_lock ();
1230 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1231 mono_loader_unlock ();
1237 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1239 MonoMethod **dest = (MonoMethod **)data;
1241 /* skip unmanaged frames */
1257 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1259 MonoMethod **dest = (MonoMethod **)data;
1261 /* skip unmanaged frames */
1266 if (!strcmp (m->klass->name_space, "System.Reflection"))
1275 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1277 MonoMethod **dest = (MonoMethod **)data;
1279 /* skip unmanaged frames */
1283 if (m->wrapper_type != MONO_WRAPPER_NONE)
1286 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1300 static MonoReflectionType *
1301 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1303 MonoMethod *m, *dest;
1305 MonoType *type = NULL;
1306 MonoAssembly *assembly = NULL;
1307 gboolean type_resolve = FALSE;
1309 mono_error_init (error);
1312 * We must compute the calling assembly as type loading must happen under a metadata context.
1313 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1314 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1316 m = mono_method_get_last_managed ();
1319 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1324 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1325 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1326 * to crash. This only seems to happen in some strange remoting
1327 * scenarios and I was unable to figure out what's happening there.
1328 * Dec 10, 2005 - Martin.
1332 assembly = dest->klass->image->assembly;
1333 type_resolve = TRUE;
1335 g_warning (G_STRLOC);
1338 if (info->assembly.name)
1339 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1343 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1344 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1347 if (!info->assembly.name && !type) /* try mscorlib */
1348 type = mono_reflection_get_type (NULL, info, ignoreCase, &type_resolve);
1350 if (assembly && !type && type_resolve) {
1351 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1352 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1358 return mono_type_get_object_checked (mono_domain_get (), type, error);
1361 ICALL_EXPORT MonoReflectionType*
1362 ves_icall_System_Type_internal_from_name (MonoString *name,
1363 MonoBoolean throwOnError,
1364 MonoBoolean ignoreCase)
1367 char *str = mono_string_to_utf8 (name);
1368 MonoTypeNameParse info;
1369 MonoReflectionType *type;
1372 parsedOk = mono_reflection_parse_type (str, &info);
1374 /* mono_reflection_parse_type() mangles the string */
1376 mono_reflection_free_type_info (&info);
1379 mono_set_pending_exception (mono_get_exception_argument("typeName", "failed parse"));
1384 type = type_from_parsed_name (&info, ignoreCase, &error);
1386 mono_reflection_free_type_info (&info);
1389 if (!mono_error_ok (&error)) {
1391 mono_error_set_pending_exception (&error);
1393 mono_error_cleanup (&error);
1398 MonoException *e = NULL;
1401 e = mono_get_exception_type_load (name, NULL);
1403 mono_loader_clear_error ();
1405 mono_set_pending_exception (e);
1414 ICALL_EXPORT MonoReflectionType*
1415 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1418 MonoReflectionType *ret;
1419 MonoDomain *domain = mono_domain_get ();
1421 ret = mono_type_get_object_checked (domain, handle, &error);
1422 mono_error_raise_exception (&error);
1427 /* System.TypeCode */
1446 TYPECODE_STRING = 18
1449 ICALL_EXPORT guint32
1450 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1452 int t = type->type->type;
1454 if (type->type->byref)
1455 return TYPECODE_OBJECT;
1459 case MONO_TYPE_VOID:
1460 return TYPECODE_OBJECT;
1461 case MONO_TYPE_BOOLEAN:
1462 return TYPECODE_BOOLEAN;
1464 return TYPECODE_BYTE;
1466 return TYPECODE_SBYTE;
1468 return TYPECODE_UINT16;
1470 return TYPECODE_INT16;
1471 case MONO_TYPE_CHAR:
1472 return TYPECODE_CHAR;
1476 return TYPECODE_OBJECT;
1478 return TYPECODE_UINT32;
1480 return TYPECODE_INT32;
1482 return TYPECODE_UINT64;
1484 return TYPECODE_INT64;
1486 return TYPECODE_SINGLE;
1488 return TYPECODE_DOUBLE;
1489 case MONO_TYPE_VALUETYPE: {
1490 MonoClass *klass = type->type->data.klass;
1492 if (klass->enumtype) {
1493 t = mono_class_enum_basetype (klass)->type;
1495 } else if (mono_is_corlib_image (klass->image)) {
1496 if (strcmp (klass->name_space, "System") == 0) {
1497 if (strcmp (klass->name, "Decimal") == 0)
1498 return TYPECODE_DECIMAL;
1499 else if (strcmp (klass->name, "DateTime") == 0)
1500 return TYPECODE_DATETIME;
1503 return TYPECODE_OBJECT;
1505 case MONO_TYPE_STRING:
1506 return TYPECODE_STRING;
1507 case MONO_TYPE_SZARRAY:
1508 case MONO_TYPE_ARRAY:
1509 case MONO_TYPE_OBJECT:
1511 case MONO_TYPE_MVAR:
1512 case MONO_TYPE_TYPEDBYREF:
1513 return TYPECODE_OBJECT;
1514 case MONO_TYPE_CLASS:
1516 MonoClass *klass = type->type->data.klass;
1517 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1518 if (strcmp (klass->name, "DBNull") == 0)
1519 return TYPECODE_DBNULL;
1522 return TYPECODE_OBJECT;
1523 case MONO_TYPE_GENERICINST:
1524 return TYPECODE_OBJECT;
1526 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1532 mono_type_is_primitive (MonoType *type)
1534 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1535 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1539 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1541 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1542 return mono_class_enum_basetype (type->data.klass);
1543 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1544 return mono_class_enum_basetype (type->data.generic_class->container_class);
1548 ICALL_EXPORT guint32
1549 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1554 g_assert (type != NULL);
1556 klass = mono_class_from_mono_type (type->type);
1557 klassc = mono_class_from_mono_type (c->type);
1559 if (type->type->byref ^ c->type->byref)
1562 if (type->type->byref) {
1563 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1564 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1566 klass = mono_class_from_mono_type (t);
1567 klassc = mono_class_from_mono_type (ot);
1569 if (mono_type_is_primitive (t)) {
1570 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1571 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1572 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1573 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1574 return t->type == ot->type;
1576 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1579 if (klass->valuetype)
1580 return klass == klassc;
1581 return klass->valuetype == klassc->valuetype;
1584 return mono_class_is_assignable_from (klass, klassc);
1587 ICALL_EXPORT guint32
1588 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1591 MonoClass *klass = mono_class_from_mono_type (type->type);
1592 mono_class_init_checked (klass, &error);
1593 mono_error_raise_exception (&error);
1594 return mono_object_isinst (obj, klass) != NULL;
1597 ICALL_EXPORT guint32
1598 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1600 MonoClass *klass = mono_class_from_mono_type (type->type);
1601 return klass->flags;
1604 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1605 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1608 MonoClass *klass = field->field->parent;
1609 MonoMarshalType *info;
1613 if (klass->generic_container ||
1614 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1617 ftype = mono_field_get_type (field->field);
1618 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1621 info = mono_marshal_load_type_info (klass);
1623 for (i = 0; i < info->num_fields; ++i) {
1624 if (info->fields [i].field == field->field) {
1625 if (!info->fields [i].mspec)
1628 MonoReflectionMarshalAsAttribute* obj;
1629 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1630 if (!mono_error_ok (&error))
1631 mono_error_set_pending_exception (&error);
1640 ICALL_EXPORT MonoReflectionField*
1641 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1644 gboolean found = FALSE;
1651 klass = handle->parent;
1653 klass = mono_class_from_mono_type (type);
1655 /* Check that the field belongs to the class */
1656 for (k = klass; k; k = k->parent) {
1657 if (k == handle->parent) {
1664 /* The managed code will throw the exception */
1668 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1669 mono_error_raise_exception (&error);
1673 ICALL_EXPORT MonoArray*
1674 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1677 MonoType *type = mono_field_get_type_checked (field->field, &error);
1680 if (!mono_error_ok (&error)) {
1681 mono_error_set_pending_exception (&error);
1685 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1686 mono_error_raise_exception (&error);
1691 vell_icall_get_method_attributes (MonoMethod *method)
1693 return method->flags;
1697 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1700 MonoReflectionType *rt;
1701 MonoDomain *domain = mono_domain_get ();
1702 MonoMethodSignature* sig;
1704 sig = mono_method_signature_checked (method, &error);
1705 if (!mono_error_ok (&error)) {
1706 mono_error_set_pending_exception (&error);
1710 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1711 if (!mono_error_ok (&error)) {
1712 mono_error_set_pending_exception (&error);
1716 MONO_STRUCT_SETREF (info, parent, rt);
1718 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1719 if (!mono_error_ok (&error)) {
1720 mono_error_set_pending_exception (&error);
1724 MONO_STRUCT_SETREF (info, ret, rt);
1726 info->attrs = method->flags;
1727 info->implattrs = method->iflags;
1728 if (sig->call_convention == MONO_CALL_DEFAULT)
1729 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1731 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1736 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1739 ICALL_EXPORT MonoArray*
1740 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1743 MonoDomain *domain = mono_domain_get ();
1745 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1746 mono_error_set_pending_exception (&error);
1750 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1751 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1754 MonoDomain *domain = mono_domain_get ();
1755 MonoReflectionMarshalAsAttribute* res = NULL;
1756 MonoMarshalSpec **mspecs;
1759 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1760 mono_method_get_marshal_info (method, mspecs);
1763 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1764 if (!mono_error_ok (&error)) {
1765 mono_error_set_pending_exception (&error);
1770 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1772 mono_metadata_free_marshal_spec (mspecs [i]);
1779 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1781 MonoClass *parent = field->field->parent;
1782 if (!parent->size_inited)
1783 mono_class_init (parent);
1784 mono_class_setup_fields_locking (parent);
1786 return field->field->offset - sizeof (MonoObject);
1789 ICALL_EXPORT MonoReflectionType*
1790 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1793 MonoReflectionType *ret;
1796 parent = declaring? field->field->parent: field->klass;
1798 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1799 mono_error_raise_exception (&error);
1805 ICALL_EXPORT MonoObject *
1806 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1808 MonoClass *fklass = field->klass;
1809 MonoClassField *cf = field->field;
1810 MonoDomain *domain = mono_object_domain (field);
1812 if (fklass->image->assembly->ref_only) {
1813 mono_set_pending_exception (mono_get_exception_invalid_operation (
1814 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1818 if (mono_security_core_clr_enabled ())
1819 mono_security_core_clr_ensure_reflection_access_field (cf);
1821 return mono_field_get_value_object (domain, cf, obj);
1825 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1828 MonoClassField *cf = field->field;
1832 if (field->klass->image->assembly->ref_only) {
1833 mono_set_pending_exception (mono_get_exception_invalid_operation (
1834 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1838 if (mono_security_core_clr_enabled ())
1839 mono_security_core_clr_ensure_reflection_access_field (cf);
1841 type = mono_field_get_type_checked (cf, &error);
1842 if (!mono_error_ok (&error)) {
1843 mono_error_set_pending_exception (&error);
1847 v = (gchar *) value;
1849 switch (type->type) {
1852 case MONO_TYPE_BOOLEAN:
1855 case MONO_TYPE_CHAR:
1864 case MONO_TYPE_VALUETYPE:
1867 v += sizeof (MonoObject);
1869 case MONO_TYPE_STRING:
1870 case MONO_TYPE_OBJECT:
1871 case MONO_TYPE_CLASS:
1872 case MONO_TYPE_ARRAY:
1873 case MONO_TYPE_SZARRAY:
1876 case MONO_TYPE_GENERICINST: {
1877 MonoGenericClass *gclass = type->data.generic_class;
1878 g_assert (!gclass->context.class_inst->is_open);
1880 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1881 MonoClass *nklass = mono_class_from_mono_type (type);
1882 MonoObject *nullable;
1885 * Convert the boxed vtype into a Nullable structure.
1886 * This is complicated by the fact that Nullables have
1887 * a variable structure.
1889 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1890 if (!mono_error_ok (&error)) {
1891 mono_error_set_pending_exception (&error);
1895 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1897 v = (gchar *)mono_object_unbox (nullable);
1900 if (gclass->container_class->valuetype && (v != NULL))
1901 v += sizeof (MonoObject);
1905 g_error ("type 0x%x not handled in "
1906 "ves_icall_FieldInfo_SetValueInternal", type->type);
1911 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1912 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
1913 if (!is_ok (&error)) {
1914 mono_error_set_pending_exception (&error);
1917 if (!vtable->initialized) {
1918 if (!mono_runtime_class_init_full (vtable, &error)) {
1919 mono_error_set_pending_exception (&error);
1923 mono_field_static_set_value (vtable, cf, v);
1925 mono_field_set_value (obj, cf, v);
1930 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1939 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1940 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1944 if (MONO_TYPE_IS_REFERENCE (f->type))
1945 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1947 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1950 ICALL_EXPORT MonoObject *
1951 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1953 MonoObject *o = NULL;
1954 MonoClassField *field = rfield->field;
1956 MonoDomain *domain = mono_object_domain (rfield);
1958 MonoTypeEnum def_type;
1959 const char *def_value;
1963 mono_class_init (field->parent);
1965 t = mono_field_get_type_checked (field, &error);
1966 if (!mono_error_ok (&error)) {
1967 mono_error_set_pending_exception (&error);
1971 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
1972 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1976 if (image_is_dynamic (field->parent->image)) {
1977 MonoClass *klass = field->parent;
1978 int fidx = field - klass->fields;
1980 g_assert (fidx >= 0 && fidx < klass->field.count);
1981 g_assert (klass->ext);
1982 g_assert (klass->ext->field_def_values);
1983 def_type = klass->ext->field_def_values [fidx].def_type;
1984 def_value = klass->ext->field_def_values [fidx].data;
1985 if (def_type == MONO_TYPE_END) {
1986 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1990 def_value = mono_class_get_field_default_value (field, &def_type);
1991 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
1993 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1998 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2002 case MONO_TYPE_BOOLEAN:
2005 case MONO_TYPE_CHAR:
2013 case MONO_TYPE_R8: {
2016 /* boxed value type */
2017 t = g_new0 (MonoType, 1);
2019 klass = mono_class_from_mono_type (t);
2021 o = mono_object_new_checked (domain, klass, &error);
2022 if (!mono_error_ok (&error)) {
2023 mono_error_set_pending_exception (&error);
2026 v = ((gchar *) o) + sizeof (MonoObject);
2027 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2030 case MONO_TYPE_STRING:
2031 case MONO_TYPE_CLASS:
2032 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2035 g_assert_not_reached ();
2041 ICALL_EXPORT MonoReflectionType*
2042 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2045 MonoReflectionType *ret;
2048 type = mono_field_get_type_checked (ref_field->field, &error);
2049 if (!mono_error_ok (&error)) {
2050 mono_error_set_pending_exception (&error);
2054 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2055 if (!mono_error_ok (&error)) {
2056 mono_error_set_pending_exception (&error);
2063 /* From MonoProperty.cs */
2065 PInfo_Attributes = 1,
2066 PInfo_GetMethod = 1 << 1,
2067 PInfo_SetMethod = 1 << 2,
2068 PInfo_ReflectedType = 1 << 3,
2069 PInfo_DeclaringType = 1 << 4,
2074 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2077 MonoReflectionType *rt;
2078 MonoReflectionMethod *rm;
2079 MonoDomain *domain = mono_object_domain (property);
2080 const MonoProperty *pproperty = property->property;
2082 if ((req_info & PInfo_ReflectedType) != 0) {
2083 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2084 mono_error_raise_exception (&error);
2086 MONO_STRUCT_SETREF (info, parent, rt);
2088 if ((req_info & PInfo_DeclaringType) != 0) {
2089 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2090 mono_error_raise_exception (&error);
2092 MONO_STRUCT_SETREF (info, declaring_type, rt);
2095 if ((req_info & PInfo_Name) != 0)
2096 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2098 if ((req_info & PInfo_Attributes) != 0)
2099 info->attrs = pproperty->attrs;
2101 if ((req_info & PInfo_GetMethod) != 0) {
2102 if (pproperty->get &&
2103 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2104 pproperty->get->klass == property->klass)) {
2105 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2106 mono_error_raise_exception (&error);
2111 MONO_STRUCT_SETREF (info, get, rm);
2113 if ((req_info & PInfo_SetMethod) != 0) {
2114 if (pproperty->set &&
2115 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2116 pproperty->set->klass == property->klass)) {
2117 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2118 mono_error_raise_exception (&error);
2123 MONO_STRUCT_SETREF (info, set, rm);
2126 * There may be other methods defined for properties, though, it seems they are not exposed
2127 * in the reflection API
2132 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2135 MonoReflectionType *rt;
2136 MonoReflectionMethod *rm;
2137 MonoDomain *domain = mono_object_domain (event);
2139 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2140 mono_error_raise_exception (&error);
2142 MONO_STRUCT_SETREF (info, reflected_type, rt);
2144 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2145 mono_error_raise_exception (&error);
2147 MONO_STRUCT_SETREF (info, declaring_type, rt);
2149 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2150 info->attrs = event->event->attrs;
2152 if (event->event->add) {
2153 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2154 mono_error_raise_exception (&error);
2159 MONO_STRUCT_SETREF (info, add_method, rm);
2161 if (event->event->remove) {
2162 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2163 mono_error_raise_exception (&error);
2168 MONO_STRUCT_SETREF (info, remove_method, rm);
2170 if (event->event->raise) {
2171 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2172 mono_error_raise_exception (&error);
2177 MONO_STRUCT_SETREF (info, raise_method, rm);
2179 #ifndef MONO_SMALL_CONFIG
2180 if (event->event->other) {
2182 while (event->event->other [n])
2184 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2186 for (i = 0; i < n; i++) {
2187 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2188 mono_error_raise_exception (&error);
2189 mono_array_setref (info->other_methods, i, rm);
2196 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2201 mono_class_setup_interfaces (klass, error);
2202 if (!mono_error_ok (error))
2205 for (i = 0; i < klass->interface_count; i++) {
2206 ic = klass->interfaces [i];
2207 g_hash_table_insert (ifaces, ic, ic);
2209 collect_interfaces (ic, ifaces, error);
2210 if (!mono_error_ok (error))
2216 MonoArray *iface_array;
2217 MonoGenericContext *context;
2221 } FillIfaceArrayData;
2224 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2226 MonoReflectionType *rt;
2227 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2228 MonoClass *ic = (MonoClass *)key;
2229 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2231 if (!mono_error_ok (data->error))
2234 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2235 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2236 if (!mono_error_ok (data->error))
2240 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2241 if (!mono_error_ok (data->error))
2244 mono_array_setref (data->iface_array, data->next_idx++, rt);
2247 mono_metadata_free_type (inflated);
2251 get_interfaces_hash (gconstpointer v1)
2253 MonoClass *k = (MonoClass*)v1;
2255 return k->type_token;
2258 ICALL_EXPORT MonoArray*
2259 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2262 MonoClass *klass = mono_class_from_mono_type (type->type);
2264 FillIfaceArrayData data = { 0 };
2267 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2269 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2270 data.context = mono_class_get_context (klass);
2271 klass = klass->generic_class->container_class;
2274 for (parent = klass; parent; parent = parent->parent) {
2275 mono_class_setup_interfaces (parent, &error);
2276 if (!mono_error_ok (&error))
2278 collect_interfaces (parent, iface_hash, &error);
2279 if (!mono_error_ok (&error))
2283 data.error = &error;
2284 data.domain = mono_object_domain (type);
2286 len = g_hash_table_size (iface_hash);
2288 g_hash_table_destroy (iface_hash);
2289 if (!data.domain->empty_types)
2290 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2291 return data.domain->empty_types;
2294 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2295 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2296 if (!mono_error_ok (&error))
2299 g_hash_table_destroy (iface_hash);
2300 return data.iface_array;
2303 g_hash_table_destroy (iface_hash);
2304 mono_error_set_pending_exception (&error);
2309 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2311 gboolean variance_used;
2312 MonoClass *klass = mono_class_from_mono_type (type->type);
2313 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2314 MonoReflectionMethod *member;
2317 int i = 0, len, ioffset;
2321 mono_class_init_checked (klass, &error);
2322 mono_error_raise_exception (&error);
2323 mono_class_init_checked (iclass, &error);
2324 mono_error_raise_exception (&error);
2326 mono_class_setup_vtable (klass);
2328 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2332 len = mono_class_num_methods (iclass);
2333 domain = mono_object_domain (type);
2334 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2335 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2337 while ((method = mono_class_get_methods (iclass, &iter))) {
2338 member = mono_method_get_object_checked (domain, method, iclass, &error);
2339 mono_error_raise_exception (&error);
2340 mono_array_setref (*methods, i, member);
2341 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2342 mono_error_raise_exception (&error);
2343 mono_array_setref (*targets, i, member);
2350 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2353 MonoClass *klass = mono_class_from_mono_type (type->type);
2355 mono_class_init_checked (klass, &error);
2356 mono_error_raise_exception (&error);
2358 if (image_is_dynamic (klass->image)) {
2359 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2360 *packing = tb->packing_size;
2361 *size = tb->class_size;
2363 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2367 ICALL_EXPORT MonoReflectionType*
2368 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2371 MonoReflectionType *ret;
2374 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2375 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2376 mono_error_raise_exception (&error);
2381 klass = mono_class_from_mono_type (type->type);
2382 mono_class_init_checked (klass, &error);
2383 mono_error_raise_exception (&error);
2385 // GetElementType should only return a type for:
2386 // Array Pointer PassedByRef
2387 if (type->type->byref)
2388 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2389 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2390 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2391 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2392 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2396 mono_error_raise_exception (&error);
2401 ICALL_EXPORT MonoReflectionType*
2402 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2405 MonoReflectionType *ret;
2407 if (type->type->byref)
2410 MonoClass *klass = mono_class_from_mono_type (type->type);
2414 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2415 mono_error_raise_exception (&error);
2420 ICALL_EXPORT MonoBoolean
2421 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2423 return type->type->type == MONO_TYPE_PTR;
2426 ICALL_EXPORT MonoBoolean
2427 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2429 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)));
2432 ICALL_EXPORT MonoBoolean
2433 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2435 return type->type->byref;
2438 ICALL_EXPORT MonoBoolean
2439 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2442 MonoClass *klass = mono_class_from_mono_type (type->type);
2443 mono_class_init_checked (klass, &error);
2444 mono_error_raise_exception (&error);
2446 return mono_class_is_com_object (klass);
2449 ICALL_EXPORT guint32
2450 ves_icall_RuntimeTypeHandle_GetMetadataToken (MonoReflectionType *obj)
2452 return mono_reflection_get_token ((MonoObject*)obj);
2455 ICALL_EXPORT MonoReflectionModule*
2456 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2459 MonoReflectionModule *result = NULL;
2460 MonoClass *klass = mono_class_from_mono_type (type->type);
2461 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2462 if (!mono_error_ok (&error))
2463 mono_error_set_pending_exception (&error);
2467 ICALL_EXPORT MonoReflectionAssembly*
2468 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2471 MonoDomain *domain = mono_domain_get ();
2472 MonoClass *klass = mono_class_from_mono_type (type->type);
2473 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2475 mono_error_set_pending_exception (&error);
2479 ICALL_EXPORT MonoReflectionType*
2480 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2483 MonoReflectionType *ret;
2484 MonoDomain *domain = mono_domain_get ();
2487 if (type->type->byref)
2489 if (type->type->type == MONO_TYPE_VAR) {
2490 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2491 klass = param ? param->owner.klass : NULL;
2492 } else if (type->type->type == MONO_TYPE_MVAR) {
2493 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2494 klass = param ? param->owner.method->klass : NULL;
2496 klass = mono_class_from_mono_type (type->type)->nested_in;
2502 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2503 mono_error_raise_exception (&error);
2508 ICALL_EXPORT MonoString*
2509 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2511 MonoDomain *domain = mono_domain_get ();
2512 MonoClass *klass = mono_class_from_mono_type (type->type);
2514 if (type->type->byref) {
2515 char *n = g_strdup_printf ("%s&", klass->name);
2516 MonoString *res = mono_string_new (domain, n);
2522 return mono_string_new (domain, klass->name);
2526 ICALL_EXPORT MonoString*
2527 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2529 MonoDomain *domain = mono_domain_get ();
2530 MonoClass *klass = mono_class_from_mono_type (type->type);
2532 while (klass->nested_in)
2533 klass = klass->nested_in;
2535 if (klass->name_space [0] == '\0')
2538 return mono_string_new (domain, klass->name_space);
2542 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2546 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2547 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2551 klass = mono_class_from_mono_type (type->type);
2557 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2560 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2564 ICALL_EXPORT MonoArray*
2565 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2568 MonoReflectionType *rt;
2570 MonoClass *klass, *pklass;
2571 MonoDomain *domain = mono_object_domain (type);
2574 klass = mono_class_from_mono_type (type->type);
2576 if (klass->generic_container) {
2577 MonoGenericContainer *container = klass->generic_container;
2578 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2579 for (i = 0; i < container->type_argc; ++i) {
2580 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2582 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2583 mono_error_raise_exception (&error);
2585 mono_array_setref (res, i, rt);
2587 } else if (klass->generic_class) {
2588 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2589 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2590 for (i = 0; i < inst->type_argc; ++i) {
2591 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2592 mono_error_raise_exception (&error);
2594 mono_array_setref (res, i, rt);
2602 ICALL_EXPORT gboolean
2603 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2607 if (!IS_MONOTYPE (type))
2610 if (type->type->byref)
2613 klass = mono_class_from_mono_type (type->type);
2614 return klass->generic_container != NULL;
2617 ICALL_EXPORT MonoReflectionType*
2618 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2621 MonoReflectionType *ret;
2624 if (type->type->byref)
2627 klass = mono_class_from_mono_type (type->type);
2629 if (klass->generic_container) {
2630 return type; /* check this one */
2632 if (klass->generic_class) {
2633 MonoClass *generic_class = klass->generic_class->container_class;
2636 tb = mono_class_get_ref_info (generic_class);
2638 if (generic_class->wastypebuilder && tb)
2639 return (MonoReflectionType *)tb;
2641 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2642 mono_error_raise_exception (&error);
2650 ICALL_EXPORT MonoReflectionType*
2651 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2654 MonoReflectionType *ret;
2656 MonoType *geninst, **types;
2659 g_assert (IS_MONOTYPE (type));
2660 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2661 mono_error_raise_exception (&error);
2663 count = mono_array_length (type_array);
2664 types = g_new0 (MonoType *, count);
2666 for (i = 0; i < count; i++) {
2667 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2668 types [i] = t->type;
2671 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2676 klass = mono_class_from_mono_type (geninst);
2678 /*we might inflate to the GTD*/
2679 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2680 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2684 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2685 mono_error_raise_exception (&error);
2690 ICALL_EXPORT gboolean
2691 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2695 if (!IS_MONOTYPE (type))
2698 if (type->type->byref)
2701 klass = mono_class_from_mono_type (type->type);
2702 return klass->generic_class != NULL || klass->generic_container != NULL;
2706 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2708 if (!IS_MONOTYPE (type))
2711 if (is_generic_parameter (type->type))
2712 return mono_type_get_generic_param_num (type->type);
2716 ICALL_EXPORT GenericParameterAttributes
2717 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2719 g_assert (IS_MONOTYPE (type));
2720 g_assert (is_generic_parameter (type->type));
2721 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2724 ICALL_EXPORT MonoArray *
2725 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2728 MonoReflectionType *rt;
2729 MonoGenericParamInfo *param_info;
2735 g_assert (IS_MONOTYPE (type));
2737 domain = mono_object_domain (type);
2738 param_info = mono_generic_param_info (type->type->data.generic_param);
2739 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2742 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2743 for (i = 0; i < count; i++) {
2744 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2745 mono_error_raise_exception (&error);
2747 mono_array_setref (res, i, rt);
2754 ICALL_EXPORT MonoBoolean
2755 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2757 return is_generic_parameter (type->type);
2760 ICALL_EXPORT MonoBoolean
2761 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2763 return is_generic_parameter (tb->type.type);
2767 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2768 MonoReflectionType *t)
2770 enumtype->type = t->type;
2773 ICALL_EXPORT MonoReflectionMethod*
2774 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2775 MonoReflectionMethod* generic)
2782 MonoReflectionMethod *ret = NULL;
2784 domain = ((MonoObject *)type)->vtable->domain;
2786 klass = mono_class_from_mono_type (type->type);
2787 mono_class_init_checked (klass, &error);
2788 mono_error_raise_exception (&error);
2791 while ((method = mono_class_get_methods (klass, &iter))) {
2792 if (method->token == generic->method->token) {
2793 ret = mono_method_get_object_checked (domain, method, klass, &error);
2794 mono_error_raise_exception (&error);
2801 ICALL_EXPORT MonoReflectionMethod *
2802 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2805 MonoType *type = ref_type->type;
2807 MonoReflectionMethod *ret = NULL;
2809 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2810 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2813 if (type->type == MONO_TYPE_VAR)
2816 method = mono_type_get_generic_param_owner (type)->owner.method;
2819 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2820 if (!mono_error_ok (&error))
2821 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2825 ICALL_EXPORT MonoBoolean
2826 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2828 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2832 ICALL_EXPORT MonoBoolean
2833 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2835 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2840 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2842 MonoDomain *domain = mono_domain_get ();
2843 MonoImage *image = method->method->klass->image;
2844 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2845 MonoTableInfo *tables = image->tables;
2846 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2847 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2848 guint32 im_cols [MONO_IMPLMAP_SIZE];
2849 guint32 scope_token;
2850 const char *import = NULL;
2851 const char *scope = NULL;
2853 if (image_is_dynamic (image)) {
2854 MonoReflectionMethodAux *method_aux =
2855 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2857 import = method_aux->dllentry;
2858 scope = method_aux->dll;
2861 if (!import || !scope) {
2862 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2867 if (piinfo->implmap_idx) {
2868 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2870 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2871 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2872 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2873 scope = mono_metadata_string_heap (image, scope_token);
2877 *flags = piinfo->piflags;
2878 *entry_point = mono_string_new (domain, import);
2879 *dll_name = mono_string_new (domain, scope);
2882 ICALL_EXPORT MonoReflectionMethod *
2883 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2885 MonoMethodInflated *imethod;
2887 MonoReflectionMethod *ret = NULL;
2890 if (method->method->is_generic)
2893 if (!method->method->is_inflated)
2896 imethod = (MonoMethodInflated *) method->method;
2898 result = imethod->declaring;
2899 /* Not a generic method. */
2900 if (!result->is_generic)
2903 if (image_is_dynamic (method->method->klass->image)) {
2904 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2905 MonoReflectionMethod *res;
2908 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2909 * the dynamic case as well ?
2911 mono_image_lock ((MonoImage*)image);
2912 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2913 mono_image_unlock ((MonoImage*)image);
2919 if (imethod->context.class_inst) {
2920 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2921 /*Generic methods gets the context of the GTD.*/
2922 if (mono_class_get_context (klass)) {
2923 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2924 if (!mono_error_ok (&error))
2929 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2931 if (!mono_error_ok (&error))
2932 mono_error_set_pending_exception (&error);
2936 ICALL_EXPORT gboolean
2937 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2939 return mono_method_signature (method->method)->generic_param_count != 0;
2942 ICALL_EXPORT gboolean
2943 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2945 return method->method->is_generic;
2948 ICALL_EXPORT MonoArray*
2949 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2952 MonoReflectionType *rt;
2957 domain = mono_object_domain (method);
2959 if (method->method->is_inflated) {
2960 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2963 count = inst->type_argc;
2964 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2966 for (i = 0; i < count; i++) {
2967 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2968 mono_error_raise_exception (&error);
2970 mono_array_setref (res, i, rt);
2977 count = mono_method_signature (method->method)->generic_param_count;
2978 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2980 for (i = 0; i < count; i++) {
2981 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2982 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2983 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
2985 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2986 mono_error_raise_exception (&error);
2988 mono_array_setref (res, i, rt);
2994 ICALL_EXPORT MonoObject *
2995 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
2999 * Invoke from reflection is supposed to always be a virtual call (the API
3000 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3001 * greater flexibility.
3003 MonoMethod *m = method->method;
3004 MonoMethodSignature *sig = mono_method_signature (m);
3007 void *obj = this_arg;
3011 if (mono_security_core_clr_enabled ())
3012 mono_security_core_clr_ensure_reflection_access_method (m);
3014 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3015 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3016 mono_error_cleanup (&error); /* FIXME does this make sense? */
3017 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3022 if (!mono_object_isinst (this_arg, m->klass)) {
3023 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3024 char *target_name = mono_type_get_full_name (m->klass);
3025 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3026 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3028 g_free (target_name);
3032 m = mono_object_get_virtual_method (this_arg, m);
3033 /* must pass the pointer to the value for valuetype methods */
3034 if (m->klass->valuetype)
3035 obj = mono_object_unbox (this_arg);
3036 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3037 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3042 if (sig->ret->byref) {
3043 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"));
3047 pcount = params? mono_array_length (params): 0;
3048 if (pcount != sig->param_count) {
3049 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3053 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3054 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."));
3058 image = m->klass->image;
3059 if (image->assembly->ref_only) {
3060 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."));
3064 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3065 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3069 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3073 intptr_t *lower_bounds;
3074 pcount = mono_array_length (params);
3075 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3076 /* Note: the synthetized array .ctors have int32 as argument type */
3077 for (i = 0; i < pcount; ++i)
3078 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3080 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3081 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3082 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3083 if (!mono_error_ok (&error)) {
3084 mono_error_set_pending_exception (&error);
3088 for (i = 0; i < mono_array_length (arr); ++i) {
3089 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3090 if (!mono_error_ok (&error)) {
3091 mono_error_set_pending_exception (&error);
3094 mono_array_setref_fast (arr, i, subarray);
3096 return (MonoObject*)arr;
3099 if (m->klass->rank == pcount) {
3100 /* Only lengths provided. */
3101 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3102 if (!mono_error_ok (&error)) {
3103 mono_error_set_pending_exception (&error);
3107 return (MonoObject*)arr;
3109 g_assert (pcount == (m->klass->rank * 2));
3110 /* The arguments are lower-bound-length pairs */
3111 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3113 for (i = 0; i < pcount / 2; ++i) {
3114 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3115 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3118 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3119 if (!mono_error_ok (&error)) {
3120 mono_error_set_pending_exception (&error);
3124 return (MonoObject*)arr;
3127 return mono_runtime_invoke_array (m, obj, params, NULL);
3130 #ifndef DISABLE_REMOTING
3131 ICALL_EXPORT MonoObject *
3132 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3134 MonoDomain *domain = mono_object_domain (method);
3135 MonoMethod *m = method->method;
3136 MonoMethodSignature *sig = mono_method_signature (m);
3137 MonoArray *out_args;
3139 int i, j, outarg_count = 0;
3141 if (m->klass == mono_defaults.object_class) {
3142 if (!strcmp (m->name, "FieldGetter")) {
3143 MonoClass *k = this_arg->vtable->klass;
3147 /* If this is a proxy, then it must be a CBO */
3148 if (k == mono_defaults.transparent_proxy_class) {
3149 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3150 this_arg = tp->rp->unwrapped_server;
3151 g_assert (this_arg);
3152 k = this_arg->vtable->klass;
3155 name = mono_array_get (params, MonoString *, 1);
3156 str = mono_string_to_utf8 (name);
3159 MonoClassField* field = mono_class_get_field_from_name (k, str);
3161 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3162 if (field_klass->valuetype)
3163 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
3165 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3167 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3168 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3169 mono_array_setref (out_args, 0, result);
3177 g_assert_not_reached ();
3179 } else if (!strcmp (m->name, "FieldSetter")) {
3180 MonoClass *k = this_arg->vtable->klass;
3186 /* If this is a proxy, then it must be a CBO */
3187 if (k == mono_defaults.transparent_proxy_class) {
3188 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3189 this_arg = tp->rp->unwrapped_server;
3190 g_assert (this_arg);
3191 k = this_arg->vtable->klass;
3194 name = mono_array_get (params, MonoString *, 1);
3195 str = mono_string_to_utf8 (name);
3198 MonoClassField* field = mono_class_get_field_from_name (k, str);
3200 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3201 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3203 if (field_klass->valuetype) {
3204 size = mono_type_size (field->type, &align);
3205 g_assert (size == mono_class_value_size (field_klass, NULL));
3206 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3208 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3211 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3212 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3222 g_assert_not_reached ();
3227 for (i = 0; i < mono_array_length (params); i++) {
3228 if (sig->params [i]->byref)
3232 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3234 /* handle constructors only for objects already allocated */
3235 if (!strcmp (method->method->name, ".ctor"))
3236 g_assert (this_arg);
3238 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3239 g_assert (!method->method->klass->valuetype);
3240 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3242 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3243 if (sig->params [i]->byref) {
3245 arg = mono_array_get (params, gpointer, i);
3246 mono_array_setref (out_args, j, arg);
3251 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3258 read_enum_value (const char *mem, int type)
3261 case MONO_TYPE_BOOLEAN:
3263 return *(guint8*)mem;
3265 return *(gint8*)mem;
3266 case MONO_TYPE_CHAR:
3268 return read16 (mem);
3270 return (gint16) read16 (mem);
3272 return read32 (mem);
3274 return (gint32) read32 (mem);
3277 return read64 (mem);
3279 g_assert_not_reached ();
3285 write_enum_value (char *mem, int type, guint64 value)
3289 case MONO_TYPE_I1: {
3290 guint8 *p = (guint8*)mem;
3295 case MONO_TYPE_I2: {
3296 guint16 *p = (guint16 *)mem;
3301 case MONO_TYPE_I4: {
3302 guint32 *p = (guint32 *)mem;
3307 case MONO_TYPE_I8: {
3308 guint64 *p = (guint64 *)mem;
3313 g_assert_not_reached ();
3318 ICALL_EXPORT MonoObject *
3319 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3327 domain = mono_object_domain (enumType);
3328 enumc = mono_class_from_mono_type (enumType->type);
3330 mono_class_init_checked (enumc, &error);
3331 mono_error_raise_exception (&error);
3333 etype = mono_class_enum_basetype (enumc);
3335 res = mono_object_new_checked (domain, enumc, &error);
3336 mono_error_raise_exception (&error);
3337 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3342 ICALL_EXPORT MonoBoolean
3343 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3345 int size = mono_class_value_size (a->vtable->klass, NULL);
3346 guint64 a_val = 0, b_val = 0;
3348 memcpy (&a_val, mono_object_unbox (a), size);
3349 memcpy (&b_val, mono_object_unbox (b), size);
3351 return (a_val & b_val) == b_val;
3354 ICALL_EXPORT MonoObject *
3355 ves_icall_System_Enum_get_value (MonoObject *eobj)
3367 g_assert (eobj->vtable->klass->enumtype);
3369 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3370 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3371 mono_error_raise_exception (&error);
3372 dst = (char *)res + sizeof (MonoObject);
3373 src = (char *)eobj + sizeof (MonoObject);
3374 size = mono_class_value_size (enumc, NULL);
3376 memcpy (dst, src, size);
3381 ICALL_EXPORT MonoReflectionType *
3382 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3385 MonoReflectionType *ret;
3389 klass = mono_class_from_mono_type (type->type);
3390 mono_class_init_checked (klass, &error);
3391 mono_error_raise_exception (&error);
3393 etype = mono_class_enum_basetype (klass);
3395 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3399 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3400 mono_error_raise_exception (&error);
3406 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3408 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3409 gpointer odata = (char *)other + sizeof (MonoObject);
3410 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3411 g_assert (basetype);
3416 if (eobj->vtable->klass != other->vtable->klass)
3419 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3420 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3421 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3424 return me > other ? 1 : -1; \
3427 switch (basetype->type) {
3429 COMPARE_ENUM_VALUES (guint8);
3431 COMPARE_ENUM_VALUES (gint8);
3432 case MONO_TYPE_CHAR:
3434 COMPARE_ENUM_VALUES (guint16);
3436 COMPARE_ENUM_VALUES (gint16);
3438 COMPARE_ENUM_VALUES (guint32);
3440 COMPARE_ENUM_VALUES (gint32);
3442 COMPARE_ENUM_VALUES (guint64);
3444 COMPARE_ENUM_VALUES (gint64);
3448 #undef COMPARE_ENUM_VALUES
3449 /* indicates that the enum was of an unsupported unerlying type */
3454 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3456 gpointer data = (char *)eobj + sizeof (MonoObject);
3457 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3458 g_assert (basetype);
3460 switch (basetype->type) {
3461 case MONO_TYPE_I1: {
3462 gint8 value = *((gint8*)data);
3463 return ((int)value ^ (int)value << 8);
3466 return *((guint8*)data);
3467 case MONO_TYPE_CHAR:
3469 return *((guint16*)data);
3471 case MONO_TYPE_I2: {
3472 gint16 value = *((gint16*)data);
3473 return ((int)(guint16)value | (((int)value) << 16));
3476 return *((guint32*)data);
3478 return *((gint32*)data);
3480 case MONO_TYPE_I8: {
3481 gint64 value = *((gint64*)data);
3482 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3485 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3490 ICALL_EXPORT MonoBoolean
3491 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3494 MonoDomain *domain = mono_object_domain (type);
3495 MonoClass *enumc = mono_class_from_mono_type (type->type);
3496 guint j = 0, nvalues;
3498 MonoClassField *field;
3500 guint64 field_value, previous_value = 0;
3501 gboolean sorted = TRUE;
3503 mono_class_init_checked (enumc, &error);
3504 mono_error_raise_exception (&error);
3506 if (!enumc->enumtype) {
3507 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3511 base_type = mono_class_enum_basetype (enumc)->type;
3513 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3514 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3515 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3518 while ((field = mono_class_get_fields (enumc, &iter))) {
3520 MonoTypeEnum def_type;
3522 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3524 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3526 if (mono_field_is_deleted (field))
3528 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3530 p = mono_class_get_field_default_value (field, &def_type);
3531 /* len = */ mono_metadata_decode_blob_size (p, &p);
3533 field_value = read_enum_value (p, base_type);
3534 mono_array_set (*values, guint64, j, field_value);
3536 if (previous_value > field_value)
3539 previous_value = field_value;
3547 BFLAGS_IgnoreCase = 1,
3548 BFLAGS_DeclaredOnly = 2,
3549 BFLAGS_Instance = 4,
3551 BFLAGS_Public = 0x10,
3552 BFLAGS_NonPublic = 0x20,
3553 BFLAGS_FlattenHierarchy = 0x40,
3554 BFLAGS_InvokeMethod = 0x100,
3555 BFLAGS_CreateInstance = 0x200,
3556 BFLAGS_GetField = 0x400,
3557 BFLAGS_SetField = 0x800,
3558 BFLAGS_GetProperty = 0x1000,
3559 BFLAGS_SetProperty = 0x2000,
3560 BFLAGS_ExactBinding = 0x10000,
3561 BFLAGS_SuppressChangeType = 0x20000,
3562 BFLAGS_OptionalParamBinding = 0x40000
3565 ICALL_EXPORT MonoArray*
3566 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3570 MonoClass *startklass, *klass, *refklass;
3575 char *utf8_name = NULL;
3576 int (*compare_func) (const char *s1, const char *s2) = NULL;
3577 MonoClassField *field;
3578 MonoPtrArray tmp_array;
3580 domain = ((MonoObject *)type)->vtable->domain;
3581 if (type->type->byref)
3582 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3584 klass = startklass = mono_class_from_mono_type (type->type);
3585 refklass = mono_class_from_mono_type (reftype->type);
3587 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3590 if (mono_class_has_failure (klass)) {
3591 mono_ptr_array_destroy (tmp_array);
3592 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3597 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3598 guint32 flags = mono_field_get_flags (field);
3600 if (mono_field_is_deleted_with_flags (field, flags))
3602 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3603 if (bflags & BFLAGS_Public)
3605 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3606 if (bflags & BFLAGS_NonPublic) {
3613 if (flags & FIELD_ATTRIBUTE_STATIC) {
3614 if (bflags & BFLAGS_Static)
3615 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3618 if (bflags & BFLAGS_Instance)
3626 if (utf8_name == NULL) {
3627 utf8_name = mono_string_to_utf8 (name);
3628 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3631 if (compare_func (mono_field_get_name (field), utf8_name))
3635 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3636 if (!mono_error_ok (&error))
3638 mono_ptr_array_append (tmp_array, member);
3640 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3643 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3645 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3646 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3648 mono_ptr_array_destroy (tmp_array);
3650 if (utf8_name != NULL)
3655 mono_ptr_array_destroy (tmp_array);
3656 mono_error_raise_exception (&error);
3657 g_assert_not_reached ();
3661 method_nonpublic (MonoMethod* method, gboolean start_klass)
3663 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3664 case METHOD_ATTRIBUTE_ASSEM:
3665 return (start_klass || mono_defaults.generic_ilist_class);
3666 case METHOD_ATTRIBUTE_PRIVATE:
3668 case METHOD_ATTRIBUTE_PUBLIC:
3676 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3679 MonoClass *startklass;
3683 /*FIXME, use MonoBitSet*/
3684 guint32 method_slots_default [8];
3685 guint32 *method_slots = NULL;
3686 int (*compare_func) (const char *s1, const char *s2) = NULL;
3688 array = g_ptr_array_new ();
3693 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3695 /* An optimization for calls made from Delegate:CreateDelegate () */
3696 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3697 method = mono_get_delegate_invoke (klass);
3698 if (mono_loader_get_last_error ())
3701 g_ptr_array_add (array, method);
3705 mono_class_setup_methods (klass);
3706 mono_class_setup_vtable (klass);
3707 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3710 if (is_generic_parameter (&klass->byval_arg))
3711 nslots = mono_class_get_vtable_size (klass->parent);
3713 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3714 if (nslots >= sizeof (method_slots_default) * 8) {
3715 method_slots = g_new0 (guint32, nslots / 32 + 1);
3717 method_slots = method_slots_default;
3718 memset (method_slots, 0, sizeof (method_slots_default));
3721 mono_class_setup_methods (klass);
3722 mono_class_setup_vtable (klass);
3723 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3727 while ((method = mono_class_get_methods (klass, &iter))) {
3729 if (method->slot != -1) {
3730 g_assert (method->slot < nslots);
3731 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3733 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3734 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3737 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3739 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3740 if (bflags & BFLAGS_Public)
3742 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3748 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3749 if (bflags & BFLAGS_Static)
3750 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3753 if (bflags & BFLAGS_Instance)
3761 if (compare_func (name, method->name))
3766 g_ptr_array_add (array, method);
3768 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3770 if (method_slots != method_slots_default)
3771 g_free (method_slots);
3776 if (method_slots != method_slots_default)
3777 g_free (method_slots);
3778 g_ptr_array_free (array, TRUE);
3780 if (mono_class_has_failure (klass)) {
3781 *ex = mono_class_get_exception_for_failure (klass);
3783 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3784 mono_loader_clear_error ();
3789 ICALL_EXPORT MonoArray*
3790 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3792 static MonoClass *MethodInfo_array;
3796 MonoVTable *array_vtable;
3797 MonoException *ex = NULL;
3798 const char *mname = NULL;
3799 GPtrArray *method_array;
3800 MonoClass *klass, *refklass;
3803 mono_error_init (&error);
3805 if (!MethodInfo_array) {
3806 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3807 mono_memory_barrier ();
3808 MethodInfo_array = klass;
3811 klass = mono_class_from_mono_type (type->type);
3812 refklass = mono_class_from_mono_type (reftype->type);
3813 domain = ((MonoObject *)type)->vtable->domain;
3814 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3815 if (!is_ok (&error)) {
3816 mono_error_set_pending_exception (&error);
3819 if (type->type->byref) {
3820 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3821 mono_error_set_pending_exception (&error);
3827 mname = mono_string_to_utf8 (name);
3829 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3830 g_free ((char*)mname);
3832 mono_set_pending_exception (ex);
3836 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3837 if (!mono_error_ok (&error)) {
3838 mono_error_set_pending_exception (&error);
3842 for (i = 0; i < method_array->len; ++i) {
3843 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3844 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3845 if (!mono_error_ok (&error))
3847 mono_array_setref (res, i, rm);
3851 g_ptr_array_free (method_array, TRUE);
3852 if (!mono_error_ok (&error))
3853 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3857 ICALL_EXPORT MonoArray*
3858 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3861 MonoClass *startklass, *klass, *refklass;
3866 gpointer iter = NULL;
3867 MonoPtrArray tmp_array;
3870 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3872 domain = ((MonoObject *)type)->vtable->domain;
3873 if (type->type->byref)
3874 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3875 klass = startklass = mono_class_from_mono_type (type->type);
3876 refklass = mono_class_from_mono_type (reftype->type);
3878 mono_class_setup_methods (klass);
3879 if (mono_class_has_failure (klass)) {
3880 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3885 while ((method = mono_class_get_methods (klass, &iter))) {
3887 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3889 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3890 if (bflags & BFLAGS_Public)
3893 if (bflags & BFLAGS_NonPublic)
3899 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3900 if (bflags & BFLAGS_Static)
3901 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3904 if (bflags & BFLAGS_Instance)
3910 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3911 if (!mono_error_ok (&error)) {
3912 mono_error_set_pending_exception (&error);
3916 mono_ptr_array_append (tmp_array, member);
3919 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
3921 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3922 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3924 mono_ptr_array_destroy (tmp_array);
3930 property_hash (gconstpointer data)
3932 MonoProperty *prop = (MonoProperty*)data;
3934 return g_str_hash (prop->name);
3938 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3940 if (method1->is_inflated)
3941 method1 = ((MonoMethodInflated*) method1)->declaring;
3942 if (method2->is_inflated)
3943 method2 = ((MonoMethodInflated*) method2)->declaring;
3945 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3949 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3951 // Properties are hide-by-name-and-signature
3952 if (!g_str_equal (prop1->name, prop2->name))
3955 /* If we see a property in a generic method, we want to
3956 compare the generic signatures, not the inflated signatures
3957 because we might conflate two properties that were
3961 public T this[T t] { getter { return t; } } // method 1
3962 public U this[U u] { getter { return u; } } // method 2
3965 If we see int Foo<int,int>::Item[int] we need to know if
3966 the indexer came from method 1 or from method 2, and we
3967 shouldn't conflate them. (Bugzilla 36283)
3969 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
3972 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
3979 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3984 return method_nonpublic (accessor, start_klass);
3987 ICALL_EXPORT MonoArray*
3988 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3992 MonoClass *startklass, *klass;
3998 gchar *propname = NULL;
3999 int (*compare_func) (const char *s1, const char *s2) = NULL;
4001 GHashTable *properties = NULL;
4002 MonoPtrArray tmp_array;
4004 mono_error_init (&error);
4006 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4008 domain = ((MonoObject *)type)->vtable->domain;
4009 if (type->type->byref)
4010 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
4011 klass = startklass = mono_class_from_mono_type (type->type);
4014 propname = mono_string_to_utf8 (name);
4015 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4018 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4020 mono_class_setup_methods (klass);
4021 mono_class_setup_vtable (klass);
4022 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4026 while ((prop = mono_class_get_properties (klass, &iter))) {
4032 flags = method->flags;
4035 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4036 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4037 if (bflags & BFLAGS_Public)
4039 } else if (bflags & BFLAGS_NonPublic) {
4040 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4041 property_accessor_nonpublic(prop->set, startklass == klass)) {
4048 if (flags & METHOD_ATTRIBUTE_STATIC) {
4049 if (bflags & BFLAGS_Static)
4050 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4053 if (bflags & BFLAGS_Instance)
4062 if (compare_func (propname, prop->name))
4066 if (g_hash_table_lookup (properties, prop))
4069 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4072 mono_ptr_array_append (tmp_array, pr);
4074 g_hash_table_insert (properties, prop, prop);
4076 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4079 g_hash_table_destroy (properties);
4082 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4083 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4084 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4086 mono_ptr_array_destroy (tmp_array);
4093 if (mono_class_has_failure (klass)) {
4094 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4096 mono_error_set_from_loader_error (&error);
4097 mono_loader_clear_error ();
4102 g_hash_table_destroy (properties);
4105 mono_ptr_array_destroy (tmp_array);
4107 mono_error_set_pending_exception (&error);
4113 event_hash (gconstpointer data)
4115 MonoEvent *event = (MonoEvent*)data;
4117 return g_str_hash (event->name);
4121 event_equal (MonoEvent *event1, MonoEvent *event2)
4123 // Events are hide-by-name
4124 return g_str_equal (event1->name, event2->name);
4127 ICALL_EXPORT MonoArray*
4128 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4132 MonoClass *startklass, *klass;
4138 char *utf8_name = NULL;
4139 int (*compare_func) (const char *s1, const char *s2) = NULL;
4140 GHashTable *events = NULL;
4141 MonoPtrArray tmp_array;
4143 mono_error_init (&error);
4145 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4147 domain = mono_object_domain (type);
4148 if (type->type->byref)
4149 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4150 klass = startklass = mono_class_from_mono_type (type->type);
4152 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4154 mono_class_setup_methods (klass);
4155 mono_class_setup_vtable (klass);
4156 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4160 while ((event = mono_class_get_events (klass, &iter))) {
4162 method = event->add;
4164 method = event->remove;
4166 method = event->raise;
4168 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4169 if (bflags & BFLAGS_Public)
4171 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4172 if (bflags & BFLAGS_NonPublic)
4177 if (bflags & BFLAGS_NonPublic)
4183 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4184 if (bflags & BFLAGS_Static)
4185 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4188 if (bflags & BFLAGS_Instance)
4193 if (bflags & BFLAGS_Instance)
4199 if (utf8_name == NULL) {
4200 utf8_name = mono_string_to_utf8 (name);
4201 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4204 if (compare_func (event->name, utf8_name))
4208 if (g_hash_table_lookup (events, event))
4211 MonoReflectionEvent *ev_obj;
4212 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4215 mono_ptr_array_append (tmp_array, ev_obj);
4217 g_hash_table_insert (events, event, event);
4219 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4222 g_hash_table_destroy (events);
4224 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4226 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4227 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4229 mono_ptr_array_destroy (tmp_array);
4231 if (utf8_name != NULL)
4237 if (mono_class_has_failure (klass)) {
4238 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4240 mono_error_set_from_loader_error (&error);
4241 mono_loader_clear_error ();
4247 g_hash_table_destroy (events);
4248 if (utf8_name != NULL)
4251 mono_ptr_array_destroy (tmp_array);
4253 mono_error_set_pending_exception (&error);
4257 ICALL_EXPORT MonoArray*
4258 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4261 MonoReflectionType *rt;
4269 MonoPtrArray tmp_array;
4271 domain = ((MonoObject *)type)->vtable->domain;
4272 if (type->type->byref)
4273 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4274 klass = mono_class_from_mono_type (type->type);
4277 * If a nested type is generic, return its generic type definition.
4278 * Note that this means that the return value is essentially the set
4279 * of nested types of the generic type definition of @klass.
4281 * A note in MSDN claims that a generic type definition can have
4282 * nested types that aren't generic. In any case, the container of that
4283 * nested type would be the generic type definition.
4285 if (klass->generic_class)
4286 klass = klass->generic_class->container_class;
4288 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4290 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4292 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4293 if (bflags & BFLAGS_Public)
4296 if (bflags & BFLAGS_NonPublic)
4304 str = mono_string_to_utf8 (name);
4305 mono_identifier_unescape_type_name_chars (str);
4308 if (strcmp (nested->name, str))
4312 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4313 mono_error_raise_exception (&error);
4315 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4318 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4320 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4321 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4323 mono_ptr_array_destroy (tmp_array);
4331 ICALL_EXPORT MonoReflectionType*
4332 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4335 MonoReflectionType *ret;
4337 MonoType *type = NULL;
4338 MonoTypeNameParse info;
4339 gboolean type_resolve;
4341 /* On MS.NET, this does not fire a TypeResolve event */
4342 type_resolve = TRUE;
4343 str = mono_string_to_utf8 (name);
4344 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4345 if (!mono_reflection_parse_type (str, &info)) {
4347 mono_reflection_free_type_info (&info);
4349 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4352 /*g_print ("failed parse\n");*/
4356 if (info.assembly.name) {
4358 mono_reflection_free_type_info (&info);
4360 /* 1.0 and 2.0 throw different exceptions */
4361 if (mono_defaults.generic_ilist_class)
4362 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4364 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4370 if (module != NULL) {
4372 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4377 if (assembly_is_dynamic (assembly->assembly)) {
4378 /* Enumerate all modules */
4379 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4383 if (abuilder->modules) {
4384 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4385 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4386 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4392 if (!type && abuilder->loaded_modules) {
4393 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4394 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4395 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4402 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4404 mono_reflection_free_type_info (&info);
4406 MonoException *e = NULL;
4409 e = mono_get_exception_type_load (name, NULL);
4411 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4412 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4414 mono_loader_clear_error ();
4417 mono_set_pending_exception (e);
4419 } else if (mono_loader_get_last_error ()) {
4421 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4424 mono_loader_clear_error ();
4427 if (type->type == MONO_TYPE_CLASS) {
4428 MonoClass *klass = mono_type_get_class (type);
4430 /* need to report exceptions ? */
4431 if (throwOnError && mono_class_has_failure (klass)) {
4432 /* report SecurityException (or others) that occured when loading the assembly */
4433 MonoException *exc = mono_class_get_exception_for_failure (klass);
4434 mono_loader_clear_error ();
4435 mono_set_pending_exception (exc);
4440 /* g_print ("got it\n"); */
4441 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4442 mono_error_raise_exception (&error);
4448 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4451 gchar *shadow_ini_file;
4454 /* Check for shadow-copied assembly */
4455 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4456 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4458 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4459 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4465 g_free (shadow_ini_file);
4466 if (content != NULL) {
4469 *filename = content;
4476 ICALL_EXPORT MonoString *
4477 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4479 MonoDomain *domain = mono_object_domain (assembly);
4480 MonoAssembly *mass = assembly->assembly;
4481 MonoString *res = NULL;
4486 if (g_path_is_absolute (mass->image->name)) {
4487 absolute = g_strdup (mass->image->name);
4488 dirname = g_path_get_dirname (absolute);
4490 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4491 dirname = g_strdup (mass->basedir);
4494 replace_shadow_path (domain, dirname, &absolute);
4499 for (i = strlen (absolute) - 1; i >= 0; i--)
4500 if (absolute [i] == '\\')
4505 uri = g_filename_to_uri (absolute, NULL, NULL);
4507 const char *prepend = "file://";
4509 if (*absolute == '/' && *(absolute + 1) == '/') {
4512 prepend = "file:///";
4515 uri = g_strconcat (prepend, absolute, NULL);
4519 res = mono_string_new (domain, uri);
4526 ICALL_EXPORT MonoBoolean
4527 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4529 MonoAssembly *mass = assembly->assembly;
4531 return mass->in_gac;
4534 ICALL_EXPORT MonoReflectionAssembly*
4535 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4540 MonoImageOpenStatus status;
4541 MonoReflectionAssembly* result = NULL;
4543 name = mono_string_to_utf8 (mname);
4544 res = mono_assembly_load_with_partial_name (name, &status);
4550 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4552 mono_error_set_pending_exception (&error);
4556 ICALL_EXPORT MonoString *
4557 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4559 MonoDomain *domain = mono_object_domain (assembly);
4562 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4567 ICALL_EXPORT MonoBoolean
4568 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4570 return assembly->assembly->ref_only;
4573 ICALL_EXPORT MonoString *
4574 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4576 MonoDomain *domain = mono_object_domain (assembly);
4578 return mono_string_new (domain, assembly->assembly->image->version);
4581 ICALL_EXPORT MonoReflectionMethod*
4582 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4585 MonoReflectionMethod *res = NULL;
4588 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4592 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4593 if (!mono_error_ok (&error))
4596 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4599 if (!mono_error_ok (&error))
4600 mono_error_set_pending_exception (&error);
4604 ICALL_EXPORT MonoReflectionModule*
4605 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4608 MonoReflectionModule *result = NULL;
4609 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4610 if (!mono_error_ok (&error))
4611 mono_error_set_pending_exception (&error);
4615 ICALL_EXPORT MonoArray*
4616 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4618 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4619 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4623 for (i = 0; i < table->rows; ++i) {
4624 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4625 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4631 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4633 static MonoMethod *create_version = NULL;
4637 mono_error_init (error);
4640 if (!create_version) {
4641 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4642 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4643 g_assert (create_version);
4644 mono_method_desc_free (desc);
4650 args [3] = &revision;
4651 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4652 return_val_if_nok (error, NULL);
4654 mono_runtime_invoke_checked (create_version, result, args, error);
4655 return_val_if_nok (error, NULL);
4660 ICALL_EXPORT MonoArray*
4661 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4665 MonoDomain *domain = mono_object_domain (assembly);
4667 static MonoMethod *create_culture = NULL;
4668 MonoImage *image = assembly->assembly->image;
4672 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4675 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4677 if (count > 0 && !create_culture) {
4678 MonoMethodDesc *desc = mono_method_desc_new (
4679 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4680 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4681 g_assert (create_culture);
4682 mono_method_desc_free (desc);
4685 for (i = 0; i < count; i++) {
4686 MonoObject *version;
4687 MonoReflectionAssemblyName *aname;
4688 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4690 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4692 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4693 domain, mono_class_get_assembly_name_class (), &error);
4694 mono_error_raise_exception (&error);
4696 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4698 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4699 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4700 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4701 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4702 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4703 aname->versioncompat = 1; /* SameMachine (default) */
4704 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4706 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4707 mono_error_raise_exception (&error);
4709 MONO_OBJECT_SETREF (aname, version, version);
4711 if (create_culture) {
4713 MonoBoolean assembly_ref = 1;
4714 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4715 args [1] = &assembly_ref;
4717 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4718 mono_error_raise_exception (&error);
4720 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4723 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4724 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4725 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4727 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4728 /* public key token isn't copied - the class library will
4729 automatically generate it from the public key if required */
4730 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4731 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4733 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4734 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4737 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4740 /* note: this function doesn't return the codebase on purpose (i.e. it can
4741 be used under partial trust as path information isn't present). */
4743 mono_array_setref (result, i, aname);
4748 /* move this in some file in mono/util/ */
4750 g_concat_dir_and_file (const char *dir, const char *file)
4752 g_return_val_if_fail (dir != NULL, NULL);
4753 g_return_val_if_fail (file != NULL, NULL);
4756 * If the directory name doesn't have a / on the end, we need
4757 * to add one so we get a proper path to the file
4759 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4760 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4762 return g_strconcat (dir, file, NULL);
4766 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4769 char *n = mono_string_to_utf8 (name);
4770 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4772 guint32 cols [MONO_MANIFEST_SIZE];
4773 guint32 impl, file_idx;
4777 for (i = 0; i < table->rows; ++i) {
4778 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4779 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4780 if (strcmp (val, n) == 0)
4784 if (i == table->rows)
4787 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4790 * this code should only be called after obtaining the
4791 * ResourceInfo and handling the other cases.
4793 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4794 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4796 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4801 module = assembly->assembly->image;
4804 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4805 mono_error_raise_exception (&error);
4806 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4808 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4811 ICALL_EXPORT gboolean
4812 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4815 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4817 guint32 cols [MONO_MANIFEST_SIZE];
4818 guint32 file_cols [MONO_FILE_SIZE];
4822 n = mono_string_to_utf8 (name);
4823 for (i = 0; i < table->rows; ++i) {
4824 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4825 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4826 if (strcmp (val, n) == 0)
4830 if (i == table->rows)
4833 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4834 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4837 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4838 case MONO_IMPLEMENTATION_FILE:
4839 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4840 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4841 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4842 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4843 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4844 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4847 info->location = RESOURCE_LOCATION_EMBEDDED;
4850 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4851 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4852 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4853 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4854 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4855 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4857 mono_set_pending_exception (ex);
4860 MonoReflectionAssembly *assm_obj;
4861 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4863 mono_error_set_pending_exception (&error);
4866 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4868 /* Obtain info recursively */
4869 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4870 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4873 case MONO_IMPLEMENTATION_EXP_TYPE:
4874 g_assert_not_reached ();
4882 ICALL_EXPORT MonoObject*
4883 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4885 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4886 MonoArray *result = NULL;
4891 /* check hash if needed */
4893 n = mono_string_to_utf8 (name);
4894 for (i = 0; i < table->rows; ++i) {
4895 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4896 if (strcmp (val, n) == 0) {
4899 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4900 fn = mono_string_new (mono_object_domain (assembly), n);
4902 return (MonoObject*)fn;
4910 for (i = 0; i < table->rows; ++i) {
4911 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4915 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4918 for (i = 0; i < table->rows; ++i) {
4919 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4920 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4921 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4922 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4927 return (MonoObject*)result;
4930 ICALL_EXPORT MonoArray*
4931 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4934 MonoDomain *domain = mono_domain_get();
4937 int i, j, file_count = 0;
4938 MonoImage **modules;
4939 guint32 module_count, real_module_count;
4940 MonoTableInfo *table;
4941 guint32 cols [MONO_FILE_SIZE];
4942 MonoImage *image = assembly->assembly->image;
4944 g_assert (image != NULL);
4945 g_assert (!assembly_is_dynamic (assembly->assembly));
4947 table = &image->tables [MONO_TABLE_FILE];
4948 file_count = table->rows;
4950 modules = image->modules;
4951 module_count = image->module_count;
4953 real_module_count = 0;
4954 for (i = 0; i < module_count; ++i)
4956 real_module_count ++;
4958 klass = mono_class_get_module_class ();
4959 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4961 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
4962 mono_error_raise_exception (&error);
4963 mono_array_setref (res, 0, image_obj);
4965 for (i = 0; i < module_count; ++i)
4967 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
4968 mono_error_raise_exception (&error);
4969 mono_array_setref (res, j, rm);
4973 for (i = 0; i < file_count; ++i, ++j) {
4974 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4975 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
4976 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
4977 mono_error_raise_exception (&error);
4978 mono_array_setref (res, j, rm);
4981 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4983 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4984 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
4987 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
4988 mono_error_raise_exception (&error);
4989 mono_array_setref (res, j, rm);
4996 ICALL_EXPORT MonoReflectionMethod*
4997 ves_icall_GetCurrentMethod (void)
4999 MonoReflectionMethod *res = NULL;
5002 MonoMethod *m = mono_method_get_last_managed ();
5005 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5009 while (m->is_inflated)
5010 m = ((MonoMethodInflated*)m)->declaring;
5012 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5013 mono_error_raise_exception (&error);
5019 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5022 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5025 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5026 //method is inflated, we should inflate it on the other class
5027 MonoGenericContext ctx;
5028 ctx.method_inst = inflated->context.method_inst;
5029 ctx.class_inst = inflated->context.class_inst;
5030 if (klass->generic_class)
5031 ctx.class_inst = klass->generic_class->context.class_inst;
5032 else if (klass->generic_container)
5033 ctx.class_inst = klass->generic_container->context.class_inst;
5034 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5035 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5039 mono_class_setup_methods (method->klass);
5040 if (mono_class_has_failure (method->klass))
5042 for (i = 0; i < method->klass->method.count; ++i) {
5043 if (method->klass->methods [i] == method) {
5048 mono_class_setup_methods (klass);
5049 if (mono_class_has_failure (klass))
5051 g_assert (offset >= 0 && offset < klass->method.count);
5052 return klass->methods [offset];
5055 ICALL_EXPORT MonoReflectionMethod*
5056 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5058 MonoReflectionMethod *res = NULL;
5062 klass = mono_class_from_mono_type (type);
5063 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5065 if (method->klass != klass) {
5066 method = mono_method_get_equivalent_method (method, klass);
5071 klass = method->klass;
5072 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5073 mono_error_raise_exception (&error);
5077 ICALL_EXPORT MonoReflectionMethodBody*
5078 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5080 return mono_method_body_get_object (mono_domain_get (), method);
5083 ICALL_EXPORT MonoReflectionAssembly*
5084 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5087 MonoReflectionAssembly *result;
5088 MonoMethod *dest = NULL;
5090 mono_stack_walk_no_il (get_executing, &dest);
5092 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5094 mono_error_set_pending_exception (&error);
5099 ICALL_EXPORT MonoReflectionAssembly*
5100 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5103 MonoReflectionAssembly *result;
5104 MonoDomain* domain = mono_domain_get ();
5106 if (!domain->entry_assembly)
5109 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5111 mono_error_set_pending_exception (&error);
5115 ICALL_EXPORT MonoReflectionAssembly*
5116 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5121 MonoReflectionAssembly *result;
5124 mono_stack_walk_no_il (get_executing, &dest);
5126 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5130 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5133 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5135 mono_error_set_pending_exception (&error);
5139 ICALL_EXPORT MonoString *
5140 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5141 gboolean assembly_qualified)
5143 MonoDomain *domain = mono_object_domain (object);
5144 MonoTypeNameFormat format;
5149 format = assembly_qualified ?
5150 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5151 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5153 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5155 name = mono_type_get_name_full (object->type, format);
5159 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5164 res = mono_string_new (domain, name);
5171 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5174 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5176 mono_class_init_checked (klass, &error);
5177 mono_error_raise_exception (&error);
5178 return mono_security_core_clr_class_level (klass);
5182 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5184 MonoClassField *field = rfield->field;
5185 return mono_security_core_clr_field_level (field, TRUE);
5189 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5191 MonoMethod *method = rfield->method;
5192 return mono_security_core_clr_method_level (method, TRUE);
5196 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)
5198 static MonoMethod *create_culture = NULL;
5202 const char *pkey_ptr;
5204 MonoBoolean assembly_ref = 0;
5206 mono_error_init (error);
5208 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5209 aname->major = name->major;
5210 aname->minor = name->minor;
5211 aname->build = name->build;
5212 aname->flags = name->flags;
5213 aname->revision = name->revision;
5214 aname->hashalg = name->hash_alg;
5215 aname->versioncompat = 1; /* SameMachine (default) */
5216 aname->processor_architecture = name->arch;
5218 if (by_default_version) {
5219 MonoObject *version;
5221 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5222 return_if_nok (error);
5224 MONO_OBJECT_SETREF (aname, version, version);
5228 if (absolute != NULL && *absolute != '\0') {
5229 const gchar *prepend = "file://";
5232 codebase = g_strdup (absolute);
5237 for (i = strlen (codebase) - 1; i >= 0; i--)
5238 if (codebase [i] == '\\')
5241 if (*codebase == '/' && *(codebase + 1) == '/') {
5244 prepend = "file:///";
5248 result = g_strconcat (prepend, codebase, NULL);
5254 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5258 if (!create_culture) {
5259 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5260 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5261 g_assert (create_culture);
5262 mono_method_desc_free (desc);
5265 if (name->culture) {
5266 args [0] = mono_string_new (domain, name->culture);
5267 args [1] = &assembly_ref;
5269 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5270 return_if_nok (error);
5272 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5275 if (name->public_key) {
5276 pkey_ptr = (char*)name->public_key;
5277 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5279 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5280 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5281 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5282 } else if (default_publickey) {
5283 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5284 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5287 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5288 if (name->public_key_token [0]) {
5292 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5293 p = mono_array_addr (aname->keyToken, char, 0);
5295 for (i = 0, j = 0; i < 8; i++) {
5296 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5297 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5300 } else if (default_token) {
5301 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5305 ICALL_EXPORT MonoString *
5306 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5308 MonoDomain *domain = mono_object_domain (assembly);
5309 MonoAssembly *mass = assembly->assembly;
5313 name = mono_stringify_assembly_name (&mass->aname);
5314 res = mono_string_new (domain, name);
5321 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5325 MonoAssembly *mass = assembly->assembly;
5327 if (g_path_is_absolute (mass->image->name)) {
5328 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5329 mono_error_set_pending_exception (&error);
5332 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5334 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5335 mono_error_set_pending_exception (&error);
5341 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5345 MonoImageOpenStatus status = MONO_IMAGE_OK;
5348 MonoAssemblyName name;
5351 filename = mono_string_to_utf8 (fname);
5353 dirname = g_path_get_dirname (filename);
5354 replace_shadow_path (mono_domain_get (), dirname, &filename);
5357 image = mono_image_open (filename, &status);
5363 if (status == MONO_IMAGE_IMAGE_INVALID)
5364 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5366 exc = mono_get_exception_file_not_found2 (NULL, fname);
5367 mono_set_pending_exception (exc);
5371 res = mono_assembly_fill_assembly_name (image, &name);
5373 mono_image_close (image);
5375 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5379 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5380 mono_error_set_pending_exception (&error);
5382 mono_image_close (image);
5386 ICALL_EXPORT MonoBoolean
5387 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5388 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5390 MonoBoolean result = FALSE;
5391 MonoDeclSecurityEntry entry;
5393 /* SecurityAction.RequestMinimum */
5394 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5395 *minimum = entry.blob;
5396 *minLength = entry.size;
5399 /* SecurityAction.RequestOptional */
5400 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5401 *optional = entry.blob;
5402 *optLength = entry.size;
5405 /* SecurityAction.RequestRefuse */
5406 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5407 *refused = entry.blob;
5408 *refLength = entry.size;
5416 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5418 guint32 attrs, visibility;
5420 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5421 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5422 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5425 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5431 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5433 MonoReflectionType *rt;
5436 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5439 mono_error_init (error);
5441 /* we start the count from 1 because we skip the special type <Module> */
5444 for (i = 1; i < tdef->rows; ++i) {
5445 if (mono_module_type_is_visible (tdef, image, i + 1))
5449 count = tdef->rows - 1;
5451 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5452 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5454 for (i = 1; i < tdef->rows; ++i) {
5455 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5456 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5457 mono_loader_assert_no_error (); /* Plug any leaks */
5458 mono_error_assert_ok (error);
5461 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5462 return_val_if_nok (error, NULL);
5464 mono_array_setref (res, count, rt);
5466 MonoException *ex = mono_error_convert_to_exception (error);
5467 mono_array_setref (*exceptions, count, ex);
5476 ICALL_EXPORT MonoArray*
5477 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5480 MonoArray *res = NULL;
5481 MonoArray *exceptions = NULL;
5482 MonoImage *image = NULL;
5483 MonoTableInfo *table = NULL;
5486 int i, len, ex_count;
5488 domain = mono_object_domain (assembly);
5490 g_assert (!assembly_is_dynamic (assembly->assembly));
5491 image = assembly->assembly->image;
5492 table = &image->tables [MONO_TABLE_FILE];
5493 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5494 mono_error_raise_exception (&error);
5496 /* Append data from all modules in the assembly */
5497 for (i = 0; i < table->rows; ++i) {
5498 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5499 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5504 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5505 mono_error_raise_exception (&error);
5507 /* Append the new types to the end of the array */
5508 if (mono_array_length (res2) > 0) {
5510 MonoArray *res3, *ex3;
5512 len1 = mono_array_length (res);
5513 len2 = mono_array_length (res2);
5515 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5516 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5517 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5520 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5521 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5522 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5529 /* the ReflectionTypeLoadException must have all the types (Types property),
5530 * NULL replacing types which throws an exception. The LoaderException must
5531 * contain all exceptions for NULL items.
5534 len = mono_array_length (res);
5537 for (i = 0; i < len; i++) {
5538 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5542 klass = mono_type_get_class (t->type);
5543 if ((klass != NULL) && mono_class_has_failure (klass)) {
5544 /* keep the class in the list */
5545 list = g_list_append (list, klass);
5546 /* and replace Type with NULL */
5547 mono_array_setref (res, i, NULL);
5554 if (list || ex_count) {
5556 MonoException *exc = NULL;
5557 MonoArray *exl = NULL;
5558 int j, length = g_list_length (list) + ex_count;
5560 mono_loader_clear_error ();
5562 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5563 /* Types for which mono_class_get_checked () succeeded */
5564 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5565 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5566 mono_array_setref (exl, i, exc);
5568 /* Types for which it don't */
5569 for (j = 0; j < mono_array_length (exceptions); ++j) {
5570 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5572 g_assert (i < length);
5573 mono_array_setref (exl, i, exc);
5580 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5581 if (!is_ok (&error)) {
5582 mono_error_set_pending_exception (&error);
5585 mono_loader_clear_error ();
5586 mono_set_pending_exception (exc);
5593 ICALL_EXPORT gboolean
5594 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5597 MonoAssemblyName aname;
5598 MonoDomain *domain = mono_object_domain (name);
5600 gboolean is_version_defined;
5601 gboolean is_token_defined;
5603 aname.public_key = NULL;
5604 val = mono_string_to_utf8 (assname);
5605 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5606 g_free ((guint8*) aname.public_key);
5611 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5612 mono_error_set_pending_exception (&error);
5614 mono_assembly_name_free (&aname);
5615 g_free ((guint8*) aname.public_key);
5621 ICALL_EXPORT MonoReflectionType*
5622 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5625 MonoReflectionType *ret;
5626 MonoDomain *domain = mono_object_domain (module);
5629 g_assert (module->image);
5631 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5632 /* These images do not have a global type */
5635 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5636 if (!mono_error_ok (&error)) {
5637 mono_error_set_pending_exception (&error);
5641 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5642 if (!mono_error_ok (&error)) {
5643 mono_error_set_pending_exception (&error);
5651 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5653 /*if (module->image)
5654 mono_image_close (module->image);*/
5657 ICALL_EXPORT MonoString*
5658 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5660 MonoDomain *domain = mono_object_domain (module);
5662 g_assert (module->image);
5663 return mono_string_new (domain, module->image->guid);
5666 ICALL_EXPORT gpointer
5667 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5670 if (module->image && module->image->is_module_handle)
5671 return module->image->raw_data;
5674 return (gpointer) (-1);
5678 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5680 if (image_is_dynamic (image)) {
5681 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5682 *pe_kind = dyn->pe_kind;
5683 *machine = dyn->machine;
5686 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5687 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5692 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5694 return (image->md_version_major << 16) | (image->md_version_minor);
5697 ICALL_EXPORT MonoArray*
5698 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5701 MonoArray *exceptions;
5705 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5709 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5710 mono_error_raise_exception (&error);
5712 for (i = 0; i < mono_array_length (exceptions); ++i) {
5713 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5715 mono_set_pending_exception (ex);
5724 mono_memberref_is_method (MonoImage *image, guint32 token)
5726 if (!image_is_dynamic (image)) {
5727 guint32 cols [MONO_MEMBERREF_SIZE];
5729 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5730 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5731 mono_metadata_decode_blob_size (sig, &sig);
5732 return (*sig != 0x6);
5734 MonoClass *handle_class;
5736 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5739 return mono_defaults.methodhandle_class == handle_class;
5744 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5747 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5748 mono_array_addr (type_args, MonoType*, 0));
5750 context->class_inst = NULL;
5752 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5753 mono_array_addr (method_args, MonoType*, 0));
5755 context->method_inst = NULL;
5758 ICALL_EXPORT MonoType*
5759 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5762 int table = mono_metadata_token_table (token);
5763 int index = mono_metadata_token_index (token);
5764 MonoGenericContext context;
5767 *resolve_error = ResolveTokenError_Other;
5769 /* Validate token */
5770 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5771 (table != MONO_TABLE_TYPESPEC)) {
5772 *resolve_error = ResolveTokenError_BadTable;
5776 if (image_is_dynamic (image)) {
5777 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5778 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5779 return klass ? &klass->byval_arg : NULL;
5782 init_generic_context_from_args (&context, type_args, method_args);
5783 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5784 return klass ? &klass->byval_arg : NULL;
5787 if ((index <= 0) || (index > image->tables [table].rows)) {
5788 *resolve_error = ResolveTokenError_OutOfRange;
5792 init_generic_context_from_args (&context, type_args, method_args);
5793 klass = mono_class_get_checked (image, token, &error);
5795 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5796 if (!mono_error_ok (&error)) {
5797 mono_error_set_pending_exception (&error);
5802 return &klass->byval_arg;
5807 ICALL_EXPORT MonoMethod*
5808 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5811 int table = mono_metadata_token_table (token);
5812 int index = mono_metadata_token_index (token);
5813 MonoGenericContext context;
5816 *resolve_error = ResolveTokenError_Other;
5818 /* Validate token */
5819 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5820 (table != MONO_TABLE_MEMBERREF)) {
5821 *resolve_error = ResolveTokenError_BadTable;
5825 if (image_is_dynamic (image)) {
5826 if (table == MONO_TABLE_METHOD)
5827 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5829 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5830 *resolve_error = ResolveTokenError_BadTable;
5834 init_generic_context_from_args (&context, type_args, method_args);
5835 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5838 if ((index <= 0) || (index > image->tables [table].rows)) {
5839 *resolve_error = ResolveTokenError_OutOfRange;
5842 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5843 *resolve_error = ResolveTokenError_BadTable;
5847 init_generic_context_from_args (&context, type_args, method_args);
5848 method = mono_get_method_checked (image, token, NULL, &context, &error);
5849 mono_error_set_pending_exception (&error);
5854 ICALL_EXPORT MonoString*
5855 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5857 int index = mono_metadata_token_index (token);
5859 *error = ResolveTokenError_Other;
5861 /* Validate token */
5862 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5863 *error = ResolveTokenError_BadTable;
5867 if (image_is_dynamic (image))
5868 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5870 if ((index <= 0) || (index >= image->heap_us.size)) {
5871 *error = ResolveTokenError_OutOfRange;
5875 /* FIXME: What to do if the index points into the middle of a string ? */
5877 return mono_ldstr (mono_domain_get (), image, index);
5880 ICALL_EXPORT MonoClassField*
5881 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5885 int table = mono_metadata_token_table (token);
5886 int index = mono_metadata_token_index (token);
5887 MonoGenericContext context;
5888 MonoClassField *field;
5890 *resolve_error = ResolveTokenError_Other;
5892 /* Validate token */
5893 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5894 *resolve_error = ResolveTokenError_BadTable;
5898 if (image_is_dynamic (image)) {
5899 if (table == MONO_TABLE_FIELD)
5900 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5902 if (mono_memberref_is_method (image, token)) {
5903 *resolve_error = ResolveTokenError_BadTable;
5907 init_generic_context_from_args (&context, type_args, method_args);
5908 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5911 if ((index <= 0) || (index > image->tables [table].rows)) {
5912 *resolve_error = ResolveTokenError_OutOfRange;
5915 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5916 *resolve_error = ResolveTokenError_BadTable;
5920 init_generic_context_from_args (&context, type_args, method_args);
5921 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5922 mono_error_set_pending_exception (&error);
5928 ICALL_EXPORT MonoObject*
5929 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5933 int table = mono_metadata_token_table (token);
5935 *error = ResolveTokenError_Other;
5938 case MONO_TABLE_TYPEDEF:
5939 case MONO_TABLE_TYPEREF:
5940 case MONO_TABLE_TYPESPEC: {
5941 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5943 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
5944 mono_error_raise_exception (&merror);
5951 case MONO_TABLE_METHOD:
5952 case MONO_TABLE_METHODSPEC: {
5953 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5955 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5956 mono_error_raise_exception (&merror);
5962 case MONO_TABLE_FIELD: {
5963 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5965 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5966 mono_error_raise_exception (&merror);
5972 case MONO_TABLE_MEMBERREF:
5973 if (mono_memberref_is_method (image, token)) {
5974 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5976 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5977 mono_error_raise_exception (&merror);
5984 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5986 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5987 mono_error_raise_exception (&merror);
5996 *error = ResolveTokenError_BadTable;
6002 ICALL_EXPORT MonoArray*
6003 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
6005 int table = mono_metadata_token_table (token);
6006 int idx = mono_metadata_token_index (token);
6007 MonoTableInfo *tables = image->tables;
6012 *error = ResolveTokenError_OutOfRange;
6014 /* FIXME: Support other tables ? */
6015 if (table != MONO_TABLE_STANDALONESIG)
6018 if (image_is_dynamic (image))
6021 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6024 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6026 ptr = mono_metadata_blob_heap (image, sig);
6027 len = mono_metadata_decode_blob_size (ptr, &ptr);
6029 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
6030 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6034 ICALL_EXPORT MonoReflectionType*
6035 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6038 MonoReflectionType *ret;
6040 int isbyref = 0, rank;
6041 char *str = mono_string_to_utf8 (smodifiers);
6044 klass = mono_class_from_mono_type (tb->type.type);
6046 /* logic taken from mono_reflection_parse_type(): keep in sync */
6050 if (isbyref) { /* only one level allowed by the spec */
6059 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6060 mono_error_raise_exception (&error);
6064 klass = mono_ptr_class_get (&klass->byval_arg);
6065 mono_class_init (klass);
6076 else if (*p != '*') { /* '*' means unknown lower bound */
6087 klass = mono_array_class_get (klass, rank);
6088 mono_class_init (klass);
6097 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6098 mono_error_raise_exception (&error);
6103 ICALL_EXPORT MonoBoolean
6104 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6110 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6116 check_for_invalid_type (MonoClass *klass, MonoError *error)
6121 mono_error_init (error);
6123 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6126 name = mono_type_get_full_name (klass);
6127 str = mono_string_new (mono_domain_get (), name);
6129 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6132 ICALL_EXPORT MonoReflectionType *
6133 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6136 MonoReflectionType *ret;
6137 MonoClass *klass, *aklass;
6139 klass = mono_class_from_mono_type (type->type);
6140 check_for_invalid_type (klass, &error);
6141 mono_error_raise_exception (&error);
6143 if (rank == 0) //single dimentional array
6144 aklass = mono_array_class_get (klass, 1);
6146 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6148 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6149 mono_error_raise_exception (&error);
6154 ICALL_EXPORT MonoReflectionType *
6155 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6158 MonoReflectionType *ret;
6161 klass = mono_class_from_mono_type (type->type);
6162 mono_class_init_checked (klass, &error);
6163 mono_error_raise_exception (&error);
6164 check_for_invalid_type (klass, &error);
6165 mono_error_raise_exception (&error);
6167 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6168 mono_error_raise_exception (&error);
6173 ICALL_EXPORT MonoReflectionType *
6174 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6177 MonoReflectionType *ret;
6178 MonoClass *klass, *pklass;
6180 klass = mono_class_from_mono_type (type->type);
6181 mono_class_init_checked (klass, &error);
6182 mono_error_raise_exception (&error);
6183 check_for_invalid_type (klass, &error);
6184 mono_error_raise_exception (&error);
6186 pklass = mono_ptr_class_get (type->type);
6188 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6189 mono_error_raise_exception (&error);
6194 ICALL_EXPORT MonoObject *
6195 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6196 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6199 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6200 MonoObject *delegate;
6202 MonoMethod *method = info->method;
6204 mono_class_init_checked (delegate_class, &error);
6205 mono_error_raise_exception (&error);
6207 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
6209 if (mono_security_core_clr_enabled ()) {
6210 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6214 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6215 mono_error_raise_exception (&error);
6217 if (method_is_dynamic (method)) {
6218 /* Creating a trampoline would leak memory */
6219 func = mono_compile_method (method);
6221 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6222 method = mono_object_get_virtual_method (target, method);
6223 func = mono_create_ftnptr (mono_domain_get (),
6224 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6227 mono_delegate_ctor_with_method (delegate, target, func, method);
6232 ICALL_EXPORT MonoMulticastDelegate *
6233 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6236 MonoMulticastDelegate *ret;
6238 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6240 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6241 mono_error_raise_exception (&error);
6242 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6247 ICALL_EXPORT MonoReflectionMethod*
6248 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6250 MonoReflectionMethod *ret = NULL;
6252 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6253 mono_error_raise_exception (&error);
6259 static inline gint32
6260 mono_array_get_byte_length (MonoArray *array)
6266 klass = array->obj.vtable->klass;
6268 if (array->bounds == NULL)
6269 length = array->max_length;
6272 for (i = 0; i < klass->rank; ++ i)
6273 length *= array->bounds [i].length;
6276 switch (klass->element_class->byval_arg.type) {
6279 case MONO_TYPE_BOOLEAN:
6283 case MONO_TYPE_CHAR:
6291 return length * sizeof (gpointer);
6302 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6304 return mono_array_get_byte_length (array);
6308 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6310 return mono_array_get (array, gint8, idx);
6314 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6316 mono_array_set (array, gint8, idx, value);
6319 ICALL_EXPORT MonoBoolean
6320 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6322 guint8 *src_buf, *dest_buf;
6325 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6329 g_assert (count >= 0);
6331 /* This is called directly from the class libraries without going through the managed wrapper */
6332 MONO_CHECK_ARG_NULL (src, FALSE);
6333 MONO_CHECK_ARG_NULL (dest, FALSE);
6335 /* watch out for integer overflow */
6336 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6339 src_buf = (guint8 *)src->vector + src_offset;
6340 dest_buf = (guint8 *)dest->vector + dest_offset;
6343 memcpy (dest_buf, src_buf, count);
6345 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6350 #ifndef DISABLE_REMOTING
6351 ICALL_EXPORT MonoObject *
6352 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6355 MonoDomain *domain = mono_object_domain (this_obj);
6357 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6358 MonoTransparentProxy *tp;
6362 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6363 mono_error_raise_exception (&error);
6364 tp = (MonoTransparentProxy*) res;
6366 MONO_OBJECT_SETREF (tp, rp, rp);
6367 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6368 klass = mono_class_from_mono_type (type);
6370 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6371 mono_class_setup_vtable (klass);
6372 if (mono_class_has_failure (klass)) {
6373 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6377 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
6378 tp->remote_class = mono_remote_class (domain, class_name, klass);
6380 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6384 ICALL_EXPORT MonoReflectionType *
6385 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6388 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6389 mono_error_raise_exception (&error);
6395 /* System.Environment */
6398 ves_icall_System_Environment_get_UserName (void)
6400 /* using glib is more portable */
6401 return mono_string_new (mono_domain_get (), g_get_user_name ());
6405 ICALL_EXPORT MonoString *
6406 ves_icall_System_Environment_get_MachineName (void)
6408 #if defined (HOST_WIN32)
6413 len = MAX_COMPUTERNAME_LENGTH + 1;
6414 buf = g_new (gunichar2, len);
6417 if (GetComputerName (buf, (PDWORD) &len)) {
6419 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6420 mono_error_raise_exception (&error);
6425 #elif !defined(DISABLE_SOCKETS)
6429 #if defined _SC_HOST_NAME_MAX
6430 n = sysconf (_SC_HOST_NAME_MAX);
6434 buf = g_malloc (n+1);
6436 if (gethostname (buf, n) == 0){
6438 result = mono_string_new (mono_domain_get (), buf);
6445 return mono_string_new (mono_domain_get (), "mono");
6450 ves_icall_System_Environment_get_Platform (void)
6452 #if defined (TARGET_WIN32)
6455 #elif defined(__MACH__)
6458 // Notice that the value is hidden from user code, and only exposed
6459 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6460 // define and making assumptions based on Unix/128/4 values before there
6461 // was a MacOS define. Lots of code would assume that not-Unix meant
6462 // Windows, but in this case, it would be OSX.
6471 ICALL_EXPORT MonoString *
6472 ves_icall_System_Environment_get_NewLine (void)
6474 #if defined (HOST_WIN32)
6475 return mono_string_new (mono_domain_get (), "\r\n");
6477 return mono_string_new (mono_domain_get (), "\n");
6481 ICALL_EXPORT MonoBoolean
6482 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6484 #if SIZEOF_VOID_P == 8
6488 gboolean isWow64Process = FALSE;
6489 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6490 return (MonoBoolean)isWow64Process;
6492 #elif defined(HAVE_SYS_UTSNAME_H)
6493 struct utsname name;
6495 if (uname (&name) >= 0) {
6496 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6503 ICALL_EXPORT MonoString *
6504 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6512 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6513 value = g_getenv (utf8_name);
6520 return mono_string_new (mono_domain_get (), value);
6524 * There is no standard way to get at environ.
6527 #ifndef __MINGW32_VERSION
6528 #if defined(__APPLE__)
6529 #if defined (TARGET_OSX)
6530 /* Apple defines this in crt_externs.h but doesn't provide that header for
6531 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6532 * in fact exist on all implementations (so far)
6534 gchar ***_NSGetEnviron(void);
6535 #define environ (*_NSGetEnviron())
6537 static char *mono_environ[1] = { NULL };
6538 #define environ mono_environ
6539 #endif /* defined (TARGET_OSX) */
6547 ICALL_EXPORT MonoArray *
6548 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6559 env_strings = GetEnvironmentStrings();
6562 env_string = env_strings;
6563 while (*env_string != '\0') {
6564 /* weird case that MS seems to skip */
6565 if (*env_string != '=')
6567 while (*env_string != '\0')
6573 domain = mono_domain_get ();
6574 names = mono_array_new (domain, mono_defaults.string_class, n);
6578 env_string = env_strings;
6579 while (*env_string != '\0') {
6580 /* weird case that MS seems to skip */
6581 if (*env_string != '=') {
6582 equal_str = wcschr(env_string, '=');
6583 g_assert(equal_str);
6585 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6586 mono_error_raise_exception (&error);
6587 mono_array_setref (names, n, str);
6590 while (*env_string != '\0')
6595 FreeEnvironmentStrings (env_strings);
6608 for (e = environ; *e != 0; ++ e)
6611 domain = mono_domain_get ();
6612 names = mono_array_new (domain, mono_defaults.string_class, n);
6615 for (e = environ; *e != 0; ++ e) {
6616 parts = g_strsplit (*e, "=", 2);
6618 str = mono_string_new (domain, *parts);
6619 mono_array_setref (names, n, str);
6632 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6634 #if !GLIB_CHECK_VERSION(2,4,0)
6635 #define g_setenv(a,b,c) setenv(a,b,c)
6636 #define g_unsetenv(a) unsetenv(a)
6640 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6643 gunichar2 *utf16_name, *utf16_value;
6645 gchar *utf8_name, *utf8_value;
6650 utf16_name = mono_string_to_utf16 (name);
6651 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6652 SetEnvironmentVariable (utf16_name, NULL);
6653 g_free (utf16_name);
6657 utf16_value = mono_string_to_utf16 (value);
6659 SetEnvironmentVariable (utf16_name, utf16_value);
6661 g_free (utf16_name);
6662 g_free (utf16_value);
6664 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6666 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6667 g_unsetenv (utf8_name);
6672 utf8_value = mono_string_to_utf8_checked (value, &error);
6673 if (!mono_error_ok (&error)) {
6675 mono_error_set_pending_exception (&error);
6678 g_setenv (utf8_name, utf8_value, TRUE);
6681 g_free (utf8_value);
6686 ves_icall_System_Environment_Exit (int result)
6688 mono_environment_exitcode_set (result);
6690 /* FIXME: There are some cleanup hangs that should be worked out, but
6691 * if the program is going to exit, everything will be cleaned up when
6692 * NaCl exits anyway.
6694 #ifndef __native_client__
6695 if (!mono_runtime_try_shutdown ())
6696 mono_thread_exit ();
6698 /* Suspend all managed threads since the runtime is going away */
6699 mono_thread_suspend_all_other_threads ();
6701 mono_runtime_quit ();
6704 /* we may need to do some cleanup here... */
6708 ICALL_EXPORT MonoString*
6709 ves_icall_System_Environment_GetGacPath (void)
6711 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6714 ICALL_EXPORT MonoString*
6715 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6717 #if defined (HOST_WIN32)
6718 #ifndef CSIDL_FLAG_CREATE
6719 #define CSIDL_FLAG_CREATE 0x8000
6722 WCHAR path [MAX_PATH];
6723 /* Create directory if no existing */
6724 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6729 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6730 mono_error_raise_exception (&error);
6734 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6736 return mono_string_new (mono_domain_get (), "");
6739 ICALL_EXPORT MonoArray *
6740 ves_icall_System_Environment_GetLogicalDrives (void)
6743 gunichar2 buf [256], *ptr, *dname;
6745 guint initial_size = 127, size = 128;
6748 MonoString *drivestr;
6749 MonoDomain *domain = mono_domain_get ();
6755 while (size > initial_size) {
6756 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6757 if (size > initial_size) {
6760 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6761 initial_size = size;
6775 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6780 while (*u16) { u16++; len ++; }
6781 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6782 mono_error_raise_exception (&error);
6783 mono_array_setref (result, ndrives++, drivestr);
6793 ICALL_EXPORT MonoString *
6794 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6796 gunichar2 volume_name [MAX_PATH + 1];
6798 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6800 return mono_string_from_utf16 (volume_name);
6803 ICALL_EXPORT MonoString *
6804 ves_icall_System_Environment_InternalGetHome (void)
6806 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6809 static const char *encodings [] = {
6811 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6812 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6813 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6815 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6816 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6817 "x_unicode_2_0_utf_7",
6819 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6820 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6822 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6825 "unicodefffe", "utf_16be",
6832 * Returns the internal codepage, if the value of "int_code_page" is
6833 * 1 at entry, and we can not compute a suitable code page number,
6834 * returns the code page as a string
6836 ICALL_EXPORT MonoString*
6837 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6842 char *codepage = NULL;
6844 int want_name = *int_code_page;
6847 *int_code_page = -1;
6849 g_get_charset (&cset);
6850 c = codepage = strdup (cset);
6851 for (c = codepage; *c; c++){
6852 if (isascii (*c) && isalpha (*c))
6857 /* g_print ("charset: %s\n", cset); */
6859 /* handle some common aliases */
6862 for (i = 0; p != 0; ){
6865 p = encodings [++i];
6868 if (strcmp (p, codepage) == 0){
6869 *int_code_page = code;
6872 p = encodings [++i];
6875 if (strstr (codepage, "utf_8") != NULL)
6876 *int_code_page |= 0x10000000;
6879 if (want_name && *int_code_page == -1)
6880 return mono_string_new (mono_domain_get (), cset);
6885 ICALL_EXPORT MonoBoolean
6886 ves_icall_System_Environment_get_HasShutdownStarted (void)
6888 if (mono_runtime_is_shutting_down ())
6891 if (mono_domain_is_unloading (mono_domain_get ()))
6898 ves_icall_System_Environment_BroadcastSettingChange (void)
6901 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6906 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6912 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6913 MonoReflectionMethod *method,
6914 MonoArray *out_args)
6916 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6919 #ifndef DISABLE_REMOTING
6920 ICALL_EXPORT MonoBoolean
6921 ves_icall_IsTransparentProxy (MonoObject *proxy)
6926 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6932 ICALL_EXPORT MonoReflectionMethod *
6933 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6934 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6936 MonoReflectionMethod *ret = NULL;
6941 MonoMethod **vtable;
6942 MonoMethod *res = NULL;
6944 MONO_CHECK_ARG_NULL (rtype, NULL);
6945 MONO_CHECK_ARG_NULL (rmethod, NULL);
6947 method = rmethod->method;
6948 klass = mono_class_from_mono_type (rtype->type);
6949 mono_class_init_checked (klass, &error);
6950 mono_error_raise_exception (&error);
6952 if (MONO_CLASS_IS_INTERFACE (klass))
6955 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6958 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6959 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6965 mono_class_setup_vtable (klass);
6966 vtable = klass->vtable;
6968 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6969 gboolean variance_used = FALSE;
6970 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6971 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6973 res = vtable [offs + method->slot];
6975 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6978 if (method->slot != -1)
6979 res = vtable [method->slot];
6985 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
6986 mono_error_raise_exception (&error);
6991 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6997 klass = mono_class_from_mono_type (type->type);
6998 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
6999 if (!is_ok (&error)) {
7000 mono_error_set_pending_exception (&error);
7004 mono_vtable_set_is_remote (vtable, enable);
7007 #else /* DISABLE_REMOTING */
7010 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7012 g_assert_not_reached ();
7017 ICALL_EXPORT MonoObject *
7018 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7025 domain = mono_object_domain (type);
7026 klass = mono_class_from_mono_type (type->type);
7027 mono_class_init_checked (klass, &error);
7028 mono_error_raise_exception (&error);
7030 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7031 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7035 if (klass->rank >= 1) {
7036 g_assert (klass->rank == 1);
7037 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7039 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7040 if (!is_ok (&error)) {
7041 mono_error_set_pending_exception (&error);
7044 /* Bypass remoting object creation check */
7045 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7046 mono_error_set_pending_exception (&error);
7052 ICALL_EXPORT MonoString *
7053 ves_icall_System_IO_get_temp_path (void)
7055 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7058 #ifndef PLATFORM_NO_DRIVEINFO
7059 ICALL_EXPORT MonoBoolean
7060 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7061 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7065 ULARGE_INTEGER wapi_free_bytes_avail;
7066 ULARGE_INTEGER wapi_total_number_of_bytes;
7067 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7069 *error = ERROR_SUCCESS;
7070 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7071 &wapi_total_number_of_free_bytes);
7074 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7075 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7076 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7078 *free_bytes_avail = 0;
7079 *total_number_of_bytes = 0;
7080 *total_number_of_free_bytes = 0;
7081 *error = GetLastError ();
7087 ICALL_EXPORT guint32
7088 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7090 return GetDriveType (mono_string_chars (root_path_name));
7094 ICALL_EXPORT gpointer
7095 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7097 return mono_compile_method (method);
7100 ICALL_EXPORT MonoString *
7101 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7106 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7108 #if defined (HOST_WIN32)
7109 /* Avoid mixing '/' and '\\' */
7112 for (i = strlen (path) - 1; i >= 0; i--)
7113 if (path [i] == '/')
7117 mcpath = mono_string_new (mono_domain_get (), path);
7124 get_bundled_app_config (void)
7126 const gchar *app_config;
7129 gchar *config_file_name, *config_file_path;
7130 gsize len, config_file_path_length, config_ext_length;
7133 domain = mono_domain_get ();
7134 file = domain->setup->configuration_file;
7135 if (!file || file->length == 0)
7138 // Retrieve config file and remove the extension
7139 config_file_name = mono_string_to_utf8 (file);
7140 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7141 if (!config_file_path)
7142 config_file_path = config_file_name;
7144 config_file_path_length = strlen (config_file_path);
7145 config_ext_length = strlen (".config");
7146 if (config_file_path_length <= config_ext_length)
7149 len = config_file_path_length - config_ext_length;
7150 module = (gchar *)g_malloc0 (len + 1);
7151 memcpy (module, config_file_path, len);
7152 // Get the config file from the module name
7153 app_config = mono_config_string_for_assembly_file (module);
7156 if (config_file_name != config_file_path)
7157 g_free (config_file_name);
7158 g_free (config_file_path);
7163 return mono_string_new (mono_domain_get (), app_config);
7167 get_bundled_machine_config (void)
7169 const gchar *machine_config;
7171 machine_config = mono_get_machine_config ();
7173 if (!machine_config)
7176 return mono_string_new (mono_domain_get (), machine_config);
7179 ICALL_EXPORT MonoString *
7180 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7185 path = g_path_get_dirname (mono_get_config_dir ());
7187 #if defined (HOST_WIN32)
7188 /* Avoid mixing '/' and '\\' */
7191 for (i = strlen (path) - 1; i >= 0; i--)
7192 if (path [i] == '/')
7196 ipath = mono_string_new (mono_domain_get (), path);
7202 ICALL_EXPORT gboolean
7203 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7205 MonoPEResourceDataEntry *entry;
7208 if (!assembly || !result || !size)
7213 image = assembly->assembly->image;
7214 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7218 *result = mono_image_rva_map (image, entry->rde_data_offset);
7223 *size = entry->rde_size;
7228 ICALL_EXPORT MonoBoolean
7229 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7231 return mono_is_debugger_attached ();
7234 ICALL_EXPORT MonoBoolean
7235 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7237 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7238 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7244 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7246 if (mono_get_runtime_callbacks ()->debug_log)
7247 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7251 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7253 #if defined (HOST_WIN32)
7254 OutputDebugString (mono_string_chars (message));
7256 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7260 /* Only used for value types */
7261 ICALL_EXPORT MonoObject *
7262 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7269 domain = mono_object_domain (type);
7270 klass = mono_class_from_mono_type (type->type);
7271 mono_class_init_checked (klass, &error);
7272 mono_error_raise_exception (&error);
7274 if (mono_class_is_nullable (klass))
7275 /* No arguments -> null */
7278 result = mono_object_new_checked (domain, klass, &error);
7279 mono_error_raise_exception (&error);
7283 ICALL_EXPORT MonoReflectionMethod *
7284 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7286 MonoReflectionMethod *ret = NULL;
7289 MonoClass *klass, *parent;
7290 MonoGenericContext *generic_inst = NULL;
7291 MonoMethod *method = m->method;
7292 MonoMethod *result = NULL;
7295 if (method->klass == NULL)
7298 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7299 MONO_CLASS_IS_INTERFACE (method->klass) ||
7300 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7303 slot = mono_method_get_vtable_slot (method);
7307 klass = method->klass;
7308 if (klass->generic_class) {
7309 generic_inst = mono_class_get_context (klass);
7310 klass = klass->generic_class->container_class;
7314 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7315 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7316 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7317 or klass is the generic container class and generic_inst is the instantiation.
7319 when we go to the parent, if the parent is an open constructed type, we need to
7320 replace the type parameters by the definitions from the generic_inst, and then take it
7321 apart again into the klass and the generic_inst.
7323 For cases like this:
7324 class C<T> : B<T, int> {
7325 public override void Foo () { ... }
7327 class B<U,V> : A<HashMap<U,V>> {
7328 public override void Foo () { ... }
7331 public virtual void Foo () { ... }
7334 if at each iteration the parent isn't open, we can skip inflating it. if at some
7335 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7338 MonoGenericContext *parent_inst = NULL;
7339 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7341 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7342 if (!mono_error_ok (&error)) {
7343 mono_error_set_pending_exception (&error);
7347 if (parent->generic_class) {
7348 parent_inst = mono_class_get_context (parent);
7349 parent = parent->generic_class->container_class;
7352 mono_class_setup_vtable (parent);
7353 if (parent->vtable_size <= slot)
7356 generic_inst = parent_inst;
7359 klass = klass->parent;
7362 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7363 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7364 if (!mono_error_ok (&error)) {
7365 mono_error_set_pending_exception (&error);
7369 generic_inst = NULL;
7371 if (klass->generic_class) {
7372 generic_inst = mono_class_get_context (klass);
7373 klass = klass->generic_class->container_class;
7379 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7380 if (!mono_error_ok (&error)) {
7381 mono_error_set_pending_exception (&error);
7386 if (klass == method->klass)
7389 /*This is possible if definition == FALSE.
7390 * Do it here to be really sure we don't read invalid memory.
7392 if (slot >= klass->vtable_size)
7395 mono_class_setup_vtable (klass);
7397 result = klass->vtable [slot];
7398 if (result == NULL) {
7399 /* It is an abstract method */
7400 gpointer iter = NULL;
7401 while ((result = mono_class_get_methods (klass, &iter)))
7402 if (result->slot == slot)
7409 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7410 mono_error_raise_exception (&error);
7414 ICALL_EXPORT MonoString*
7415 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7417 MonoMethod *method = m->method;
7419 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7424 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7426 iter->sig = *(MonoMethodSignature**)argsp;
7428 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7429 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7432 /* FIXME: it's not documented what start is exactly... */
7436 iter->args = argsp + sizeof (gpointer);
7438 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7440 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7443 ICALL_EXPORT MonoTypedRef
7444 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7446 guint32 i, arg_size;
7450 i = iter->sig->sentinelpos + iter->next_arg;
7452 g_assert (i < iter->sig->param_count);
7454 res.type = iter->sig->params [i];
7455 res.klass = mono_class_from_mono_type (res.type);
7456 arg_size = mono_type_stack_size (res.type, &align);
7457 #if defined(__arm__) || defined(__mips__)
7458 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7460 res.value = iter->args;
7461 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7462 /* Values are stored as 8 byte register sized objects, but 'value'
7463 * is dereferenced as a pointer in other routines.
7465 res.value = (char*)res.value + 4;
7467 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7468 if (arg_size <= sizeof (gpointer)) {
7470 int padding = arg_size - mono_type_size (res.type, &dummy);
7471 res.value = (guint8*)res.value + padding;
7474 iter->args = (char*)iter->args + arg_size;
7477 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7482 ICALL_EXPORT MonoTypedRef
7483 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7485 guint32 i, arg_size;
7489 i = iter->sig->sentinelpos + iter->next_arg;
7491 g_assert (i < iter->sig->param_count);
7493 while (i < iter->sig->param_count) {
7494 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7496 res.type = iter->sig->params [i];
7497 res.klass = mono_class_from_mono_type (res.type);
7498 /* FIXME: endianess issue... */
7499 arg_size = mono_type_stack_size (res.type, &align);
7500 #if defined(__arm__) || defined(__mips__)
7501 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7503 res.value = iter->args;
7504 iter->args = (char*)iter->args + arg_size;
7506 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7509 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7517 ICALL_EXPORT MonoType*
7518 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7522 i = iter->sig->sentinelpos + iter->next_arg;
7524 g_assert (i < iter->sig->param_count);
7526 return iter->sig->params [i];
7529 ICALL_EXPORT MonoObject*
7530 mono_TypedReference_ToObject (MonoTypedRef* tref)
7532 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7533 MonoObject** objp = (MonoObject **)tref->value;
7537 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
7540 ICALL_EXPORT MonoTypedRef
7541 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7544 MonoReflectionField *f;
7546 MonoType *ftype = NULL;
7550 memset (&res, 0, sizeof (res));
7553 g_assert (mono_array_length (fields) > 0);
7555 klass = target->vtable->klass;
7557 for (i = 0; i < mono_array_length (fields); ++i) {
7558 f = mono_array_get (fields, MonoReflectionField*, i);
7560 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7563 if (f->field->parent != klass) {
7564 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7568 p = (guint8*)target + f->field->offset;
7570 p += f->field->offset - sizeof (MonoObject);
7571 klass = mono_class_from_mono_type (f->field->type);
7572 ftype = f->field->type;
7576 res.klass = mono_class_from_mono_type (ftype);
7583 prelink_method (MonoMethod *method, MonoError *error)
7585 const char *exc_class, *exc_arg;
7587 mono_error_init (error);
7588 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7590 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7592 mono_error_set_exception_instance (error,
7593 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7596 /* create the wrapper, too? */
7600 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7604 prelink_method (method->method, &error);
7605 mono_error_raise_exception (&error);
7609 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7612 MonoClass *klass = mono_class_from_mono_type (type->type);
7614 gpointer iter = NULL;
7616 mono_class_init_checked (klass, &error);
7617 mono_error_raise_exception (&error);
7619 while ((m = mono_class_get_methods (klass, &iter))) {
7620 prelink_method (m, &error);
7621 mono_error_raise_exception (&error);
7625 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7627 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7628 gint32 const **exponents,
7629 gunichar2 const **digitLowerTable,
7630 gunichar2 const **digitUpperTable,
7631 gint64 const **tenPowersList,
7632 gint32 const **decHexDigits)
7634 *mantissas = Formatter_MantissaBitsTable;
7635 *exponents = Formatter_TensExponentTable;
7636 *digitLowerTable = Formatter_DigitLowerTable;
7637 *digitUpperTable = Formatter_DigitUpperTable;
7638 *tenPowersList = Formatter_TenPowersList;
7639 *decHexDigits = Formatter_DecHexDigits;
7643 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7644 * and avoid useless allocations.
7647 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7649 MonoReflectionType *rt;
7653 mono_error_init (error);
7654 for (i = 0; i < type->num_mods; ++i) {
7655 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7660 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7662 for (i = 0; i < type->num_mods; ++i) {
7663 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7664 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7665 return_val_if_nok (error, NULL);
7667 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7668 return_val_if_nok (error, NULL);
7670 mono_array_setref (res, count, rt);
7677 ICALL_EXPORT MonoArray*
7678 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7681 MonoType *type = param->ClassImpl->type;
7682 MonoClass *member_class = mono_object_class (param->MemberImpl);
7683 MonoMethod *method = NULL;
7686 MonoMethodSignature *sig;
7689 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7690 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7691 method = rmethod->method;
7692 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7693 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7694 if (!(method = prop->property->get))
7695 method = prop->property->set;
7698 char *type_name = mono_type_get_full_name (member_class);
7699 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7700 MonoException *ex = mono_get_exception_not_supported (msg);
7703 mono_set_pending_exception (ex);
7707 image = method->klass->image;
7708 pos = param->PositionImpl;
7709 sig = mono_method_signature (method);
7713 type = sig->params [pos];
7715 res = type_array_from_modifiers (image, type, optional, &error);
7716 mono_error_raise_exception (&error);
7721 get_property_type (MonoProperty *prop)
7723 MonoMethodSignature *sig;
7725 sig = mono_method_signature (prop->get);
7727 } else if (prop->set) {
7728 sig = mono_method_signature (prop->set);
7729 return sig->params [sig->param_count - 1];
7734 ICALL_EXPORT MonoArray*
7735 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7738 MonoType *type = get_property_type (property->property);
7739 MonoImage *image = property->klass->image;
7744 res = type_array_from_modifiers (image, type, optional, &error);
7745 mono_error_raise_exception (&error);
7750 *Construct a MonoType suited to be used to decode a constant blob object.
7752 * @type is the target type which will be constructed
7753 * @blob_type is the blob type, for example, that comes from the constant table
7754 * @real_type is the expected constructed type.
7757 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7759 type->type = blob_type;
7760 type->data.klass = NULL;
7761 if (blob_type == MONO_TYPE_CLASS)
7762 type->data.klass = mono_defaults.object_class;
7763 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7764 /* For enums, we need to use the base type */
7765 type->type = MONO_TYPE_VALUETYPE;
7766 type->data.klass = mono_class_from_mono_type (real_type);
7768 type->data.klass = mono_class_from_mono_type (real_type);
7771 ICALL_EXPORT MonoObject*
7772 property_info_get_default_value (MonoReflectionProperty *property)
7776 MonoProperty *prop = property->property;
7777 MonoType *type = get_property_type (prop);
7778 MonoDomain *domain = mono_object_domain (property);
7779 MonoTypeEnum def_type;
7780 const char *def_value;
7783 mono_class_init (prop->parent);
7785 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7786 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7790 def_value = mono_class_get_property_default_value (prop, &def_type);
7792 mono_type_from_blob_type (&blob_type, def_type, type);
7793 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7795 mono_error_set_pending_exception (&error);
7799 ICALL_EXPORT MonoBoolean
7800 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7803 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7804 MonoCustomAttrInfo *cinfo;
7807 mono_class_init_checked (attr_class, &error);
7808 mono_error_raise_exception (&error);
7810 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7811 if (!is_ok (&error)) {
7812 mono_error_set_pending_exception (&error);
7817 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7819 mono_custom_attrs_free (cinfo);
7823 ICALL_EXPORT MonoArray*
7824 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7826 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7831 mono_class_init_checked (attr_class, &error);
7832 mono_error_raise_exception (&error);
7835 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7836 if (!mono_error_ok (&error)) {
7837 mono_error_set_pending_exception (&error);
7841 if (mono_loader_get_last_error ()) {
7842 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7849 ICALL_EXPORT MonoArray*
7850 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7854 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7855 mono_error_set_pending_exception (&error);
7860 ICALL_EXPORT MonoString*
7861 ves_icall_Mono_Runtime_GetDisplayName (void)
7864 MonoString *display_name;
7866 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7867 display_name = mono_string_new (mono_domain_get (), info);
7869 return display_name;
7872 ICALL_EXPORT MonoString*
7873 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7876 MonoString *message;
7880 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7881 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7884 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7886 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7887 mono_error_raise_exception (&error);
7894 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7897 char *path_str = mono_string_to_utf8 (path);
7899 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7907 ICALL_EXPORT gpointer
7908 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
7910 return GetCurrentProcess ();
7913 ICALL_EXPORT MonoBoolean
7914 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
7916 return GetExitCodeProcess (handle, (guint32*) exitcode);
7919 ICALL_EXPORT MonoBoolean
7920 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
7922 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
7923 return CloseHandle (handle);
7925 return CloseProcess (handle);
7929 ICALL_EXPORT MonoBoolean
7930 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
7932 return TerminateProcess (handle, exitcode);
7936 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
7938 return WaitForInputIdle (handle, milliseconds);
7941 ICALL_EXPORT MonoBoolean
7942 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
7944 return GetProcessWorkingSetSize (handle, min, max);
7947 ICALL_EXPORT MonoBoolean
7948 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
7950 return SetProcessWorkingSetSize (handle, min, max);
7953 ICALL_EXPORT MonoBoolean
7954 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
7956 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
7960 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
7962 return mono_process_current_pid ();
7966 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
7968 return GetPriorityClass (handle);
7971 ICALL_EXPORT MonoBoolean
7972 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
7974 return SetPriorityClass (handle, priorityClass);
7977 #ifndef DISABLE_ICALL_TABLES
7979 #define ICALL_TYPE(id,name,first)
7980 #define ICALL(id,name,func) Icall_ ## id,
7983 #include "metadata/icall-def.h"
7989 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7990 #define ICALL(id,name,func)
7992 #include "metadata/icall-def.h"
7998 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7999 #define ICALL(id,name,func)
8001 guint16 first_icall;
8004 static const IcallTypeDesc
8005 icall_type_descs [] = {
8006 #include "metadata/icall-def.h"
8010 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8013 #define ICALL_TYPE(id,name,first)
8016 #ifdef HAVE_ARRAY_ELEM_INIT
8017 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8018 #define MSGSTRFIELD1(line) str##line
8020 static const struct msgstrtn_t {
8021 #define ICALL(id,name,func)
8023 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8024 #include "metadata/icall-def.h"
8026 } icall_type_names_str = {
8027 #define ICALL_TYPE(id,name,first) (name),
8028 #include "metadata/icall-def.h"
8031 static const guint16 icall_type_names_idx [] = {
8032 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8033 #include "metadata/icall-def.h"
8036 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8038 static const struct msgstr_t {
8040 #define ICALL_TYPE(id,name,first)
8041 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8042 #include "metadata/icall-def.h"
8044 } icall_names_str = {
8045 #define ICALL(id,name,func) (name),
8046 #include "metadata/icall-def.h"
8049 static const guint16 icall_names_idx [] = {
8050 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8051 #include "metadata/icall-def.h"
8054 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8060 #define ICALL_TYPE(id,name,first) name,
8061 #define ICALL(id,name,func)
8062 static const char* const
8063 icall_type_names [] = {
8064 #include "metadata/icall-def.h"
8068 #define icall_type_name_get(id) (icall_type_names [(id)])
8072 #define ICALL_TYPE(id,name,first)
8073 #define ICALL(id,name,func) name,
8074 static const char* const
8076 #include "metadata/icall-def.h"
8079 #define icall_name_get(id) icall_names [(id)]
8081 #endif /* !HAVE_ARRAY_ELEM_INIT */
8085 #define ICALL_TYPE(id,name,first)
8086 #define ICALL(id,name,func) func,
8087 static const gconstpointer
8088 icall_functions [] = {
8089 #include "metadata/icall-def.h"
8093 #ifdef ENABLE_ICALL_SYMBOL_MAP
8096 #define ICALL_TYPE(id,name,first)
8097 #define ICALL(id,name,func) #func,
8098 static const gconstpointer
8099 icall_symbols [] = {
8100 #include "metadata/icall-def.h"
8105 #endif /* DISABLE_ICALL_TABLES */
8107 static mono_mutex_t icall_mutex;
8108 static GHashTable *icall_hash = NULL;
8109 static GHashTable *jit_icall_hash_name = NULL;
8110 static GHashTable *jit_icall_hash_addr = NULL;
8113 mono_icall_init (void)
8115 #ifndef DISABLE_ICALL_TABLES
8118 /* check that tables are sorted: disable in release */
8121 const char *prev_class = NULL;
8122 const char *prev_method;
8124 for (i = 0; i < Icall_type_num; ++i) {
8125 const IcallTypeDesc *desc;
8128 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8129 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8130 prev_class = icall_type_name_get (i);
8131 desc = &icall_type_descs [i];
8132 num_icalls = icall_desc_num_icalls (desc);
8133 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8134 for (j = 0; j < num_icalls; ++j) {
8135 const char *methodn = icall_name_get (desc->first_icall + j);
8136 if (prev_method && strcmp (prev_method, methodn) >= 0)
8137 g_print ("method %s should come before method %s\n", methodn, prev_method);
8138 prev_method = methodn;
8144 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8145 mono_os_mutex_init (&icall_mutex);
8149 mono_icall_lock (void)
8151 mono_locks_os_acquire (&icall_mutex, IcallLock);
8155 mono_icall_unlock (void)
8157 mono_locks_os_release (&icall_mutex, IcallLock);
8161 mono_icall_cleanup (void)
8163 g_hash_table_destroy (icall_hash);
8164 g_hash_table_destroy (jit_icall_hash_name);
8165 g_hash_table_destroy (jit_icall_hash_addr);
8166 mono_os_mutex_destroy (&icall_mutex);
8170 * mono_add_internal_call:
8171 * @name: method specification to surface to the managed world
8172 * @method: pointer to a C method to invoke when the method is called
8174 * This method surfaces the C function pointed by @method as a method
8175 * that has been surfaced in managed code with the method specified in
8176 * @name as an internal call.
8178 * Internal calls are surfaced to all app domains loaded and they are
8179 * accessibly by a type with the specified name.
8181 * You must provide a fully qualified type name, that is namespaces
8182 * and type name, followed by a colon and the method name, with an
8183 * optional signature to bind.
8185 * For example, the following are all valid declarations:
8187 * "MyApp.Services.ScriptService:Accelerate"
8188 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8190 * You use method parameters in cases where there might be more than
8191 * one surface method to managed code. That way you can register different
8192 * internal calls for different method overloads.
8194 * The internal calls are invoked with no marshalling. This means that .NET
8195 * types like System.String are exposed as `MonoString *` parameters. This is
8196 * different than the way that strings are surfaced in P/Invoke.
8198 * For more information on how the parameters are marshalled, see the
8199 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8202 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8203 * reference for more information on the format of method descriptions.
8206 mono_add_internal_call (const char *name, gconstpointer method)
8210 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8212 mono_icall_unlock ();
8215 #ifndef DISABLE_ICALL_TABLES
8217 #ifdef HAVE_ARRAY_ELEM_INIT
8219 compare_method_imap (const void *key, const void *elem)
8221 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8222 return strcmp (key, method_name);
8226 find_method_icall (const IcallTypeDesc *imap, const char *name)
8228 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);
8231 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8235 compare_class_imap (const void *key, const void *elem)
8237 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8238 return strcmp (key, class_name);
8241 static const IcallTypeDesc*
8242 find_class_icalls (const char *name)
8244 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);
8247 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8250 #else /* HAVE_ARRAY_ELEM_INIT */
8253 compare_method_imap (const void *key, const void *elem)
8255 const char** method_name = (const char**)elem;
8256 return strcmp (key, *method_name);
8260 find_method_icall (const IcallTypeDesc *imap, const char *name)
8262 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8265 return (gpointer)icall_functions [(nameslot - icall_names)];
8269 compare_class_imap (const void *key, const void *elem)
8271 const char** class_name = (const char**)elem;
8272 return strcmp (key, *class_name);
8275 static const IcallTypeDesc*
8276 find_class_icalls (const char *name)
8278 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8281 return &icall_type_descs [nameslot - icall_type_names];
8284 #endif /* HAVE_ARRAY_ELEM_INIT */
8286 #endif /* DISABLE_ICALL_TABLES */
8289 * we should probably export this as an helper (handle nested types).
8290 * Returns the number of chars written in buf.
8293 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8295 int nspacelen, cnamelen;
8296 nspacelen = strlen (klass->name_space);
8297 cnamelen = strlen (klass->name);
8298 if (nspacelen + cnamelen + 2 > bufsize)
8301 memcpy (buf, klass->name_space, nspacelen);
8302 buf [nspacelen ++] = '.';
8304 memcpy (buf + nspacelen, klass->name, cnamelen);
8305 buf [nspacelen + cnamelen] = 0;
8306 return nspacelen + cnamelen;
8309 #ifdef DISABLE_ICALL_TABLES
8311 no_icall_table (void)
8313 g_assert_not_reached ();
8318 mono_lookup_internal_call (MonoMethod *method)
8323 int typelen = 0, mlen, siglen;
8325 #ifndef DISABLE_ICALL_TABLES
8326 const IcallTypeDesc *imap = NULL;
8329 g_assert (method != NULL);
8331 if (method->is_inflated)
8332 method = ((MonoMethodInflated *) method)->declaring;
8334 if (method->klass->nested_in) {
8335 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8339 mname [pos++] = '/';
8342 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8348 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8353 #ifndef DISABLE_ICALL_TABLES
8354 imap = find_class_icalls (mname);
8357 mname [typelen] = ':';
8358 mname [typelen + 1] = ':';
8360 mlen = strlen (method->name);
8361 memcpy (mname + typelen + 2, method->name, mlen);
8362 sigstart = mname + typelen + 2 + mlen;
8365 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8366 siglen = strlen (tmpsig);
8367 if (typelen + mlen + siglen + 6 > sizeof (mname))
8370 memcpy (sigstart + 1, tmpsig, siglen);
8371 sigstart [siglen + 1] = ')';
8372 sigstart [siglen + 2] = 0;
8377 res = g_hash_table_lookup (icall_hash, mname);
8379 mono_icall_unlock ();;
8382 /* try without signature */
8384 res = g_hash_table_lookup (icall_hash, mname);
8386 mono_icall_unlock ();
8390 #ifdef DISABLE_ICALL_TABLES
8391 mono_icall_unlock ();
8392 /* Fail only when the result is actually used */
8393 /* mono_marshal_get_native_wrapper () depends on this */
8394 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8395 return ves_icall_System_String_ctor_RedirectToCreateString;
8397 return no_icall_table;
8399 /* it wasn't found in the static call tables */
8401 mono_icall_unlock ();
8404 res = find_method_icall (imap, sigstart - mlen);
8406 mono_icall_unlock ();
8409 /* try _with_ signature */
8411 res = find_method_icall (imap, sigstart - mlen);
8413 mono_icall_unlock ();
8417 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8418 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8419 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8420 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8421 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");
8422 g_print ("If you see other errors or faults after this message they are probably related\n");
8423 g_print ("and you need to fix your mono install first.\n");
8425 mono_icall_unlock ();
8431 #ifdef ENABLE_ICALL_SYMBOL_MAP
8433 func_cmp (gconstpointer key, gconstpointer p)
8435 return (gsize)key - (gsize)*(gsize*)p;
8440 * mono_lookup_icall_symbol:
8442 * Given the icall METHOD, returns its C symbol.
8445 mono_lookup_icall_symbol (MonoMethod *m)
8447 #ifdef DISABLE_ICALL_TABLES
8448 g_assert_not_reached ();
8451 #ifdef ENABLE_ICALL_SYMBOL_MAP
8455 static gconstpointer *functions_sorted;
8456 static const char**symbols_sorted;
8457 static gboolean inited;
8462 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8463 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8464 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8465 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8466 /* Bubble sort the two arrays */
8470 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8471 if (functions_sorted [i] > functions_sorted [i + 1]) {
8474 tmp = functions_sorted [i];
8475 functions_sorted [i] = functions_sorted [i + 1];
8476 functions_sorted [i + 1] = tmp;
8477 tmp = symbols_sorted [i];
8478 symbols_sorted [i] = symbols_sorted [i + 1];
8479 symbols_sorted [i + 1] = tmp;
8486 func = mono_lookup_internal_call (m);
8489 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8493 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8495 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8496 g_assert_not_reached ();
8503 type_from_typename (char *type_name)
8505 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8507 if (!strcmp (type_name, "int"))
8508 klass = mono_defaults.int_class;
8509 else if (!strcmp (type_name, "ptr"))
8510 klass = mono_defaults.int_class;
8511 else if (!strcmp (type_name, "void"))
8512 klass = mono_defaults.void_class;
8513 else if (!strcmp (type_name, "int32"))
8514 klass = mono_defaults.int32_class;
8515 else if (!strcmp (type_name, "uint32"))
8516 klass = mono_defaults.uint32_class;
8517 else if (!strcmp (type_name, "int8"))
8518 klass = mono_defaults.sbyte_class;
8519 else if (!strcmp (type_name, "uint8"))
8520 klass = mono_defaults.byte_class;
8521 else if (!strcmp (type_name, "int16"))
8522 klass = mono_defaults.int16_class;
8523 else if (!strcmp (type_name, "uint16"))
8524 klass = mono_defaults.uint16_class;
8525 else if (!strcmp (type_name, "long"))
8526 klass = mono_defaults.int64_class;
8527 else if (!strcmp (type_name, "ulong"))
8528 klass = mono_defaults.uint64_class;
8529 else if (!strcmp (type_name, "float"))
8530 klass = mono_defaults.single_class;
8531 else if (!strcmp (type_name, "double"))
8532 klass = mono_defaults.double_class;
8533 else if (!strcmp (type_name, "object"))
8534 klass = mono_defaults.object_class;
8535 else if (!strcmp (type_name, "obj"))
8536 klass = mono_defaults.object_class;
8537 else if (!strcmp (type_name, "string"))
8538 klass = mono_defaults.string_class;
8539 else if (!strcmp (type_name, "bool"))
8540 klass = mono_defaults.boolean_class;
8541 else if (!strcmp (type_name, "boolean"))
8542 klass = mono_defaults.boolean_class;
8544 g_error ("%s", type_name);
8545 g_assert_not_reached ();
8547 return &klass->byval_arg;
8551 * LOCKING: Take the corlib image lock.
8553 MonoMethodSignature*
8554 mono_create_icall_signature (const char *sigstr)
8559 MonoMethodSignature *res, *res2;
8560 MonoImage *corlib = mono_defaults.corlib;
8562 mono_image_lock (corlib);
8563 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8564 mono_image_unlock (corlib);
8569 parts = g_strsplit (sigstr, " ", 256);
8578 res = mono_metadata_signature_alloc (corlib, len - 1);
8583 * Under windows, the default pinvoke calling convention is STDCALL but
8586 res->call_convention = MONO_CALL_C;
8589 res->ret = type_from_typename (parts [0]);
8590 for (i = 1; i < len; ++i) {
8591 res->params [i - 1] = type_from_typename (parts [i]);
8596 mono_image_lock (corlib);
8597 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8599 res = res2; /*Value is allocated in the image pool*/
8601 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8602 mono_image_unlock (corlib);
8608 mono_find_jit_icall_by_name (const char *name)
8610 MonoJitICallInfo *info;
8611 g_assert (jit_icall_hash_name);
8614 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8615 mono_icall_unlock ();
8620 mono_find_jit_icall_by_addr (gconstpointer addr)
8622 MonoJitICallInfo *info;
8623 g_assert (jit_icall_hash_addr);
8626 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8627 mono_icall_unlock ();
8633 * mono_get_jit_icall_info:
8635 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8636 * caller should access it while holding the icall lock.
8639 mono_get_jit_icall_info (void)
8641 return jit_icall_hash_name;
8645 * mono_lookup_jit_icall_symbol:
8647 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8650 mono_lookup_jit_icall_symbol (const char *name)
8652 MonoJitICallInfo *info;
8653 const char *res = NULL;
8656 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8658 res = info->c_symbol;
8659 mono_icall_unlock ();
8664 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8667 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8668 mono_icall_unlock ();
8672 * 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
8673 * icalls without wrappers in some cases.
8676 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8678 MonoJitICallInfo *info;
8685 if (!jit_icall_hash_name) {
8686 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8687 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8690 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8691 g_warning ("jit icall already defined \"%s\"\n", name);
8692 g_assert_not_reached ();
8695 info = g_new0 (MonoJitICallInfo, 1);
8700 info->c_symbol = c_symbol;
8701 info->no_raise = no_raise;
8704 info->wrapper = func;
8706 info->wrapper = NULL;
8709 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8710 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8712 mono_icall_unlock ();
8717 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8719 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);