5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
9 * Aleksey Kliger (aleksey@xamarin.com)
11 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
12 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
24 #ifdef HAVE_SYS_TIME_H
30 #if defined (HOST_WIN32)
33 #if defined (HAVE_WCHAR_H)
37 #include "mono/utils/mono-membar.h"
38 #include <mono/metadata/object.h>
39 #include <mono/metadata/threads.h>
40 #include <mono/metadata/threads-types.h>
41 #include <mono/metadata/threadpool-ms.h>
42 #include <mono/metadata/threadpool-ms-io.h>
43 #include <mono/metadata/monitor.h>
44 #include <mono/metadata/reflection.h>
45 #include <mono/metadata/assembly.h>
46 #include <mono/metadata/tabledefs.h>
47 #include <mono/metadata/exception.h>
48 #include <mono/metadata/exception-internals.h>
49 #include <mono/metadata/file-io.h>
50 #include <mono/metadata/console-io.h>
51 #include <mono/metadata/mono-route.h>
52 #include <mono/metadata/socket-io.h>
53 #include <mono/metadata/mono-endian.h>
54 #include <mono/metadata/tokentype.h>
55 #include <mono/metadata/domain-internals.h>
56 #include <mono/metadata/metadata-internals.h>
57 #include <mono/metadata/class-internals.h>
58 #include <mono/metadata/reflection-internals.h>
59 #include <mono/metadata/marshal.h>
60 #include <mono/metadata/gc-internals.h>
61 #include <mono/metadata/mono-gc.h>
62 #include <mono/metadata/rand.h>
63 #include <mono/metadata/sysmath.h>
64 #include <mono/metadata/string-icalls.h>
65 #include <mono/metadata/debug-helpers.h>
66 #include <mono/metadata/process.h>
67 #include <mono/metadata/environment.h>
68 #include <mono/metadata/profiler-private.h>
69 #include <mono/metadata/locales.h>
70 #include <mono/metadata/filewatcher.h>
71 #include <mono/metadata/security.h>
72 #include <mono/metadata/mono-config.h>
73 #include <mono/metadata/cil-coff.h>
74 #include <mono/metadata/number-formatter.h>
75 #include <mono/metadata/security-manager.h>
76 #include <mono/metadata/security-core-clr.h>
77 #include <mono/metadata/mono-perfcounters.h>
78 #include <mono/metadata/mono-debug.h>
79 #include <mono/metadata/mono-ptr-array.h>
80 #include <mono/metadata/verify-internals.h>
81 #include <mono/metadata/runtime.h>
82 #include <mono/metadata/file-mmap.h>
83 #include <mono/metadata/seq-points-data.h>
84 #include <mono/io-layer/io-layer.h>
85 #include <mono/utils/monobitset.h>
86 #include <mono/utils/mono-time.h>
87 #include <mono/utils/mono-proclib.h>
88 #include <mono/utils/mono-string.h>
89 #include <mono/utils/mono-error-internals.h>
90 #include <mono/utils/mono-mmap.h>
91 #include <mono/utils/mono-io-portability.h>
92 #include <mono/utils/mono-digest.h>
93 #include <mono/utils/bsearch.h>
94 #include <mono/utils/mono-os-mutex.h>
95 #include <mono/utils/mono-threads.h>
97 #if defined (HOST_WIN32)
101 #include "decimal-ms.h"
102 #include "number-ms.h"
104 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
105 #include <sys/utsname.h>
108 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
110 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
112 /* Lazy class loading functions */
113 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
114 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
115 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
116 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
121 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
123 static inline MonoBoolean
124 is_generic_parameter (MonoType *type)
126 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
130 mono_class_init_checked (MonoClass *klass, MonoError *error)
132 mono_error_init (error);
134 if (!mono_class_init (klass))
135 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
138 ICALL_EXPORT MonoObject *
139 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
145 ac = (MonoClass *)arr->obj.vtable->klass;
147 esize = mono_array_element_size (ac);
148 ea = (gpointer*)((char*)arr->vector + (pos * esize));
150 if (ac->element_class->valuetype)
151 return mono_value_box (arr->obj.vtable->domain, ac->element_class, ea);
153 return (MonoObject *)*ea;
156 ICALL_EXPORT MonoObject *
157 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
163 MONO_CHECK_ARG_NULL (idxs, NULL);
166 ic = (MonoClass *)io->obj.vtable->klass;
168 ac = (MonoClass *)arr->obj.vtable->klass;
170 g_assert (ic->rank == 1);
171 if (io->bounds != NULL || io->max_length != ac->rank) {
172 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
176 ind = (gint32 *)io->vector;
178 if (arr->bounds == NULL) {
179 if (*ind < 0 || *ind >= arr->max_length) {
180 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
184 return ves_icall_System_Array_GetValueImpl (arr, *ind);
187 for (i = 0; i < ac->rank; i++) {
188 if ((ind [i] < arr->bounds [i].lower_bound) ||
189 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
190 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
195 pos = ind [0] - arr->bounds [0].lower_bound;
196 for (i = 1; i < ac->rank; i++)
197 pos = pos * arr->bounds [i].length + ind [i] -
198 arr->bounds [i].lower_bound;
200 return ves_icall_System_Array_GetValueImpl (arr, pos);
204 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
206 MonoClass *ac, *vc, *ec;
216 vc = value->vtable->klass;
220 ac = arr->obj.vtable->klass;
221 ec = ac->element_class;
223 esize = mono_array_element_size (ac);
224 ea = (gpointer*)((char*)arr->vector + (pos * esize));
225 va = (gpointer*)((char*)value + sizeof (MonoObject));
227 if (mono_class_is_nullable (ec)) {
228 mono_nullable_init ((guint8*)ea, value, ec);
233 mono_gc_bzero_atomic (ea, esize);
237 #define NO_WIDENING_CONVERSION G_STMT_START{\
238 mono_set_pending_exception (mono_get_exception_argument ( \
239 "value", "not a widening conversion")); \
243 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
244 if (esize < vsize + (extra)) { \
245 mono_set_pending_exception (mono_get_exception_argument ( \
246 "value", "not a widening conversion")); \
251 #define INVALID_CAST G_STMT_START{ \
252 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
253 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
257 /* Check element (destination) type. */
258 switch (ec->byval_arg.type) {
259 case MONO_TYPE_STRING:
260 switch (vc->byval_arg.type) {
261 case MONO_TYPE_STRING:
267 case MONO_TYPE_BOOLEAN:
268 switch (vc->byval_arg.type) {
269 case MONO_TYPE_BOOLEAN:
282 NO_WIDENING_CONVERSION;
291 if (!ec->valuetype) {
292 if (!mono_object_isinst (value, ec))
294 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
298 if (mono_object_isinst (value, ec)) {
299 if (ec->has_references)
300 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
302 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
309 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
311 et = ec->byval_arg.type;
312 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
313 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
315 vt = vc->byval_arg.type;
316 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
317 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
319 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
325 case MONO_TYPE_CHAR: \
326 CHECK_WIDENING_CONVERSION(0); \
327 *(etype *) ea = (etype) u64; \
329 /* You can't assign a signed value to an unsigned array. */ \
334 /* You can't assign a floating point number to an integer array. */ \
337 NO_WIDENING_CONVERSION; \
341 #define ASSIGN_SIGNED(etype) G_STMT_START{\
347 CHECK_WIDENING_CONVERSION(0); \
348 *(etype *) ea = (etype) i64; \
350 /* You can assign an unsigned value to a signed array if the array's */ \
351 /* element size is larger than the value size. */ \
356 case MONO_TYPE_CHAR: \
357 CHECK_WIDENING_CONVERSION(1); \
358 *(etype *) ea = (etype) u64; \
360 /* You can't assign a floating point number to an integer array. */ \
363 NO_WIDENING_CONVERSION; \
367 #define ASSIGN_REAL(etype) G_STMT_START{\
371 CHECK_WIDENING_CONVERSION(0); \
372 *(etype *) ea = (etype) r64; \
374 /* All integer values fit into a floating point array, so we don't */ \
375 /* need to CHECK_WIDENING_CONVERSION here. */ \
380 *(etype *) ea = (etype) i64; \
386 case MONO_TYPE_CHAR: \
387 *(etype *) ea = (etype) u64; \
394 u64 = *(guint8 *) va;
397 u64 = *(guint16 *) va;
400 u64 = *(guint32 *) va;
403 u64 = *(guint64 *) va;
409 i64 = *(gint16 *) va;
412 i64 = *(gint32 *) va;
415 i64 = *(gint64 *) va;
418 r64 = *(gfloat *) va;
421 r64 = *(gdouble *) va;
424 u64 = *(guint16 *) va;
426 case MONO_TYPE_BOOLEAN:
427 /* Boolean is only compatible with itself. */
440 NO_WIDENING_CONVERSION;
447 /* If we can't do a direct copy, let's try a widening conversion. */
450 ASSIGN_UNSIGNED (guint16);
452 ASSIGN_UNSIGNED (guint8);
454 ASSIGN_UNSIGNED (guint16);
456 ASSIGN_UNSIGNED (guint32);
458 ASSIGN_UNSIGNED (guint64);
460 ASSIGN_SIGNED (gint8);
462 ASSIGN_SIGNED (gint16);
464 ASSIGN_SIGNED (gint32);
466 ASSIGN_SIGNED (gint64);
468 ASSIGN_REAL (gfloat);
470 ASSIGN_REAL (gdouble);
474 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
478 #undef NO_WIDENING_CONVERSION
479 #undef CHECK_WIDENING_CONVERSION
480 #undef ASSIGN_UNSIGNED
486 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
492 MONO_CHECK_ARG_NULL (idxs,);
494 ic = idxs->obj.vtable->klass;
495 ac = arr->obj.vtable->klass;
497 g_assert (ic->rank == 1);
498 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
499 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
503 ind = (gint32 *)idxs->vector;
505 if (arr->bounds == NULL) {
506 if (*ind < 0 || *ind >= arr->max_length) {
507 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
511 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
515 for (i = 0; i < ac->rank; i++)
516 if ((ind [i] < arr->bounds [i].lower_bound) ||
517 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
518 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
522 pos = ind [0] - arr->bounds [0].lower_bound;
523 for (i = 1; i < ac->rank; i++)
524 pos = pos * arr->bounds [i].length + ind [i] -
525 arr->bounds [i].lower_bound;
527 ves_icall_System_Array_SetValueImpl (arr, value, pos);
530 ICALL_EXPORT MonoArray *
531 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
534 MonoClass *aklass, *klass;
537 gboolean bounded = FALSE;
539 MONO_CHECK_ARG_NULL (type, NULL);
540 MONO_CHECK_ARG_NULL (lengths, NULL);
542 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
544 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
546 for (i = 0; i < mono_array_length (lengths); i++) {
547 if (mono_array_get (lengths, gint32, i) < 0) {
548 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
553 klass = mono_class_from_mono_type (type->type);
554 mono_class_init_checked (klass, &error);
555 mono_error_raise_exception (&error);
557 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
558 /* vectors are not the same as one dimensional arrays with no-zero bounds */
563 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
565 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
566 for (i = 0; i < aklass->rank; ++i) {
567 sizes [i] = mono_array_get (lengths, guint32, i);
569 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
571 sizes [i + aklass->rank] = 0;
574 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
575 mono_error_set_pending_exception (&error);
580 ICALL_EXPORT MonoArray *
581 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
584 MonoClass *aklass, *klass;
587 gboolean bounded = FALSE;
589 MONO_CHECK_ARG_NULL (type, NULL);
590 MONO_CHECK_ARG_NULL (lengths, NULL);
592 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
594 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
596 for (i = 0; i < mono_array_length (lengths); i++) {
597 if ((mono_array_get (lengths, gint64, i) < 0) ||
598 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
599 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
604 klass = mono_class_from_mono_type (type->type);
605 mono_class_init_checked (klass, &error);
606 mono_error_raise_exception (&error);
608 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
609 /* vectors are not the same as one dimensional arrays with no-zero bounds */
614 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
616 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
617 for (i = 0; i < aklass->rank; ++i) {
618 sizes [i] = mono_array_get (lengths, guint64, i);
620 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
622 sizes [i + aklass->rank] = 0;
625 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
626 mono_error_set_pending_exception (&error);
632 ves_icall_System_Array_GetRank (MonoObject *arr)
634 return arr->vtable->klass->rank;
638 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
640 gint32 rank = arr->obj.vtable->klass->rank;
643 if ((dimension < 0) || (dimension >= rank)) {
644 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
648 if (arr->bounds == NULL)
649 length = arr->max_length;
651 length = arr->bounds [dimension].length;
653 #ifdef MONO_BIG_ARRAYS
654 if (length > G_MAXINT32) {
655 mono_set_pending_exception (mono_get_exception_overflow ());
663 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
665 gint32 rank = arr->obj.vtable->klass->rank;
667 if ((dimension < 0) || (dimension >= rank)) {
668 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
672 if (arr->bounds == NULL)
673 return arr->max_length;
675 return arr->bounds [dimension].length;
679 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
681 gint32 rank = arr->obj.vtable->klass->rank;
683 if ((dimension < 0) || (dimension >= rank)) {
684 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
688 if (arr->bounds == NULL)
691 return arr->bounds [dimension].lower_bound;
695 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
697 int sz = mono_array_element_size (mono_object_class (arr));
698 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
701 ICALL_EXPORT gboolean
702 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
707 MonoVTable *src_vtable;
708 MonoVTable *dest_vtable;
709 MonoClass *src_class;
710 MonoClass *dest_class;
712 src_vtable = source->obj.vtable;
713 dest_vtable = dest->obj.vtable;
715 if (src_vtable->rank != dest_vtable->rank)
718 if (source->bounds || dest->bounds)
721 /* there's no integer overflow since mono_array_length returns an unsigned integer */
722 if ((dest_idx + length > mono_array_length_fast (dest)) ||
723 (source_idx + length > mono_array_length_fast (source)))
726 src_class = src_vtable->klass->element_class;
727 dest_class = dest_vtable->klass->element_class;
730 * Handle common cases.
733 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
734 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
736 if (src_class == mono_defaults.object_class && dest_class->valuetype)
739 /* Check if we're copying a char[] <==> (u)short[] */
740 if (src_class != dest_class) {
741 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
744 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
745 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
749 if (dest_class->valuetype) {
750 element_size = mono_array_element_size (source->obj.vtable->klass);
751 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
752 if (dest_class->has_references) {
753 mono_value_copy_array (dest, dest_idx, source_addr, length);
755 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
756 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
759 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
766 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
772 ac = (MonoClass *)arr->obj.vtable->klass;
774 esize = mono_array_element_size (ac);
775 ea = (gpointer*)((char*)arr->vector + (pos * esize));
777 mono_gc_memmove_atomic (value, ea, esize);
781 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
787 ac = (MonoClass *)arr->obj.vtable->klass;
788 ec = ac->element_class;
790 esize = mono_array_element_size (ac);
791 ea = (gpointer*)((char*)arr->vector + (pos * esize));
793 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
794 g_assert (esize == sizeof (gpointer));
795 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
797 g_assert (ec->inited);
798 g_assert (esize == mono_class_value_size (ec, NULL));
799 if (ec->has_references)
800 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
802 mono_gc_memmove_atomic (ea, value, esize);
807 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
809 MonoClass *klass = array->obj.vtable->klass;
810 guint32 size = mono_array_element_size (klass);
811 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
813 const char *field_data;
815 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
816 MonoException *exc = mono_get_exception_argument("array",
817 "Cannot initialize array of non-primitive type.");
818 mono_set_pending_exception (exc);
822 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
823 MonoException *exc = mono_get_exception_argument("field_handle",
824 "Field doesn't have an RVA");
825 mono_set_pending_exception (exc);
829 size *= array->max_length;
830 field_data = mono_field_get_data (field_handle);
832 if (size > mono_type_size (field_handle->type, &align)) {
833 MonoException *exc = mono_get_exception_argument("field_handle",
834 "Field not large enough to fill array");
835 mono_set_pending_exception (exc);
839 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
841 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
842 guint ## n *src = (guint ## n *) field_data; \
844 nEnt = (size / sizeof(guint ## n)); \
846 for (i = 0; i < nEnt; i++) { \
847 data[i] = read ## n (&src[i]); \
851 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
853 switch (type->type) {
870 memcpy (mono_array_addr (array, char, 0), field_data, size);
874 memcpy (mono_array_addr (array, char, 0), field_data, size);
879 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
881 return offsetof (MonoString, chars);
884 ICALL_EXPORT MonoObject *
885 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
887 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
891 MonoObject *ret = mono_object_clone_checked (obj, &error);
892 mono_error_set_pending_exception (&error);
899 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
905 MONO_CHECK_ARG_NULL (handle,);
907 klass = mono_class_from_mono_type (handle);
908 MONO_CHECK_ARG (handle, klass,);
910 if (klass->generic_container)
913 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
914 if (!is_ok (&error)) {
915 mono_error_set_pending_exception (&error);
919 /* This will call the type constructor */
920 if (!mono_runtime_class_init_full (vtable, &error))
921 mono_error_set_pending_exception (&error);
925 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
929 mono_image_check_for_module_cctor (image);
930 if (image->has_module_cctor) {
931 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
932 if (!mono_error_ok (&error)) {
933 mono_error_set_pending_exception (&error);
936 /*It's fine to raise the exception here*/
937 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
938 if (!is_ok (&error)) {
939 mono_error_set_pending_exception (&error);
942 if (!mono_runtime_class_init_full (vtable, &error))
943 mono_error_set_pending_exception (&error);
947 ICALL_EXPORT MonoBoolean
948 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
953 /* later make this configurable and per-arch */
954 int min_size = 4096 * 4 * sizeof (void*);
955 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
956 /* if we have no info we are optimistic and assume there is enough room */
960 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
964 current = (guint8 *)&stack_addr;
965 if (current > stack_addr) {
966 if ((current - stack_addr) < min_size)
969 if (current - (stack_addr - stack_size) < min_size)
975 ICALL_EXPORT MonoObject *
976 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
979 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
980 mono_error_set_pending_exception (&error);
986 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
989 MonoObject **values = NULL;
992 gint32 result = (int)(gsize)mono_defaults.int32_class;
993 MonoClassField* field;
996 klass = mono_object_class (this_obj);
998 if (mono_class_num_fields (klass) == 0)
1002 * Compute the starting value of the hashcode for fields of primitive
1003 * types, and return the remaining fields in an array to the managed side.
1004 * This way, we can avoid costly reflection operations in managed code.
1007 while ((field = mono_class_get_fields (klass, &iter))) {
1008 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1010 if (mono_field_is_deleted (field))
1012 /* FIXME: Add more types */
1013 switch (field->type->type) {
1015 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1017 case MONO_TYPE_STRING: {
1019 s = *(MonoString**)((guint8*)this_obj + field->offset);
1021 result ^= mono_string_hash (s);
1026 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1027 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1028 values [count++] = o;
1034 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1035 for (i = 0; i < count; ++i)
1036 mono_array_setref (*fields, i, values [i]);
1043 ICALL_EXPORT MonoBoolean
1044 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1047 MonoObject **values = NULL;
1049 MonoClassField* field;
1053 MONO_CHECK_ARG_NULL (that, FALSE);
1055 if (this_obj->vtable != that->vtable)
1058 klass = mono_object_class (this_obj);
1060 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1061 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1064 * Do the comparison for fields of primitive type and return a result if
1065 * possible. Otherwise, return the remaining fields in an array to the
1066 * managed side. This way, we can avoid costly reflection operations in
1071 while ((field = mono_class_get_fields (klass, &iter))) {
1072 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1074 if (mono_field_is_deleted (field))
1076 /* FIXME: Add more types */
1077 switch (field->type->type) {
1080 case MONO_TYPE_BOOLEAN:
1081 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1086 case MONO_TYPE_CHAR:
1087 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1092 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1097 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1101 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1105 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1110 case MONO_TYPE_STRING: {
1111 MonoString *s1, *s2;
1112 guint32 s1len, s2len;
1113 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1114 s2 = *(MonoString**)((guint8*)that + field->offset);
1117 if ((s1 == NULL) || (s2 == NULL))
1119 s1len = mono_string_length (s1);
1120 s2len = mono_string_length (s2);
1124 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1130 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1131 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1132 values [count++] = o;
1133 o = mono_field_get_value_object (mono_object_domain (this_obj), field, that);
1134 values [count++] = o;
1137 if (klass->enumtype)
1138 /* enums only have one non-static field */
1144 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1145 for (i = 0; i < count; ++i)
1146 mono_array_setref_fast (*fields, i, values [i]);
1153 ICALL_EXPORT MonoReflectionType *
1154 ves_icall_System_Object_GetType (MonoObject *obj)
1157 MonoReflectionType *ret;
1158 #ifndef DISABLE_REMOTING
1159 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1160 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1163 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1165 mono_error_raise_exception (&error);
1171 ves_icall_MonoType_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1173 mtype->type = &obj->vtable->klass->byval_arg;
1174 g_assert (mtype->type->type);
1178 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1180 MONO_CHECK_ARG_NULL (obj, 0);
1183 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1184 mono_error_raise_exception (&error);
1189 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1190 MonoReflectionMethod *method,
1191 MonoArray *opt_param_types)
1193 MONO_CHECK_ARG_NULL (method, 0);
1196 gint32 result = mono_image_create_method_token (
1197 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1198 mono_error_raise_exception (&error);
1203 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1206 mono_image_create_pefile (mb, file, &error);
1207 mono_error_raise_exception (&error);
1211 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1214 if (!mono_image_build_metadata (mb, &error))
1215 mono_error_raise_exception (&error);
1219 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1221 mono_image_register_token (mb->dynamic_image, token, obj);
1224 ICALL_EXPORT MonoObject*
1225 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1229 mono_loader_lock ();
1230 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1231 mono_loader_unlock ();
1236 ICALL_EXPORT MonoReflectionModule*
1237 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1240 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1241 mono_error_set_pending_exception (&error);
1246 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1248 MonoMethod **dest = (MonoMethod **)data;
1250 /* skip unmanaged frames */
1266 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1268 MonoMethod **dest = (MonoMethod **)data;
1270 /* skip unmanaged frames */
1275 if (!strcmp (m->klass->name_space, "System.Reflection"))
1284 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1286 MonoMethod **dest = (MonoMethod **)data;
1288 /* skip unmanaged frames */
1292 if (m->wrapper_type != MONO_WRAPPER_NONE)
1295 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1309 static MonoReflectionType *
1310 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1312 MonoMethod *m, *dest;
1314 MonoType *type = NULL;
1315 MonoAssembly *assembly = NULL;
1316 gboolean type_resolve = FALSE;
1318 mono_error_init (error);
1321 * We must compute the calling assembly as type loading must happen under a metadata context.
1322 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1323 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1325 m = mono_method_get_last_managed ();
1328 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1333 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1334 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1335 * to crash. This only seems to happen in some strange remoting
1336 * scenarios and I was unable to figure out what's happening there.
1337 * Dec 10, 2005 - Martin.
1341 assembly = dest->klass->image->assembly;
1342 type_resolve = TRUE;
1344 g_warning (G_STRLOC);
1347 if (info->assembly.name)
1348 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1352 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1353 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1356 if (!info->assembly.name && !type) /* try mscorlib */
1357 type = mono_reflection_get_type (NULL, info, ignoreCase, &type_resolve);
1359 if (assembly && !type && type_resolve) {
1360 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1361 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1367 return mono_type_get_object_checked (mono_domain_get (), type, error);
1370 ICALL_EXPORT MonoReflectionType*
1371 ves_icall_System_Type_internal_from_name (MonoString *name,
1372 MonoBoolean throwOnError,
1373 MonoBoolean ignoreCase)
1376 char *str = mono_string_to_utf8 (name);
1377 MonoTypeNameParse info;
1378 MonoReflectionType *type;
1381 parsedOk = mono_reflection_parse_type (str, &info);
1383 /* mono_reflection_parse_type() mangles the string */
1385 mono_reflection_free_type_info (&info);
1388 mono_set_pending_exception (mono_get_exception_argument("typeName", "failed parse"));
1393 type = type_from_parsed_name (&info, ignoreCase, &error);
1395 mono_reflection_free_type_info (&info);
1398 if (!mono_error_ok (&error)) {
1400 mono_error_set_pending_exception (&error);
1402 mono_error_cleanup (&error);
1407 MonoException *e = NULL;
1410 e = mono_get_exception_type_load (name, NULL);
1412 mono_loader_clear_error ();
1414 mono_set_pending_exception (e);
1423 ICALL_EXPORT MonoReflectionType*
1424 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1427 MonoReflectionType *ret;
1428 MonoDomain *domain = mono_domain_get ();
1430 ret = mono_type_get_object_checked (domain, handle, &error);
1431 mono_error_raise_exception (&error);
1436 /* System.TypeCode */
1455 TYPECODE_STRING = 18
1458 ICALL_EXPORT guint32
1459 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1461 int t = type->type->type;
1463 if (type->type->byref)
1464 return TYPECODE_OBJECT;
1468 case MONO_TYPE_VOID:
1469 return TYPECODE_OBJECT;
1470 case MONO_TYPE_BOOLEAN:
1471 return TYPECODE_BOOLEAN;
1473 return TYPECODE_BYTE;
1475 return TYPECODE_SBYTE;
1477 return TYPECODE_UINT16;
1479 return TYPECODE_INT16;
1480 case MONO_TYPE_CHAR:
1481 return TYPECODE_CHAR;
1485 return TYPECODE_OBJECT;
1487 return TYPECODE_UINT32;
1489 return TYPECODE_INT32;
1491 return TYPECODE_UINT64;
1493 return TYPECODE_INT64;
1495 return TYPECODE_SINGLE;
1497 return TYPECODE_DOUBLE;
1498 case MONO_TYPE_VALUETYPE: {
1499 MonoClass *klass = type->type->data.klass;
1501 if (klass->enumtype) {
1502 t = mono_class_enum_basetype (klass)->type;
1504 } else if (mono_is_corlib_image (klass->image)) {
1505 if (strcmp (klass->name_space, "System") == 0) {
1506 if (strcmp (klass->name, "Decimal") == 0)
1507 return TYPECODE_DECIMAL;
1508 else if (strcmp (klass->name, "DateTime") == 0)
1509 return TYPECODE_DATETIME;
1512 return TYPECODE_OBJECT;
1514 case MONO_TYPE_STRING:
1515 return TYPECODE_STRING;
1516 case MONO_TYPE_SZARRAY:
1517 case MONO_TYPE_ARRAY:
1518 case MONO_TYPE_OBJECT:
1520 case MONO_TYPE_MVAR:
1521 case MONO_TYPE_TYPEDBYREF:
1522 return TYPECODE_OBJECT;
1523 case MONO_TYPE_CLASS:
1525 MonoClass *klass = type->type->data.klass;
1526 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1527 if (strcmp (klass->name, "DBNull") == 0)
1528 return TYPECODE_DBNULL;
1531 return TYPECODE_OBJECT;
1532 case MONO_TYPE_GENERICINST:
1533 return TYPECODE_OBJECT;
1535 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1541 mono_type_is_primitive (MonoType *type)
1543 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1544 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1548 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1550 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1551 return mono_class_enum_basetype (type->data.klass);
1552 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1553 return mono_class_enum_basetype (type->data.generic_class->container_class);
1557 ICALL_EXPORT guint32
1558 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1563 g_assert (type != NULL);
1565 klass = mono_class_from_mono_type (type->type);
1566 klassc = mono_class_from_mono_type (c->type);
1568 if (type->type->byref ^ c->type->byref)
1571 if (type->type->byref) {
1572 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1573 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1575 klass = mono_class_from_mono_type (t);
1576 klassc = mono_class_from_mono_type (ot);
1578 if (mono_type_is_primitive (t)) {
1579 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1580 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1581 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1582 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1583 return t->type == ot->type;
1585 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1588 if (klass->valuetype)
1589 return klass == klassc;
1590 return klass->valuetype == klassc->valuetype;
1593 return mono_class_is_assignable_from (klass, klassc);
1596 ICALL_EXPORT guint32
1597 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1600 MonoClass *klass = mono_class_from_mono_type (type->type);
1601 mono_class_init_checked (klass, &error);
1602 mono_error_raise_exception (&error);
1603 return mono_object_isinst (obj, klass) != NULL;
1606 ICALL_EXPORT guint32
1607 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1609 MonoClass *klass = mono_class_from_mono_type (type->type);
1610 return klass->flags;
1613 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1614 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1617 MonoClass *klass = field->field->parent;
1618 MonoMarshalType *info;
1622 if (klass->generic_container ||
1623 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1626 ftype = mono_field_get_type (field->field);
1627 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1630 info = mono_marshal_load_type_info (klass);
1632 for (i = 0; i < info->num_fields; ++i) {
1633 if (info->fields [i].field == field->field) {
1634 if (!info->fields [i].mspec)
1637 MonoReflectionMarshalAsAttribute* obj;
1638 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1639 if (!mono_error_ok (&error))
1640 mono_error_set_pending_exception (&error);
1649 ICALL_EXPORT MonoReflectionField*
1650 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1653 gboolean found = FALSE;
1660 klass = handle->parent;
1662 klass = mono_class_from_mono_type (type);
1664 /* Check that the field belongs to the class */
1665 for (k = klass; k; k = k->parent) {
1666 if (k == handle->parent) {
1673 /* The managed code will throw the exception */
1677 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1678 mono_error_raise_exception (&error);
1682 ICALL_EXPORT MonoArray*
1683 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1686 MonoType *type = mono_field_get_type_checked (field->field, &error);
1689 if (!mono_error_ok (&error)) {
1690 mono_error_set_pending_exception (&error);
1694 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1695 mono_error_raise_exception (&error);
1700 vell_icall_get_method_attributes (MonoMethod *method)
1702 return method->flags;
1706 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1709 MonoReflectionType *rt;
1710 MonoDomain *domain = mono_domain_get ();
1711 MonoMethodSignature* sig;
1713 sig = mono_method_signature_checked (method, &error);
1714 if (!mono_error_ok (&error)) {
1715 mono_error_set_pending_exception (&error);
1719 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1720 if (!mono_error_ok (&error)) {
1721 mono_error_set_pending_exception (&error);
1725 MONO_STRUCT_SETREF (info, parent, rt);
1727 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1728 if (!mono_error_ok (&error)) {
1729 mono_error_set_pending_exception (&error);
1733 MONO_STRUCT_SETREF (info, ret, rt);
1735 info->attrs = method->flags;
1736 info->implattrs = method->iflags;
1737 if (sig->call_convention == MONO_CALL_DEFAULT)
1738 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1740 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1745 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1748 ICALL_EXPORT MonoArray*
1749 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1752 MonoDomain *domain = mono_domain_get ();
1754 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1755 mono_error_set_pending_exception (&error);
1759 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1760 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1763 MonoDomain *domain = mono_domain_get ();
1764 MonoReflectionMarshalAsAttribute* res = NULL;
1765 MonoMarshalSpec **mspecs;
1768 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1769 mono_method_get_marshal_info (method, mspecs);
1772 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1773 if (!mono_error_ok (&error)) {
1774 mono_error_set_pending_exception (&error);
1779 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1781 mono_metadata_free_marshal_spec (mspecs [i]);
1788 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1790 MonoClass *parent = field->field->parent;
1791 if (!parent->size_inited)
1792 mono_class_init (parent);
1793 mono_class_setup_fields_locking (parent);
1795 return field->field->offset - sizeof (MonoObject);
1798 ICALL_EXPORT MonoReflectionType*
1799 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1802 MonoReflectionType *ret;
1805 parent = declaring? field->field->parent: field->klass;
1807 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1808 mono_error_raise_exception (&error);
1814 ICALL_EXPORT MonoObject *
1815 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1817 MonoClass *fklass = field->klass;
1818 MonoClassField *cf = field->field;
1819 MonoDomain *domain = mono_object_domain (field);
1821 if (fklass->image->assembly->ref_only) {
1822 mono_set_pending_exception (mono_get_exception_invalid_operation (
1823 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1827 if (mono_security_core_clr_enabled ())
1828 mono_security_core_clr_ensure_reflection_access_field (cf);
1830 return mono_field_get_value_object (domain, cf, obj);
1834 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1837 MonoClassField *cf = field->field;
1841 if (field->klass->image->assembly->ref_only) {
1842 mono_set_pending_exception (mono_get_exception_invalid_operation (
1843 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1847 if (mono_security_core_clr_enabled ())
1848 mono_security_core_clr_ensure_reflection_access_field (cf);
1850 type = mono_field_get_type_checked (cf, &error);
1851 if (!mono_error_ok (&error)) {
1852 mono_error_set_pending_exception (&error);
1856 v = (gchar *) value;
1858 switch (type->type) {
1861 case MONO_TYPE_BOOLEAN:
1864 case MONO_TYPE_CHAR:
1873 case MONO_TYPE_VALUETYPE:
1876 v += sizeof (MonoObject);
1878 case MONO_TYPE_STRING:
1879 case MONO_TYPE_OBJECT:
1880 case MONO_TYPE_CLASS:
1881 case MONO_TYPE_ARRAY:
1882 case MONO_TYPE_SZARRAY:
1885 case MONO_TYPE_GENERICINST: {
1886 MonoGenericClass *gclass = type->data.generic_class;
1887 g_assert (!gclass->context.class_inst->is_open);
1889 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1890 MonoClass *nklass = mono_class_from_mono_type (type);
1891 MonoObject *nullable;
1894 * Convert the boxed vtype into a Nullable structure.
1895 * This is complicated by the fact that Nullables have
1896 * a variable structure.
1898 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1899 if (!mono_error_ok (&error)) {
1900 mono_error_set_pending_exception (&error);
1904 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1906 v = (gchar *)mono_object_unbox (nullable);
1909 if (gclass->container_class->valuetype && (v != NULL))
1910 v += sizeof (MonoObject);
1914 g_error ("type 0x%x not handled in "
1915 "ves_icall_FieldInfo_SetValueInternal", type->type);
1920 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1921 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
1922 if (!is_ok (&error)) {
1923 mono_error_set_pending_exception (&error);
1926 if (!vtable->initialized) {
1927 if (!mono_runtime_class_init_full (vtable, &error)) {
1928 mono_error_set_pending_exception (&error);
1932 mono_field_static_set_value (vtable, cf, v);
1934 mono_field_set_value (obj, cf, v);
1939 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1948 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1949 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1953 if (MONO_TYPE_IS_REFERENCE (f->type))
1954 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1956 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1959 ICALL_EXPORT MonoObject *
1960 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1962 MonoObject *o = NULL;
1963 MonoClassField *field = rfield->field;
1965 MonoDomain *domain = mono_object_domain (rfield);
1967 MonoTypeEnum def_type;
1968 const char *def_value;
1972 mono_class_init (field->parent);
1974 t = mono_field_get_type_checked (field, &error);
1975 if (!mono_error_ok (&error)) {
1976 mono_error_set_pending_exception (&error);
1980 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
1981 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1985 if (image_is_dynamic (field->parent->image)) {
1986 MonoClass *klass = field->parent;
1987 int fidx = field - klass->fields;
1989 g_assert (fidx >= 0 && fidx < klass->field.count);
1990 g_assert (klass->ext);
1991 g_assert (klass->ext->field_def_values);
1992 def_type = klass->ext->field_def_values [fidx].def_type;
1993 def_value = klass->ext->field_def_values [fidx].data;
1994 if (def_type == MONO_TYPE_END) {
1995 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1999 def_value = mono_class_get_field_default_value (field, &def_type);
2000 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2002 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2007 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2011 case MONO_TYPE_BOOLEAN:
2014 case MONO_TYPE_CHAR:
2022 case MONO_TYPE_R8: {
2025 /* boxed value type */
2026 t = g_new0 (MonoType, 1);
2028 klass = mono_class_from_mono_type (t);
2030 o = mono_object_new_checked (domain, klass, &error);
2031 if (!mono_error_ok (&error)) {
2032 mono_error_set_pending_exception (&error);
2035 v = ((gchar *) o) + sizeof (MonoObject);
2036 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2039 case MONO_TYPE_STRING:
2040 case MONO_TYPE_CLASS:
2041 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2044 g_assert_not_reached ();
2050 ICALL_EXPORT MonoReflectionType*
2051 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2054 MonoReflectionType *ret;
2057 type = mono_field_get_type_checked (ref_field->field, &error);
2058 if (!mono_error_ok (&error)) {
2059 mono_error_set_pending_exception (&error);
2063 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2064 if (!mono_error_ok (&error)) {
2065 mono_error_set_pending_exception (&error);
2072 /* From MonoProperty.cs */
2074 PInfo_Attributes = 1,
2075 PInfo_GetMethod = 1 << 1,
2076 PInfo_SetMethod = 1 << 2,
2077 PInfo_ReflectedType = 1 << 3,
2078 PInfo_DeclaringType = 1 << 4,
2083 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2086 MonoReflectionType *rt;
2087 MonoReflectionMethod *rm;
2088 MonoDomain *domain = mono_object_domain (property);
2089 const MonoProperty *pproperty = property->property;
2091 if ((req_info & PInfo_ReflectedType) != 0) {
2092 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2093 mono_error_raise_exception (&error);
2095 MONO_STRUCT_SETREF (info, parent, rt);
2097 if ((req_info & PInfo_DeclaringType) != 0) {
2098 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2099 mono_error_raise_exception (&error);
2101 MONO_STRUCT_SETREF (info, declaring_type, rt);
2104 if ((req_info & PInfo_Name) != 0)
2105 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2107 if ((req_info & PInfo_Attributes) != 0)
2108 info->attrs = pproperty->attrs;
2110 if ((req_info & PInfo_GetMethod) != 0) {
2111 if (pproperty->get &&
2112 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2113 pproperty->get->klass == property->klass)) {
2114 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2115 mono_error_raise_exception (&error);
2120 MONO_STRUCT_SETREF (info, get, rm);
2122 if ((req_info & PInfo_SetMethod) != 0) {
2123 if (pproperty->set &&
2124 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2125 pproperty->set->klass == property->klass)) {
2126 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2127 mono_error_raise_exception (&error);
2132 MONO_STRUCT_SETREF (info, set, rm);
2135 * There may be other methods defined for properties, though, it seems they are not exposed
2136 * in the reflection API
2141 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2144 MonoReflectionType *rt;
2145 MonoReflectionMethod *rm;
2146 MonoDomain *domain = mono_object_domain (event);
2148 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2149 mono_error_raise_exception (&error);
2151 MONO_STRUCT_SETREF (info, reflected_type, rt);
2153 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2154 mono_error_raise_exception (&error);
2156 MONO_STRUCT_SETREF (info, declaring_type, rt);
2158 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2159 info->attrs = event->event->attrs;
2161 if (event->event->add) {
2162 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2163 mono_error_raise_exception (&error);
2168 MONO_STRUCT_SETREF (info, add_method, rm);
2170 if (event->event->remove) {
2171 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2172 mono_error_raise_exception (&error);
2177 MONO_STRUCT_SETREF (info, remove_method, rm);
2179 if (event->event->raise) {
2180 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2181 mono_error_raise_exception (&error);
2186 MONO_STRUCT_SETREF (info, raise_method, rm);
2188 #ifndef MONO_SMALL_CONFIG
2189 if (event->event->other) {
2191 while (event->event->other [n])
2193 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2195 for (i = 0; i < n; i++) {
2196 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2197 mono_error_raise_exception (&error);
2198 mono_array_setref (info->other_methods, i, rm);
2205 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2210 mono_class_setup_interfaces (klass, error);
2211 if (!mono_error_ok (error))
2214 for (i = 0; i < klass->interface_count; i++) {
2215 ic = klass->interfaces [i];
2216 g_hash_table_insert (ifaces, ic, ic);
2218 collect_interfaces (ic, ifaces, error);
2219 if (!mono_error_ok (error))
2225 MonoArray *iface_array;
2226 MonoGenericContext *context;
2230 } FillIfaceArrayData;
2233 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2235 MonoReflectionType *rt;
2236 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2237 MonoClass *ic = (MonoClass *)key;
2238 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2240 if (!mono_error_ok (data->error))
2243 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2244 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2245 if (!mono_error_ok (data->error))
2249 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2250 if (!mono_error_ok (data->error))
2253 mono_array_setref (data->iface_array, data->next_idx++, rt);
2256 mono_metadata_free_type (inflated);
2260 get_interfaces_hash (gconstpointer v1)
2262 MonoClass *k = (MonoClass*)v1;
2264 return k->type_token;
2267 ICALL_EXPORT MonoArray*
2268 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2271 MonoClass *klass = mono_class_from_mono_type (type->type);
2273 FillIfaceArrayData data = { 0 };
2276 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2278 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2279 data.context = mono_class_get_context (klass);
2280 klass = klass->generic_class->container_class;
2283 for (parent = klass; parent; parent = parent->parent) {
2284 mono_class_setup_interfaces (parent, &error);
2285 if (!mono_error_ok (&error))
2287 collect_interfaces (parent, iface_hash, &error);
2288 if (!mono_error_ok (&error))
2292 data.error = &error;
2293 data.domain = mono_object_domain (type);
2295 len = g_hash_table_size (iface_hash);
2297 g_hash_table_destroy (iface_hash);
2298 if (!data.domain->empty_types)
2299 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2300 return data.domain->empty_types;
2303 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2304 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2305 if (!mono_error_ok (&error))
2308 g_hash_table_destroy (iface_hash);
2309 return data.iface_array;
2312 g_hash_table_destroy (iface_hash);
2313 mono_error_set_pending_exception (&error);
2318 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2320 gboolean variance_used;
2321 MonoClass *klass = mono_class_from_mono_type (type->type);
2322 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2323 MonoReflectionMethod *member;
2326 int i = 0, len, ioffset;
2330 mono_class_init_checked (klass, &error);
2331 mono_error_raise_exception (&error);
2332 mono_class_init_checked (iclass, &error);
2333 mono_error_raise_exception (&error);
2335 mono_class_setup_vtable (klass);
2337 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2341 len = mono_class_num_methods (iclass);
2342 domain = mono_object_domain (type);
2343 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2344 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2346 while ((method = mono_class_get_methods (iclass, &iter))) {
2347 member = mono_method_get_object_checked (domain, method, iclass, &error);
2348 mono_error_raise_exception (&error);
2349 mono_array_setref (*methods, i, member);
2350 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2351 mono_error_raise_exception (&error);
2352 mono_array_setref (*targets, i, member);
2359 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2362 MonoClass *klass = mono_class_from_mono_type (type->type);
2364 mono_class_init_checked (klass, &error);
2365 mono_error_raise_exception (&error);
2367 if (image_is_dynamic (klass->image)) {
2368 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2369 *packing = tb->packing_size;
2370 *size = tb->class_size;
2372 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2376 ICALL_EXPORT MonoReflectionType*
2377 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2380 MonoReflectionType *ret;
2383 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2384 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2385 mono_error_raise_exception (&error);
2390 klass = mono_class_from_mono_type (type->type);
2391 mono_class_init_checked (klass, &error);
2392 mono_error_raise_exception (&error);
2394 // GetElementType should only return a type for:
2395 // Array Pointer PassedByRef
2396 if (type->type->byref)
2397 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2398 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2399 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2400 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2401 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2405 mono_error_raise_exception (&error);
2410 ICALL_EXPORT MonoReflectionType*
2411 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2414 MonoReflectionType *ret;
2416 if (type->type->byref)
2419 MonoClass *klass = mono_class_from_mono_type (type->type);
2423 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2424 mono_error_raise_exception (&error);
2429 ICALL_EXPORT MonoBoolean
2430 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2432 return type->type->type == MONO_TYPE_PTR;
2435 ICALL_EXPORT MonoBoolean
2436 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2438 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)));
2441 ICALL_EXPORT MonoBoolean
2442 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2444 return type->type->byref;
2447 ICALL_EXPORT MonoBoolean
2448 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2451 MonoClass *klass = mono_class_from_mono_type (type->type);
2452 mono_class_init_checked (klass, &error);
2453 mono_error_raise_exception (&error);
2455 return mono_class_is_com_object (klass);
2458 ICALL_EXPORT guint32
2459 ves_icall_RuntimeTypeHandle_GetMetadataToken (MonoReflectionType *obj)
2461 return mono_reflection_get_token ((MonoObject*)obj);
2464 ICALL_EXPORT MonoReflectionModule*
2465 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2468 MonoReflectionModule *result = NULL;
2469 MonoClass *klass = mono_class_from_mono_type (type->type);
2470 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2471 if (!mono_error_ok (&error))
2472 mono_error_set_pending_exception (&error);
2476 ICALL_EXPORT MonoReflectionAssembly*
2477 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2480 MonoDomain *domain = mono_domain_get ();
2481 MonoClass *klass = mono_class_from_mono_type (type->type);
2482 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2484 mono_error_set_pending_exception (&error);
2488 ICALL_EXPORT MonoReflectionType*
2489 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2492 MonoReflectionType *ret;
2493 MonoDomain *domain = mono_domain_get ();
2496 if (type->type->byref)
2498 if (type->type->type == MONO_TYPE_VAR) {
2499 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2500 klass = param ? param->owner.klass : NULL;
2501 } else if (type->type->type == MONO_TYPE_MVAR) {
2502 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2503 klass = param ? param->owner.method->klass : NULL;
2505 klass = mono_class_from_mono_type (type->type)->nested_in;
2511 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2512 mono_error_raise_exception (&error);
2517 ICALL_EXPORT MonoString*
2518 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2520 MonoDomain *domain = mono_domain_get ();
2521 MonoClass *klass = mono_class_from_mono_type (type->type);
2523 if (type->type->byref) {
2524 char *n = g_strdup_printf ("%s&", klass->name);
2525 MonoString *res = mono_string_new (domain, n);
2531 return mono_string_new (domain, klass->name);
2535 ICALL_EXPORT MonoString*
2536 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2538 MonoDomain *domain = mono_domain_get ();
2539 MonoClass *klass = mono_class_from_mono_type (type->type);
2541 while (klass->nested_in)
2542 klass = klass->nested_in;
2544 if (klass->name_space [0] == '\0')
2547 return mono_string_new (domain, klass->name_space);
2551 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2555 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2556 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2560 klass = mono_class_from_mono_type (type->type);
2566 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2569 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2573 ICALL_EXPORT MonoArray*
2574 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2577 MonoReflectionType *rt;
2579 MonoClass *klass, *pklass;
2580 MonoDomain *domain = mono_object_domain (type);
2583 klass = mono_class_from_mono_type (type->type);
2585 if (klass->generic_container) {
2586 MonoGenericContainer *container = klass->generic_container;
2587 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2588 for (i = 0; i < container->type_argc; ++i) {
2589 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2591 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2592 mono_error_raise_exception (&error);
2594 mono_array_setref (res, i, rt);
2596 } else if (klass->generic_class) {
2597 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2598 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2599 for (i = 0; i < inst->type_argc; ++i) {
2600 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2601 mono_error_raise_exception (&error);
2603 mono_array_setref (res, i, rt);
2611 ICALL_EXPORT gboolean
2612 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2616 if (!IS_MONOTYPE (type))
2619 if (type->type->byref)
2622 klass = mono_class_from_mono_type (type->type);
2623 return klass->generic_container != NULL;
2626 ICALL_EXPORT MonoReflectionType*
2627 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2630 MonoReflectionType *ret;
2633 if (type->type->byref)
2636 klass = mono_class_from_mono_type (type->type);
2638 if (klass->generic_container) {
2639 return type; /* check this one */
2641 if (klass->generic_class) {
2642 MonoClass *generic_class = klass->generic_class->container_class;
2645 tb = mono_class_get_ref_info (generic_class);
2647 if (generic_class->wastypebuilder && tb)
2648 return (MonoReflectionType *)tb;
2650 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2651 mono_error_raise_exception (&error);
2659 ICALL_EXPORT MonoReflectionType*
2660 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2663 MonoReflectionType *ret;
2665 MonoType *geninst, **types;
2668 g_assert (IS_MONOTYPE (type));
2669 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2670 mono_error_raise_exception (&error);
2672 count = mono_array_length (type_array);
2673 types = g_new0 (MonoType *, count);
2675 for (i = 0; i < count; i++) {
2676 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2677 types [i] = t->type;
2680 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2685 klass = mono_class_from_mono_type (geninst);
2687 /*we might inflate to the GTD*/
2688 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2689 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2693 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2694 mono_error_raise_exception (&error);
2699 ICALL_EXPORT gboolean
2700 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2704 if (!IS_MONOTYPE (type))
2707 if (type->type->byref)
2710 klass = mono_class_from_mono_type (type->type);
2711 return klass->generic_class != NULL || klass->generic_container != NULL;
2715 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2717 if (!IS_MONOTYPE (type))
2720 if (is_generic_parameter (type->type))
2721 return mono_type_get_generic_param_num (type->type);
2725 ICALL_EXPORT GenericParameterAttributes
2726 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2728 g_assert (IS_MONOTYPE (type));
2729 g_assert (is_generic_parameter (type->type));
2730 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2733 ICALL_EXPORT MonoArray *
2734 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2737 MonoReflectionType *rt;
2738 MonoGenericParamInfo *param_info;
2744 g_assert (IS_MONOTYPE (type));
2746 domain = mono_object_domain (type);
2747 param_info = mono_generic_param_info (type->type->data.generic_param);
2748 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2751 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2752 for (i = 0; i < count; i++) {
2753 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2754 mono_error_raise_exception (&error);
2756 mono_array_setref (res, i, rt);
2763 ICALL_EXPORT MonoBoolean
2764 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2766 return is_generic_parameter (type->type);
2769 ICALL_EXPORT MonoBoolean
2770 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2772 return is_generic_parameter (tb->type.type);
2776 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2777 MonoReflectionType *t)
2779 enumtype->type = t->type;
2782 ICALL_EXPORT MonoReflectionMethod*
2783 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2784 MonoReflectionMethod* generic)
2791 MonoReflectionMethod *ret = NULL;
2793 domain = ((MonoObject *)type)->vtable->domain;
2795 klass = mono_class_from_mono_type (type->type);
2796 mono_class_init_checked (klass, &error);
2797 mono_error_raise_exception (&error);
2800 while ((method = mono_class_get_methods (klass, &iter))) {
2801 if (method->token == generic->method->token) {
2802 ret = mono_method_get_object_checked (domain, method, klass, &error);
2803 mono_error_raise_exception (&error);
2810 ICALL_EXPORT MonoReflectionMethod *
2811 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2814 MonoType *type = ref_type->type;
2816 MonoReflectionMethod *ret = NULL;
2818 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2819 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2822 if (type->type == MONO_TYPE_VAR)
2825 method = mono_type_get_generic_param_owner (type)->owner.method;
2828 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2829 if (!mono_error_ok (&error))
2830 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2834 ICALL_EXPORT MonoBoolean
2835 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2837 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2841 ICALL_EXPORT MonoBoolean
2842 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2844 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2849 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2851 MonoDomain *domain = mono_domain_get ();
2852 MonoImage *image = method->method->klass->image;
2853 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2854 MonoTableInfo *tables = image->tables;
2855 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2856 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2857 guint32 im_cols [MONO_IMPLMAP_SIZE];
2858 guint32 scope_token;
2859 const char *import = NULL;
2860 const char *scope = NULL;
2862 if (image_is_dynamic (image)) {
2863 MonoReflectionMethodAux *method_aux =
2864 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2866 import = method_aux->dllentry;
2867 scope = method_aux->dll;
2870 if (!import || !scope) {
2871 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2876 if (piinfo->implmap_idx) {
2877 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2879 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2880 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2881 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2882 scope = mono_metadata_string_heap (image, scope_token);
2886 *flags = piinfo->piflags;
2887 *entry_point = mono_string_new (domain, import);
2888 *dll_name = mono_string_new (domain, scope);
2891 ICALL_EXPORT MonoReflectionMethod *
2892 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2894 MonoMethodInflated *imethod;
2896 MonoReflectionMethod *ret = NULL;
2899 if (method->method->is_generic)
2902 if (!method->method->is_inflated)
2905 imethod = (MonoMethodInflated *) method->method;
2907 result = imethod->declaring;
2908 /* Not a generic method. */
2909 if (!result->is_generic)
2912 if (image_is_dynamic (method->method->klass->image)) {
2913 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2914 MonoReflectionMethod *res;
2917 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2918 * the dynamic case as well ?
2920 mono_image_lock ((MonoImage*)image);
2921 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2922 mono_image_unlock ((MonoImage*)image);
2928 if (imethod->context.class_inst) {
2929 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2930 /*Generic methods gets the context of the GTD.*/
2931 if (mono_class_get_context (klass)) {
2932 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2933 if (!mono_error_ok (&error))
2938 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2940 if (!mono_error_ok (&error))
2941 mono_error_set_pending_exception (&error);
2945 ICALL_EXPORT gboolean
2946 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2948 return mono_method_signature (method->method)->generic_param_count != 0;
2951 ICALL_EXPORT gboolean
2952 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2954 return method->method->is_generic;
2957 ICALL_EXPORT MonoArray*
2958 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2961 MonoReflectionType *rt;
2966 domain = mono_object_domain (method);
2968 if (method->method->is_inflated) {
2969 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2972 count = inst->type_argc;
2973 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2975 for (i = 0; i < count; i++) {
2976 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2977 mono_error_raise_exception (&error);
2979 mono_array_setref (res, i, rt);
2986 count = mono_method_signature (method->method)->generic_param_count;
2987 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2989 for (i = 0; i < count; i++) {
2990 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2991 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2992 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
2994 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2995 mono_error_raise_exception (&error);
2997 mono_array_setref (res, i, rt);
3003 ICALL_EXPORT MonoObject *
3004 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3008 * Invoke from reflection is supposed to always be a virtual call (the API
3009 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3010 * greater flexibility.
3012 MonoMethod *m = method->method;
3013 MonoMethodSignature *sig = mono_method_signature (m);
3016 void *obj = this_arg;
3020 if (mono_security_core_clr_enabled ())
3021 mono_security_core_clr_ensure_reflection_access_method (m);
3023 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3024 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3025 mono_error_cleanup (&error); /* FIXME does this make sense? */
3026 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3031 if (!mono_object_isinst (this_arg, m->klass)) {
3032 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3033 char *target_name = mono_type_get_full_name (m->klass);
3034 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3035 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3037 g_free (target_name);
3041 m = mono_object_get_virtual_method (this_arg, m);
3042 /* must pass the pointer to the value for valuetype methods */
3043 if (m->klass->valuetype)
3044 obj = mono_object_unbox (this_arg);
3045 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3046 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3051 if (sig->ret->byref) {
3052 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"));
3056 pcount = params? mono_array_length (params): 0;
3057 if (pcount != sig->param_count) {
3058 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3062 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3063 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."));
3067 image = m->klass->image;
3068 if (image->assembly->ref_only) {
3069 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."));
3073 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3074 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3078 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3082 intptr_t *lower_bounds;
3083 pcount = mono_array_length (params);
3084 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3085 /* Note: the synthetized array .ctors have int32 as argument type */
3086 for (i = 0; i < pcount; ++i)
3087 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3089 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3090 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3091 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3092 if (!mono_error_ok (&error)) {
3093 mono_error_set_pending_exception (&error);
3097 for (i = 0; i < mono_array_length (arr); ++i) {
3098 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3099 if (!mono_error_ok (&error)) {
3100 mono_error_set_pending_exception (&error);
3103 mono_array_setref_fast (arr, i, subarray);
3105 return (MonoObject*)arr;
3108 if (m->klass->rank == pcount) {
3109 /* Only lengths provided. */
3110 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3111 if (!mono_error_ok (&error)) {
3112 mono_error_set_pending_exception (&error);
3116 return (MonoObject*)arr;
3118 g_assert (pcount == (m->klass->rank * 2));
3119 /* The arguments are lower-bound-length pairs */
3120 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3122 for (i = 0; i < pcount / 2; ++i) {
3123 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3124 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3127 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3128 if (!mono_error_ok (&error)) {
3129 mono_error_set_pending_exception (&error);
3133 return (MonoObject*)arr;
3136 return mono_runtime_invoke_array (m, obj, params, NULL);
3139 #ifndef DISABLE_REMOTING
3140 ICALL_EXPORT MonoObject *
3141 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3143 MonoDomain *domain = mono_object_domain (method);
3144 MonoMethod *m = method->method;
3145 MonoMethodSignature *sig = mono_method_signature (m);
3146 MonoArray *out_args;
3148 int i, j, outarg_count = 0;
3150 if (m->klass == mono_defaults.object_class) {
3151 if (!strcmp (m->name, "FieldGetter")) {
3152 MonoClass *k = this_arg->vtable->klass;
3156 /* If this is a proxy, then it must be a CBO */
3157 if (k == mono_defaults.transparent_proxy_class) {
3158 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3159 this_arg = tp->rp->unwrapped_server;
3160 g_assert (this_arg);
3161 k = this_arg->vtable->klass;
3164 name = mono_array_get (params, MonoString *, 1);
3165 str = mono_string_to_utf8 (name);
3168 MonoClassField* field = mono_class_get_field_from_name (k, str);
3170 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3171 if (field_klass->valuetype)
3172 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
3174 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3176 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3177 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3178 mono_array_setref (out_args, 0, result);
3186 g_assert_not_reached ();
3188 } else if (!strcmp (m->name, "FieldSetter")) {
3189 MonoClass *k = this_arg->vtable->klass;
3195 /* If this is a proxy, then it must be a CBO */
3196 if (k == mono_defaults.transparent_proxy_class) {
3197 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3198 this_arg = tp->rp->unwrapped_server;
3199 g_assert (this_arg);
3200 k = this_arg->vtable->klass;
3203 name = mono_array_get (params, MonoString *, 1);
3204 str = mono_string_to_utf8 (name);
3207 MonoClassField* field = mono_class_get_field_from_name (k, str);
3209 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3210 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3212 if (field_klass->valuetype) {
3213 size = mono_type_size (field->type, &align);
3214 g_assert (size == mono_class_value_size (field_klass, NULL));
3215 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3217 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3220 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3221 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3231 g_assert_not_reached ();
3236 for (i = 0; i < mono_array_length (params); i++) {
3237 if (sig->params [i]->byref)
3241 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3243 /* handle constructors only for objects already allocated */
3244 if (!strcmp (method->method->name, ".ctor"))
3245 g_assert (this_arg);
3247 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3248 g_assert (!method->method->klass->valuetype);
3249 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3251 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3252 if (sig->params [i]->byref) {
3254 arg = mono_array_get (params, gpointer, i);
3255 mono_array_setref (out_args, j, arg);
3260 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3267 read_enum_value (const char *mem, int type)
3270 case MONO_TYPE_BOOLEAN:
3272 return *(guint8*)mem;
3274 return *(gint8*)mem;
3275 case MONO_TYPE_CHAR:
3277 return read16 (mem);
3279 return (gint16) read16 (mem);
3281 return read32 (mem);
3283 return (gint32) read32 (mem);
3286 return read64 (mem);
3288 g_assert_not_reached ();
3294 write_enum_value (char *mem, int type, guint64 value)
3298 case MONO_TYPE_I1: {
3299 guint8 *p = (guint8*)mem;
3304 case MONO_TYPE_I2: {
3305 guint16 *p = (guint16 *)mem;
3310 case MONO_TYPE_I4: {
3311 guint32 *p = (guint32 *)mem;
3316 case MONO_TYPE_I8: {
3317 guint64 *p = (guint64 *)mem;
3322 g_assert_not_reached ();
3327 ICALL_EXPORT MonoObject *
3328 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3336 domain = mono_object_domain (enumType);
3337 enumc = mono_class_from_mono_type (enumType->type);
3339 mono_class_init_checked (enumc, &error);
3340 mono_error_raise_exception (&error);
3342 etype = mono_class_enum_basetype (enumc);
3344 res = mono_object_new_checked (domain, enumc, &error);
3345 mono_error_raise_exception (&error);
3346 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3351 ICALL_EXPORT MonoBoolean
3352 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3354 int size = mono_class_value_size (a->vtable->klass, NULL);
3355 guint64 a_val = 0, b_val = 0;
3357 memcpy (&a_val, mono_object_unbox (a), size);
3358 memcpy (&b_val, mono_object_unbox (b), size);
3360 return (a_val & b_val) == b_val;
3363 ICALL_EXPORT MonoObject *
3364 ves_icall_System_Enum_get_value (MonoObject *eobj)
3376 g_assert (eobj->vtable->klass->enumtype);
3378 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3379 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3380 mono_error_raise_exception (&error);
3381 dst = (char *)res + sizeof (MonoObject);
3382 src = (char *)eobj + sizeof (MonoObject);
3383 size = mono_class_value_size (enumc, NULL);
3385 memcpy (dst, src, size);
3390 ICALL_EXPORT MonoReflectionType *
3391 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3394 MonoReflectionType *ret;
3398 klass = mono_class_from_mono_type (type->type);
3399 mono_class_init_checked (klass, &error);
3400 mono_error_raise_exception (&error);
3402 etype = mono_class_enum_basetype (klass);
3404 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3408 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3409 mono_error_raise_exception (&error);
3415 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3417 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3418 gpointer odata = (char *)other + sizeof (MonoObject);
3419 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3420 g_assert (basetype);
3425 if (eobj->vtable->klass != other->vtable->klass)
3428 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3429 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3430 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3433 return me > other ? 1 : -1; \
3436 switch (basetype->type) {
3438 COMPARE_ENUM_VALUES (guint8);
3440 COMPARE_ENUM_VALUES (gint8);
3441 case MONO_TYPE_CHAR:
3443 COMPARE_ENUM_VALUES (guint16);
3445 COMPARE_ENUM_VALUES (gint16);
3447 COMPARE_ENUM_VALUES (guint32);
3449 COMPARE_ENUM_VALUES (gint32);
3451 COMPARE_ENUM_VALUES (guint64);
3453 COMPARE_ENUM_VALUES (gint64);
3457 #undef COMPARE_ENUM_VALUES
3458 /* indicates that the enum was of an unsupported unerlying type */
3463 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3465 gpointer data = (char *)eobj + sizeof (MonoObject);
3466 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3467 g_assert (basetype);
3469 switch (basetype->type) {
3470 case MONO_TYPE_I1: {
3471 gint8 value = *((gint8*)data);
3472 return ((int)value ^ (int)value << 8);
3475 return *((guint8*)data);
3476 case MONO_TYPE_CHAR:
3478 return *((guint16*)data);
3480 case MONO_TYPE_I2: {
3481 gint16 value = *((gint16*)data);
3482 return ((int)(guint16)value | (((int)value) << 16));
3485 return *((guint32*)data);
3487 return *((gint32*)data);
3489 case MONO_TYPE_I8: {
3490 gint64 value = *((gint64*)data);
3491 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3494 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3499 ICALL_EXPORT MonoBoolean
3500 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3503 MonoDomain *domain = mono_object_domain (type);
3504 MonoClass *enumc = mono_class_from_mono_type (type->type);
3505 guint j = 0, nvalues;
3507 MonoClassField *field;
3509 guint64 field_value, previous_value = 0;
3510 gboolean sorted = TRUE;
3512 mono_class_init_checked (enumc, &error);
3513 mono_error_raise_exception (&error);
3515 if (!enumc->enumtype) {
3516 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3520 base_type = mono_class_enum_basetype (enumc)->type;
3522 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3523 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3524 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3527 while ((field = mono_class_get_fields (enumc, &iter))) {
3529 MonoTypeEnum def_type;
3531 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3533 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3535 if (mono_field_is_deleted (field))
3537 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3539 p = mono_class_get_field_default_value (field, &def_type);
3540 /* len = */ mono_metadata_decode_blob_size (p, &p);
3542 field_value = read_enum_value (p, base_type);
3543 mono_array_set (*values, guint64, j, field_value);
3545 if (previous_value > field_value)
3548 previous_value = field_value;
3556 BFLAGS_IgnoreCase = 1,
3557 BFLAGS_DeclaredOnly = 2,
3558 BFLAGS_Instance = 4,
3560 BFLAGS_Public = 0x10,
3561 BFLAGS_NonPublic = 0x20,
3562 BFLAGS_FlattenHierarchy = 0x40,
3563 BFLAGS_InvokeMethod = 0x100,
3564 BFLAGS_CreateInstance = 0x200,
3565 BFLAGS_GetField = 0x400,
3566 BFLAGS_SetField = 0x800,
3567 BFLAGS_GetProperty = 0x1000,
3568 BFLAGS_SetProperty = 0x2000,
3569 BFLAGS_ExactBinding = 0x10000,
3570 BFLAGS_SuppressChangeType = 0x20000,
3571 BFLAGS_OptionalParamBinding = 0x40000
3574 ICALL_EXPORT MonoArray*
3575 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3579 MonoClass *startklass, *klass, *refklass;
3584 char *utf8_name = NULL;
3585 int (*compare_func) (const char *s1, const char *s2) = NULL;
3586 MonoClassField *field;
3587 MonoPtrArray tmp_array;
3589 domain = ((MonoObject *)type)->vtable->domain;
3590 if (type->type->byref)
3591 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3593 klass = startklass = mono_class_from_mono_type (type->type);
3594 refklass = mono_class_from_mono_type (reftype->type);
3596 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3599 if (mono_class_has_failure (klass)) {
3600 mono_ptr_array_destroy (tmp_array);
3601 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3606 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3607 guint32 flags = mono_field_get_flags (field);
3609 if (mono_field_is_deleted_with_flags (field, flags))
3611 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3612 if (bflags & BFLAGS_Public)
3614 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3615 if (bflags & BFLAGS_NonPublic) {
3622 if (flags & FIELD_ATTRIBUTE_STATIC) {
3623 if (bflags & BFLAGS_Static)
3624 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3627 if (bflags & BFLAGS_Instance)
3635 if (utf8_name == NULL) {
3636 utf8_name = mono_string_to_utf8 (name);
3637 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3640 if (compare_func (mono_field_get_name (field), utf8_name))
3644 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3645 if (!mono_error_ok (&error))
3647 mono_ptr_array_append (tmp_array, member);
3649 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3652 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3654 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3655 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3657 mono_ptr_array_destroy (tmp_array);
3659 if (utf8_name != NULL)
3664 mono_ptr_array_destroy (tmp_array);
3665 mono_error_raise_exception (&error);
3666 g_assert_not_reached ();
3670 method_nonpublic (MonoMethod* method, gboolean start_klass)
3672 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3673 case METHOD_ATTRIBUTE_ASSEM:
3674 return (start_klass || mono_defaults.generic_ilist_class);
3675 case METHOD_ATTRIBUTE_PRIVATE:
3677 case METHOD_ATTRIBUTE_PUBLIC:
3685 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3688 MonoClass *startklass;
3692 /*FIXME, use MonoBitSet*/
3693 guint32 method_slots_default [8];
3694 guint32 *method_slots = NULL;
3695 int (*compare_func) (const char *s1, const char *s2) = NULL;
3697 array = g_ptr_array_new ();
3702 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3704 /* An optimization for calls made from Delegate:CreateDelegate () */
3705 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3706 method = mono_get_delegate_invoke (klass);
3707 if (mono_loader_get_last_error ())
3710 g_ptr_array_add (array, method);
3714 mono_class_setup_methods (klass);
3715 mono_class_setup_vtable (klass);
3716 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3719 if (is_generic_parameter (&klass->byval_arg))
3720 nslots = mono_class_get_vtable_size (klass->parent);
3722 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3723 if (nslots >= sizeof (method_slots_default) * 8) {
3724 method_slots = g_new0 (guint32, nslots / 32 + 1);
3726 method_slots = method_slots_default;
3727 memset (method_slots, 0, sizeof (method_slots_default));
3730 mono_class_setup_methods (klass);
3731 mono_class_setup_vtable (klass);
3732 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3736 while ((method = mono_class_get_methods (klass, &iter))) {
3738 if (method->slot != -1) {
3739 g_assert (method->slot < nslots);
3740 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3742 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3743 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3746 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3748 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3749 if (bflags & BFLAGS_Public)
3751 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3757 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3758 if (bflags & BFLAGS_Static)
3759 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3762 if (bflags & BFLAGS_Instance)
3770 if (compare_func (name, method->name))
3775 g_ptr_array_add (array, method);
3777 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3779 if (method_slots != method_slots_default)
3780 g_free (method_slots);
3785 if (method_slots != method_slots_default)
3786 g_free (method_slots);
3787 g_ptr_array_free (array, TRUE);
3789 if (mono_class_has_failure (klass)) {
3790 *ex = mono_class_get_exception_for_failure (klass);
3792 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3793 mono_loader_clear_error ();
3798 ICALL_EXPORT MonoArray*
3799 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3801 static MonoClass *MethodInfo_array;
3805 MonoVTable *array_vtable;
3806 MonoException *ex = NULL;
3807 const char *mname = NULL;
3808 GPtrArray *method_array;
3809 MonoClass *klass, *refklass;
3812 mono_error_init (&error);
3814 if (!MethodInfo_array) {
3815 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3816 mono_memory_barrier ();
3817 MethodInfo_array = klass;
3820 klass = mono_class_from_mono_type (type->type);
3821 refklass = mono_class_from_mono_type (reftype->type);
3822 domain = ((MonoObject *)type)->vtable->domain;
3823 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3824 if (!is_ok (&error)) {
3825 mono_error_set_pending_exception (&error);
3828 if (type->type->byref) {
3829 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3830 mono_error_set_pending_exception (&error);
3836 mname = mono_string_to_utf8 (name);
3838 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3839 g_free ((char*)mname);
3841 mono_set_pending_exception (ex);
3845 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3846 if (!mono_error_ok (&error)) {
3847 mono_error_set_pending_exception (&error);
3851 for (i = 0; i < method_array->len; ++i) {
3852 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3853 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3854 if (!mono_error_ok (&error))
3856 mono_array_setref (res, i, rm);
3860 g_ptr_array_free (method_array, TRUE);
3861 if (!mono_error_ok (&error))
3862 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3866 ICALL_EXPORT MonoArray*
3867 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3870 MonoClass *startklass, *klass, *refklass;
3875 gpointer iter = NULL;
3876 MonoPtrArray tmp_array;
3879 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3881 domain = ((MonoObject *)type)->vtable->domain;
3882 if (type->type->byref)
3883 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3884 klass = startklass = mono_class_from_mono_type (type->type);
3885 refklass = mono_class_from_mono_type (reftype->type);
3887 mono_class_setup_methods (klass);
3888 if (mono_class_has_failure (klass)) {
3889 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3894 while ((method = mono_class_get_methods (klass, &iter))) {
3896 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3898 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3899 if (bflags & BFLAGS_Public)
3902 if (bflags & BFLAGS_NonPublic)
3908 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3909 if (bflags & BFLAGS_Static)
3910 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3913 if (bflags & BFLAGS_Instance)
3919 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3920 if (!mono_error_ok (&error)) {
3921 mono_error_set_pending_exception (&error);
3925 mono_ptr_array_append (tmp_array, member);
3928 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
3930 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3931 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3933 mono_ptr_array_destroy (tmp_array);
3939 property_hash (gconstpointer data)
3941 MonoProperty *prop = (MonoProperty*)data;
3943 return g_str_hash (prop->name);
3947 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3949 if (method1->is_inflated)
3950 method1 = ((MonoMethodInflated*) method1)->declaring;
3951 if (method2->is_inflated)
3952 method2 = ((MonoMethodInflated*) method2)->declaring;
3954 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3958 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3960 // Properties are hide-by-name-and-signature
3961 if (!g_str_equal (prop1->name, prop2->name))
3964 /* If we see a property in a generic method, we want to
3965 compare the generic signatures, not the inflated signatures
3966 because we might conflate two properties that were
3970 public T this[T t] { getter { return t; } } // method 1
3971 public U this[U u] { getter { return u; } } // method 2
3974 If we see int Foo<int,int>::Item[int] we need to know if
3975 the indexer came from method 1 or from method 2, and we
3976 shouldn't conflate them. (Bugzilla 36283)
3978 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
3981 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
3988 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3993 return method_nonpublic (accessor, start_klass);
3996 ICALL_EXPORT MonoArray*
3997 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4001 MonoClass *startklass, *klass;
4007 gchar *propname = NULL;
4008 int (*compare_func) (const char *s1, const char *s2) = NULL;
4010 GHashTable *properties = NULL;
4011 MonoPtrArray tmp_array;
4013 mono_error_init (&error);
4015 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4017 domain = ((MonoObject *)type)->vtable->domain;
4018 if (type->type->byref)
4019 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
4020 klass = startklass = mono_class_from_mono_type (type->type);
4023 propname = mono_string_to_utf8 (name);
4024 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4027 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4029 mono_class_setup_methods (klass);
4030 mono_class_setup_vtable (klass);
4031 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4035 while ((prop = mono_class_get_properties (klass, &iter))) {
4041 flags = method->flags;
4044 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4045 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4046 if (bflags & BFLAGS_Public)
4048 } else if (bflags & BFLAGS_NonPublic) {
4049 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4050 property_accessor_nonpublic(prop->set, startklass == klass)) {
4057 if (flags & METHOD_ATTRIBUTE_STATIC) {
4058 if (bflags & BFLAGS_Static)
4059 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4062 if (bflags & BFLAGS_Instance)
4071 if (compare_func (propname, prop->name))
4075 if (g_hash_table_lookup (properties, prop))
4078 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4081 mono_ptr_array_append (tmp_array, pr);
4083 g_hash_table_insert (properties, prop, prop);
4085 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4088 g_hash_table_destroy (properties);
4091 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4092 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4093 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4095 mono_ptr_array_destroy (tmp_array);
4102 if (mono_class_has_failure (klass)) {
4103 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4105 mono_error_set_from_loader_error (&error);
4106 mono_loader_clear_error ();
4111 g_hash_table_destroy (properties);
4114 mono_ptr_array_destroy (tmp_array);
4116 mono_error_set_pending_exception (&error);
4122 event_hash (gconstpointer data)
4124 MonoEvent *event = (MonoEvent*)data;
4126 return g_str_hash (event->name);
4130 event_equal (MonoEvent *event1, MonoEvent *event2)
4132 // Events are hide-by-name
4133 return g_str_equal (event1->name, event2->name);
4136 ICALL_EXPORT MonoArray*
4137 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4141 MonoClass *startklass, *klass;
4147 char *utf8_name = NULL;
4148 int (*compare_func) (const char *s1, const char *s2) = NULL;
4149 GHashTable *events = NULL;
4150 MonoPtrArray tmp_array;
4152 mono_error_init (&error);
4154 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4156 domain = mono_object_domain (type);
4157 if (type->type->byref)
4158 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4159 klass = startklass = mono_class_from_mono_type (type->type);
4161 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4163 mono_class_setup_methods (klass);
4164 mono_class_setup_vtable (klass);
4165 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4169 while ((event = mono_class_get_events (klass, &iter))) {
4171 method = event->add;
4173 method = event->remove;
4175 method = event->raise;
4177 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4178 if (bflags & BFLAGS_Public)
4180 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4181 if (bflags & BFLAGS_NonPublic)
4186 if (bflags & BFLAGS_NonPublic)
4192 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4193 if (bflags & BFLAGS_Static)
4194 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4197 if (bflags & BFLAGS_Instance)
4202 if (bflags & BFLAGS_Instance)
4208 if (utf8_name == NULL) {
4209 utf8_name = mono_string_to_utf8 (name);
4210 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4213 if (compare_func (event->name, utf8_name))
4217 if (g_hash_table_lookup (events, event))
4220 MonoReflectionEvent *ev_obj;
4221 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4224 mono_ptr_array_append (tmp_array, ev_obj);
4226 g_hash_table_insert (events, event, event);
4228 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4231 g_hash_table_destroy (events);
4233 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4235 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4236 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4238 mono_ptr_array_destroy (tmp_array);
4240 if (utf8_name != NULL)
4246 if (mono_class_has_failure (klass)) {
4247 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4249 mono_error_set_from_loader_error (&error);
4250 mono_loader_clear_error ();
4256 g_hash_table_destroy (events);
4257 if (utf8_name != NULL)
4260 mono_ptr_array_destroy (tmp_array);
4262 mono_error_set_pending_exception (&error);
4266 ICALL_EXPORT MonoArray*
4267 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4270 MonoReflectionType *rt;
4278 MonoPtrArray tmp_array;
4280 domain = ((MonoObject *)type)->vtable->domain;
4281 if (type->type->byref)
4282 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4283 klass = mono_class_from_mono_type (type->type);
4286 * If a nested type is generic, return its generic type definition.
4287 * Note that this means that the return value is essentially the set
4288 * of nested types of the generic type definition of @klass.
4290 * A note in MSDN claims that a generic type definition can have
4291 * nested types that aren't generic. In any case, the container of that
4292 * nested type would be the generic type definition.
4294 if (klass->generic_class)
4295 klass = klass->generic_class->container_class;
4297 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4299 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4301 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4302 if (bflags & BFLAGS_Public)
4305 if (bflags & BFLAGS_NonPublic)
4313 str = mono_string_to_utf8 (name);
4314 mono_identifier_unescape_type_name_chars (str);
4317 if (strcmp (nested->name, str))
4321 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4322 mono_error_raise_exception (&error);
4324 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4327 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4329 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4330 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4332 mono_ptr_array_destroy (tmp_array);
4340 ICALL_EXPORT MonoReflectionType*
4341 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4344 MonoReflectionType *ret;
4346 MonoType *type = NULL;
4347 MonoTypeNameParse info;
4348 gboolean type_resolve;
4350 /* On MS.NET, this does not fire a TypeResolve event */
4351 type_resolve = TRUE;
4352 str = mono_string_to_utf8 (name);
4353 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4354 if (!mono_reflection_parse_type (str, &info)) {
4356 mono_reflection_free_type_info (&info);
4358 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4361 /*g_print ("failed parse\n");*/
4365 if (info.assembly.name) {
4367 mono_reflection_free_type_info (&info);
4369 /* 1.0 and 2.0 throw different exceptions */
4370 if (mono_defaults.generic_ilist_class)
4371 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4373 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4379 if (module != NULL) {
4381 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4386 if (assembly_is_dynamic (assembly->assembly)) {
4387 /* Enumerate all modules */
4388 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4392 if (abuilder->modules) {
4393 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4394 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4395 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4401 if (!type && abuilder->loaded_modules) {
4402 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4403 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4404 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4411 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4413 mono_reflection_free_type_info (&info);
4415 MonoException *e = NULL;
4418 e = mono_get_exception_type_load (name, NULL);
4420 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4421 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4423 mono_loader_clear_error ();
4426 mono_set_pending_exception (e);
4428 } else if (mono_loader_get_last_error ()) {
4430 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4433 mono_loader_clear_error ();
4436 if (type->type == MONO_TYPE_CLASS) {
4437 MonoClass *klass = mono_type_get_class (type);
4439 /* need to report exceptions ? */
4440 if (throwOnError && mono_class_has_failure (klass)) {
4441 /* report SecurityException (or others) that occured when loading the assembly */
4442 MonoException *exc = mono_class_get_exception_for_failure (klass);
4443 mono_loader_clear_error ();
4444 mono_set_pending_exception (exc);
4449 /* g_print ("got it\n"); */
4450 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4451 mono_error_raise_exception (&error);
4457 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4460 gchar *shadow_ini_file;
4463 /* Check for shadow-copied assembly */
4464 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4465 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4467 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4468 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4474 g_free (shadow_ini_file);
4475 if (content != NULL) {
4478 *filename = content;
4485 ICALL_EXPORT MonoString *
4486 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4488 MonoDomain *domain = mono_object_domain (assembly);
4489 MonoAssembly *mass = assembly->assembly;
4490 MonoString *res = NULL;
4495 if (g_path_is_absolute (mass->image->name)) {
4496 absolute = g_strdup (mass->image->name);
4497 dirname = g_path_get_dirname (absolute);
4499 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4500 dirname = g_strdup (mass->basedir);
4503 replace_shadow_path (domain, dirname, &absolute);
4508 for (i = strlen (absolute) - 1; i >= 0; i--)
4509 if (absolute [i] == '\\')
4514 uri = g_filename_to_uri (absolute, NULL, NULL);
4516 const char *prepend = "file://";
4518 if (*absolute == '/' && *(absolute + 1) == '/') {
4521 prepend = "file:///";
4524 uri = g_strconcat (prepend, absolute, NULL);
4528 res = mono_string_new (domain, uri);
4535 ICALL_EXPORT MonoBoolean
4536 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4538 MonoAssembly *mass = assembly->assembly;
4540 return mass->in_gac;
4543 ICALL_EXPORT MonoReflectionAssembly*
4544 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4549 MonoImageOpenStatus status;
4550 MonoReflectionAssembly* result = NULL;
4552 name = mono_string_to_utf8 (mname);
4553 res = mono_assembly_load_with_partial_name (name, &status);
4559 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4561 mono_error_set_pending_exception (&error);
4565 ICALL_EXPORT MonoString *
4566 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4568 MonoDomain *domain = mono_object_domain (assembly);
4571 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4576 ICALL_EXPORT MonoBoolean
4577 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4579 return assembly->assembly->ref_only;
4582 ICALL_EXPORT MonoString *
4583 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4585 MonoDomain *domain = mono_object_domain (assembly);
4587 return mono_string_new (domain, assembly->assembly->image->version);
4590 ICALL_EXPORT MonoReflectionMethod*
4591 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4594 MonoReflectionMethod *res = NULL;
4597 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4601 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4602 if (!mono_error_ok (&error))
4605 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4608 if (!mono_error_ok (&error))
4609 mono_error_set_pending_exception (&error);
4613 ICALL_EXPORT MonoReflectionModule*
4614 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4617 MonoReflectionModule *result = NULL;
4618 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4619 if (!mono_error_ok (&error))
4620 mono_error_set_pending_exception (&error);
4624 ICALL_EXPORT MonoArray*
4625 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4627 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4628 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4632 for (i = 0; i < table->rows; ++i) {
4633 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4634 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4640 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4642 static MonoMethod *create_version = NULL;
4646 mono_error_init (error);
4649 if (!create_version) {
4650 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4651 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4652 g_assert (create_version);
4653 mono_method_desc_free (desc);
4659 args [3] = &revision;
4660 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4661 return_val_if_nok (error, NULL);
4663 mono_runtime_invoke_checked (create_version, result, args, error);
4664 return_val_if_nok (error, NULL);
4669 ICALL_EXPORT MonoArray*
4670 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4674 MonoDomain *domain = mono_object_domain (assembly);
4676 static MonoMethod *create_culture = NULL;
4677 MonoImage *image = assembly->assembly->image;
4681 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4684 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4686 if (count > 0 && !create_culture) {
4687 MonoMethodDesc *desc = mono_method_desc_new (
4688 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4689 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4690 g_assert (create_culture);
4691 mono_method_desc_free (desc);
4694 for (i = 0; i < count; i++) {
4695 MonoObject *version;
4696 MonoReflectionAssemblyName *aname;
4697 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4699 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4701 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4702 domain, mono_class_get_assembly_name_class (), &error);
4703 mono_error_raise_exception (&error);
4705 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4707 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4708 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4709 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4710 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4711 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4712 aname->versioncompat = 1; /* SameMachine (default) */
4713 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4715 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4716 mono_error_raise_exception (&error);
4718 MONO_OBJECT_SETREF (aname, version, version);
4720 if (create_culture) {
4722 MonoBoolean assembly_ref = 1;
4723 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4724 args [1] = &assembly_ref;
4726 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4727 mono_error_raise_exception (&error);
4729 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4732 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4733 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4734 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4736 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4737 /* public key token isn't copied - the class library will
4738 automatically generate it from the public key if required */
4739 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4740 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4742 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4743 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4746 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4749 /* note: this function doesn't return the codebase on purpose (i.e. it can
4750 be used under partial trust as path information isn't present). */
4752 mono_array_setref (result, i, aname);
4757 /* move this in some file in mono/util/ */
4759 g_concat_dir_and_file (const char *dir, const char *file)
4761 g_return_val_if_fail (dir != NULL, NULL);
4762 g_return_val_if_fail (file != NULL, NULL);
4765 * If the directory name doesn't have a / on the end, we need
4766 * to add one so we get a proper path to the file
4768 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4769 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4771 return g_strconcat (dir, file, NULL);
4775 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4778 char *n = mono_string_to_utf8 (name);
4779 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4781 guint32 cols [MONO_MANIFEST_SIZE];
4782 guint32 impl, file_idx;
4786 for (i = 0; i < table->rows; ++i) {
4787 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4788 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4789 if (strcmp (val, n) == 0)
4793 if (i == table->rows)
4796 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4799 * this code should only be called after obtaining the
4800 * ResourceInfo and handling the other cases.
4802 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4803 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4805 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4810 module = assembly->assembly->image;
4813 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4814 mono_error_raise_exception (&error);
4815 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4817 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4820 ICALL_EXPORT gboolean
4821 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4824 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4826 guint32 cols [MONO_MANIFEST_SIZE];
4827 guint32 file_cols [MONO_FILE_SIZE];
4831 n = mono_string_to_utf8 (name);
4832 for (i = 0; i < table->rows; ++i) {
4833 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4834 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4835 if (strcmp (val, n) == 0)
4839 if (i == table->rows)
4842 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4843 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4846 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4847 case MONO_IMPLEMENTATION_FILE:
4848 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4849 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4850 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4851 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4852 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4853 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4856 info->location = RESOURCE_LOCATION_EMBEDDED;
4859 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4860 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4861 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4862 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4863 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4864 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4866 mono_set_pending_exception (ex);
4869 MonoReflectionAssembly *assm_obj;
4870 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4872 mono_error_set_pending_exception (&error);
4875 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4877 /* Obtain info recursively */
4878 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4879 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4882 case MONO_IMPLEMENTATION_EXP_TYPE:
4883 g_assert_not_reached ();
4891 ICALL_EXPORT MonoObject*
4892 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4894 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4895 MonoArray *result = NULL;
4900 /* check hash if needed */
4902 n = mono_string_to_utf8 (name);
4903 for (i = 0; i < table->rows; ++i) {
4904 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4905 if (strcmp (val, n) == 0) {
4908 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4909 fn = mono_string_new (mono_object_domain (assembly), n);
4911 return (MonoObject*)fn;
4919 for (i = 0; i < table->rows; ++i) {
4920 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4924 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4927 for (i = 0; i < table->rows; ++i) {
4928 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4929 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4930 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4931 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4936 return (MonoObject*)result;
4939 ICALL_EXPORT MonoArray*
4940 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4943 MonoDomain *domain = mono_domain_get();
4946 int i, j, file_count = 0;
4947 MonoImage **modules;
4948 guint32 module_count, real_module_count;
4949 MonoTableInfo *table;
4950 guint32 cols [MONO_FILE_SIZE];
4951 MonoImage *image = assembly->assembly->image;
4953 g_assert (image != NULL);
4954 g_assert (!assembly_is_dynamic (assembly->assembly));
4956 table = &image->tables [MONO_TABLE_FILE];
4957 file_count = table->rows;
4959 modules = image->modules;
4960 module_count = image->module_count;
4962 real_module_count = 0;
4963 for (i = 0; i < module_count; ++i)
4965 real_module_count ++;
4967 klass = mono_class_get_module_class ();
4968 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4970 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
4971 mono_error_raise_exception (&error);
4972 mono_array_setref (res, 0, image_obj);
4974 for (i = 0; i < module_count; ++i)
4976 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
4977 mono_error_raise_exception (&error);
4978 mono_array_setref (res, j, rm);
4982 for (i = 0; i < file_count; ++i, ++j) {
4983 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4984 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
4985 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
4986 mono_error_raise_exception (&error);
4987 mono_array_setref (res, j, rm);
4990 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4992 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4993 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
4996 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
4997 mono_error_raise_exception (&error);
4998 mono_array_setref (res, j, rm);
5005 ICALL_EXPORT MonoReflectionMethod*
5006 ves_icall_GetCurrentMethod (void)
5008 MonoReflectionMethod *res = NULL;
5011 MonoMethod *m = mono_method_get_last_managed ();
5014 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5018 while (m->is_inflated)
5019 m = ((MonoMethodInflated*)m)->declaring;
5021 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5022 mono_error_raise_exception (&error);
5028 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5031 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5034 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5035 //method is inflated, we should inflate it on the other class
5036 MonoGenericContext ctx;
5037 ctx.method_inst = inflated->context.method_inst;
5038 ctx.class_inst = inflated->context.class_inst;
5039 if (klass->generic_class)
5040 ctx.class_inst = klass->generic_class->context.class_inst;
5041 else if (klass->generic_container)
5042 ctx.class_inst = klass->generic_container->context.class_inst;
5043 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5044 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5048 mono_class_setup_methods (method->klass);
5049 if (mono_class_has_failure (method->klass))
5051 for (i = 0; i < method->klass->method.count; ++i) {
5052 if (method->klass->methods [i] == method) {
5057 mono_class_setup_methods (klass);
5058 if (mono_class_has_failure (klass))
5060 g_assert (offset >= 0 && offset < klass->method.count);
5061 return klass->methods [offset];
5064 ICALL_EXPORT MonoReflectionMethod*
5065 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5067 MonoReflectionMethod *res = NULL;
5071 klass = mono_class_from_mono_type (type);
5072 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5074 if (method->klass != klass) {
5075 method = mono_method_get_equivalent_method (method, klass);
5080 klass = method->klass;
5081 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5082 mono_error_raise_exception (&error);
5086 ICALL_EXPORT MonoReflectionMethodBody*
5087 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5089 return mono_method_body_get_object (mono_domain_get (), method);
5092 ICALL_EXPORT MonoReflectionAssembly*
5093 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5096 MonoReflectionAssembly *result;
5097 MonoMethod *dest = NULL;
5099 mono_stack_walk_no_il (get_executing, &dest);
5101 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5103 mono_error_set_pending_exception (&error);
5108 ICALL_EXPORT MonoReflectionAssembly*
5109 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5112 MonoReflectionAssembly *result;
5113 MonoDomain* domain = mono_domain_get ();
5115 if (!domain->entry_assembly)
5118 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5120 mono_error_set_pending_exception (&error);
5124 ICALL_EXPORT MonoReflectionAssembly*
5125 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5130 MonoReflectionAssembly *result;
5133 mono_stack_walk_no_il (get_executing, &dest);
5135 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5139 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5142 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5144 mono_error_set_pending_exception (&error);
5148 ICALL_EXPORT MonoString *
5149 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5150 gboolean assembly_qualified)
5152 MonoDomain *domain = mono_object_domain (object);
5153 MonoTypeNameFormat format;
5158 format = assembly_qualified ?
5159 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5160 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5162 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5164 name = mono_type_get_name_full (object->type, format);
5168 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5173 res = mono_string_new (domain, name);
5180 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5183 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5185 mono_class_init_checked (klass, &error);
5186 mono_error_raise_exception (&error);
5187 return mono_security_core_clr_class_level (klass);
5191 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5193 MonoClassField *field = rfield->field;
5194 return mono_security_core_clr_field_level (field, TRUE);
5198 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5200 MonoMethod *method = rfield->method;
5201 return mono_security_core_clr_method_level (method, TRUE);
5205 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)
5207 static MonoMethod *create_culture = NULL;
5211 const char *pkey_ptr;
5213 MonoBoolean assembly_ref = 0;
5215 mono_error_init (error);
5217 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5218 aname->major = name->major;
5219 aname->minor = name->minor;
5220 aname->build = name->build;
5221 aname->flags = name->flags;
5222 aname->revision = name->revision;
5223 aname->hashalg = name->hash_alg;
5224 aname->versioncompat = 1; /* SameMachine (default) */
5225 aname->processor_architecture = name->arch;
5227 if (by_default_version) {
5228 MonoObject *version;
5230 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5231 return_if_nok (error);
5233 MONO_OBJECT_SETREF (aname, version, version);
5237 if (absolute != NULL && *absolute != '\0') {
5238 const gchar *prepend = "file://";
5241 codebase = g_strdup (absolute);
5246 for (i = strlen (codebase) - 1; i >= 0; i--)
5247 if (codebase [i] == '\\')
5250 if (*codebase == '/' && *(codebase + 1) == '/') {
5253 prepend = "file:///";
5257 result = g_strconcat (prepend, codebase, NULL);
5263 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5267 if (!create_culture) {
5268 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5269 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5270 g_assert (create_culture);
5271 mono_method_desc_free (desc);
5274 if (name->culture) {
5275 args [0] = mono_string_new (domain, name->culture);
5276 args [1] = &assembly_ref;
5278 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5279 return_if_nok (error);
5281 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5284 if (name->public_key) {
5285 pkey_ptr = (char*)name->public_key;
5286 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5288 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5289 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5290 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5291 } else if (default_publickey) {
5292 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5293 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5296 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5297 if (name->public_key_token [0]) {
5301 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5302 p = mono_array_addr (aname->keyToken, char, 0);
5304 for (i = 0, j = 0; i < 8; i++) {
5305 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5306 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5309 } else if (default_token) {
5310 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5314 ICALL_EXPORT MonoString *
5315 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5317 MonoDomain *domain = mono_object_domain (assembly);
5318 MonoAssembly *mass = assembly->assembly;
5322 name = mono_stringify_assembly_name (&mass->aname);
5323 res = mono_string_new (domain, name);
5330 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5334 MonoAssembly *mass = assembly->assembly;
5336 if (g_path_is_absolute (mass->image->name)) {
5337 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5338 mono_error_set_pending_exception (&error);
5341 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5343 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5344 mono_error_set_pending_exception (&error);
5350 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5354 MonoImageOpenStatus status = MONO_IMAGE_OK;
5357 MonoAssemblyName name;
5360 filename = mono_string_to_utf8 (fname);
5362 dirname = g_path_get_dirname (filename);
5363 replace_shadow_path (mono_domain_get (), dirname, &filename);
5366 image = mono_image_open (filename, &status);
5372 if (status == MONO_IMAGE_IMAGE_INVALID)
5373 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5375 exc = mono_get_exception_file_not_found2 (NULL, fname);
5376 mono_set_pending_exception (exc);
5380 res = mono_assembly_fill_assembly_name (image, &name);
5382 mono_image_close (image);
5384 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5388 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5389 mono_error_set_pending_exception (&error);
5391 mono_image_close (image);
5395 ICALL_EXPORT MonoBoolean
5396 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5397 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5399 MonoBoolean result = FALSE;
5400 MonoDeclSecurityEntry entry;
5402 /* SecurityAction.RequestMinimum */
5403 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5404 *minimum = entry.blob;
5405 *minLength = entry.size;
5408 /* SecurityAction.RequestOptional */
5409 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5410 *optional = entry.blob;
5411 *optLength = entry.size;
5414 /* SecurityAction.RequestRefuse */
5415 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5416 *refused = entry.blob;
5417 *refLength = entry.size;
5425 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5427 guint32 attrs, visibility;
5429 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5430 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5431 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5434 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5440 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5442 MonoReflectionType *rt;
5445 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5448 mono_error_init (error);
5450 /* we start the count from 1 because we skip the special type <Module> */
5453 for (i = 1; i < tdef->rows; ++i) {
5454 if (mono_module_type_is_visible (tdef, image, i + 1))
5458 count = tdef->rows - 1;
5460 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5461 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5463 for (i = 1; i < tdef->rows; ++i) {
5464 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5465 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5466 mono_loader_assert_no_error (); /* Plug any leaks */
5467 mono_error_assert_ok (error);
5470 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5471 return_val_if_nok (error, NULL);
5473 mono_array_setref (res, count, rt);
5475 MonoException *ex = mono_error_convert_to_exception (error);
5476 mono_array_setref (*exceptions, count, ex);
5485 ICALL_EXPORT MonoArray*
5486 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5489 MonoArray *res = NULL;
5490 MonoArray *exceptions = NULL;
5491 MonoImage *image = NULL;
5492 MonoTableInfo *table = NULL;
5495 int i, len, ex_count;
5497 domain = mono_object_domain (assembly);
5499 g_assert (!assembly_is_dynamic (assembly->assembly));
5500 image = assembly->assembly->image;
5501 table = &image->tables [MONO_TABLE_FILE];
5502 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5503 mono_error_raise_exception (&error);
5505 /* Append data from all modules in the assembly */
5506 for (i = 0; i < table->rows; ++i) {
5507 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5508 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5513 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5514 mono_error_raise_exception (&error);
5516 /* Append the new types to the end of the array */
5517 if (mono_array_length (res2) > 0) {
5519 MonoArray *res3, *ex3;
5521 len1 = mono_array_length (res);
5522 len2 = mono_array_length (res2);
5524 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5525 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5526 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5529 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5530 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5531 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5538 /* the ReflectionTypeLoadException must have all the types (Types property),
5539 * NULL replacing types which throws an exception. The LoaderException must
5540 * contain all exceptions for NULL items.
5543 len = mono_array_length (res);
5546 for (i = 0; i < len; i++) {
5547 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5551 klass = mono_type_get_class (t->type);
5552 if ((klass != NULL) && mono_class_has_failure (klass)) {
5553 /* keep the class in the list */
5554 list = g_list_append (list, klass);
5555 /* and replace Type with NULL */
5556 mono_array_setref (res, i, NULL);
5563 if (list || ex_count) {
5565 MonoException *exc = NULL;
5566 MonoArray *exl = NULL;
5567 int j, length = g_list_length (list) + ex_count;
5569 mono_loader_clear_error ();
5571 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5572 /* Types for which mono_class_get_checked () succeeded */
5573 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5574 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5575 mono_array_setref (exl, i, exc);
5577 /* Types for which it don't */
5578 for (j = 0; j < mono_array_length (exceptions); ++j) {
5579 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5581 g_assert (i < length);
5582 mono_array_setref (exl, i, exc);
5589 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5590 if (!is_ok (&error)) {
5591 mono_error_set_pending_exception (&error);
5594 mono_loader_clear_error ();
5595 mono_set_pending_exception (exc);
5602 ICALL_EXPORT gboolean
5603 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5606 MonoAssemblyName aname;
5607 MonoDomain *domain = mono_object_domain (name);
5609 gboolean is_version_defined;
5610 gboolean is_token_defined;
5612 aname.public_key = NULL;
5613 val = mono_string_to_utf8 (assname);
5614 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5615 g_free ((guint8*) aname.public_key);
5620 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5621 mono_error_set_pending_exception (&error);
5623 mono_assembly_name_free (&aname);
5624 g_free ((guint8*) aname.public_key);
5630 ICALL_EXPORT MonoReflectionType*
5631 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5634 MonoReflectionType *ret;
5635 MonoDomain *domain = mono_object_domain (module);
5638 g_assert (module->image);
5640 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5641 /* These images do not have a global type */
5644 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5645 if (!mono_error_ok (&error)) {
5646 mono_error_set_pending_exception (&error);
5650 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5651 if (!mono_error_ok (&error)) {
5652 mono_error_set_pending_exception (&error);
5660 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5662 /*if (module->image)
5663 mono_image_close (module->image);*/
5666 ICALL_EXPORT MonoString*
5667 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5669 MonoDomain *domain = mono_object_domain (module);
5671 g_assert (module->image);
5672 return mono_string_new (domain, module->image->guid);
5675 ICALL_EXPORT gpointer
5676 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5679 if (module->image && module->image->is_module_handle)
5680 return module->image->raw_data;
5683 return (gpointer) (-1);
5687 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5689 if (image_is_dynamic (image)) {
5690 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5691 *pe_kind = dyn->pe_kind;
5692 *machine = dyn->machine;
5695 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5696 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5701 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5703 return (image->md_version_major << 16) | (image->md_version_minor);
5706 ICALL_EXPORT MonoArray*
5707 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5710 MonoArray *exceptions;
5714 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5718 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5719 mono_error_raise_exception (&error);
5721 for (i = 0; i < mono_array_length (exceptions); ++i) {
5722 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5724 mono_set_pending_exception (ex);
5733 mono_memberref_is_method (MonoImage *image, guint32 token)
5735 if (!image_is_dynamic (image)) {
5736 guint32 cols [MONO_MEMBERREF_SIZE];
5738 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5739 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5740 mono_metadata_decode_blob_size (sig, &sig);
5741 return (*sig != 0x6);
5743 MonoClass *handle_class;
5745 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5748 return mono_defaults.methodhandle_class == handle_class;
5753 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5756 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5757 mono_array_addr (type_args, MonoType*, 0));
5759 context->class_inst = NULL;
5761 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5762 mono_array_addr (method_args, MonoType*, 0));
5764 context->method_inst = NULL;
5767 ICALL_EXPORT MonoType*
5768 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5771 int table = mono_metadata_token_table (token);
5772 int index = mono_metadata_token_index (token);
5773 MonoGenericContext context;
5776 *resolve_error = ResolveTokenError_Other;
5778 /* Validate token */
5779 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5780 (table != MONO_TABLE_TYPESPEC)) {
5781 *resolve_error = ResolveTokenError_BadTable;
5785 if (image_is_dynamic (image)) {
5786 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5787 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5788 return klass ? &klass->byval_arg : NULL;
5791 init_generic_context_from_args (&context, type_args, method_args);
5792 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5793 return klass ? &klass->byval_arg : NULL;
5796 if ((index <= 0) || (index > image->tables [table].rows)) {
5797 *resolve_error = ResolveTokenError_OutOfRange;
5801 init_generic_context_from_args (&context, type_args, method_args);
5802 klass = mono_class_get_checked (image, token, &error);
5804 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5805 if (!mono_error_ok (&error)) {
5806 mono_error_set_pending_exception (&error);
5811 return &klass->byval_arg;
5816 ICALL_EXPORT MonoMethod*
5817 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5820 int table = mono_metadata_token_table (token);
5821 int index = mono_metadata_token_index (token);
5822 MonoGenericContext context;
5825 *resolve_error = ResolveTokenError_Other;
5827 /* Validate token */
5828 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5829 (table != MONO_TABLE_MEMBERREF)) {
5830 *resolve_error = ResolveTokenError_BadTable;
5834 if (image_is_dynamic (image)) {
5835 if (table == MONO_TABLE_METHOD)
5836 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5838 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5839 *resolve_error = ResolveTokenError_BadTable;
5843 init_generic_context_from_args (&context, type_args, method_args);
5844 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5847 if ((index <= 0) || (index > image->tables [table].rows)) {
5848 *resolve_error = ResolveTokenError_OutOfRange;
5851 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5852 *resolve_error = ResolveTokenError_BadTable;
5856 init_generic_context_from_args (&context, type_args, method_args);
5857 method = mono_get_method_checked (image, token, NULL, &context, &error);
5858 mono_error_set_pending_exception (&error);
5863 ICALL_EXPORT MonoString*
5864 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5866 int index = mono_metadata_token_index (token);
5868 *error = ResolveTokenError_Other;
5870 /* Validate token */
5871 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5872 *error = ResolveTokenError_BadTable;
5876 if (image_is_dynamic (image))
5877 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5879 if ((index <= 0) || (index >= image->heap_us.size)) {
5880 *error = ResolveTokenError_OutOfRange;
5884 /* FIXME: What to do if the index points into the middle of a string ? */
5886 return mono_ldstr (mono_domain_get (), image, index);
5889 ICALL_EXPORT MonoClassField*
5890 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5894 int table = mono_metadata_token_table (token);
5895 int index = mono_metadata_token_index (token);
5896 MonoGenericContext context;
5897 MonoClassField *field;
5899 *resolve_error = ResolveTokenError_Other;
5901 /* Validate token */
5902 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5903 *resolve_error = ResolveTokenError_BadTable;
5907 if (image_is_dynamic (image)) {
5908 if (table == MONO_TABLE_FIELD)
5909 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5911 if (mono_memberref_is_method (image, token)) {
5912 *resolve_error = ResolveTokenError_BadTable;
5916 init_generic_context_from_args (&context, type_args, method_args);
5917 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5920 if ((index <= 0) || (index > image->tables [table].rows)) {
5921 *resolve_error = ResolveTokenError_OutOfRange;
5924 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5925 *resolve_error = ResolveTokenError_BadTable;
5929 init_generic_context_from_args (&context, type_args, method_args);
5930 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5931 mono_error_set_pending_exception (&error);
5937 ICALL_EXPORT MonoObject*
5938 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5942 int table = mono_metadata_token_table (token);
5944 *error = ResolveTokenError_Other;
5947 case MONO_TABLE_TYPEDEF:
5948 case MONO_TABLE_TYPEREF:
5949 case MONO_TABLE_TYPESPEC: {
5950 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5952 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
5953 mono_error_raise_exception (&merror);
5960 case MONO_TABLE_METHOD:
5961 case MONO_TABLE_METHODSPEC: {
5962 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5964 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5965 mono_error_raise_exception (&merror);
5971 case MONO_TABLE_FIELD: {
5972 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5974 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5975 mono_error_raise_exception (&merror);
5981 case MONO_TABLE_MEMBERREF:
5982 if (mono_memberref_is_method (image, token)) {
5983 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5985 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5986 mono_error_raise_exception (&merror);
5993 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5995 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5996 mono_error_raise_exception (&merror);
6005 *error = ResolveTokenError_BadTable;
6011 ICALL_EXPORT MonoArray*
6012 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
6014 int table = mono_metadata_token_table (token);
6015 int idx = mono_metadata_token_index (token);
6016 MonoTableInfo *tables = image->tables;
6021 *error = ResolveTokenError_OutOfRange;
6023 /* FIXME: Support other tables ? */
6024 if (table != MONO_TABLE_STANDALONESIG)
6027 if (image_is_dynamic (image))
6030 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6033 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6035 ptr = mono_metadata_blob_heap (image, sig);
6036 len = mono_metadata_decode_blob_size (ptr, &ptr);
6038 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
6039 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6043 ICALL_EXPORT MonoReflectionType*
6044 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6047 MonoReflectionType *ret;
6049 int isbyref = 0, rank;
6050 char *str = mono_string_to_utf8 (smodifiers);
6053 klass = mono_class_from_mono_type (tb->type.type);
6055 /* logic taken from mono_reflection_parse_type(): keep in sync */
6059 if (isbyref) { /* only one level allowed by the spec */
6068 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6069 mono_error_raise_exception (&error);
6073 klass = mono_ptr_class_get (&klass->byval_arg);
6074 mono_class_init (klass);
6085 else if (*p != '*') { /* '*' means unknown lower bound */
6096 klass = mono_array_class_get (klass, rank);
6097 mono_class_init (klass);
6106 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6107 mono_error_raise_exception (&error);
6112 ICALL_EXPORT MonoBoolean
6113 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6119 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6125 check_for_invalid_type (MonoClass *klass, MonoError *error)
6130 mono_error_init (error);
6132 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6135 name = mono_type_get_full_name (klass);
6136 str = mono_string_new (mono_domain_get (), name);
6138 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6141 ICALL_EXPORT MonoReflectionType *
6142 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6145 MonoReflectionType *ret;
6146 MonoClass *klass, *aklass;
6148 klass = mono_class_from_mono_type (type->type);
6149 check_for_invalid_type (klass, &error);
6150 mono_error_raise_exception (&error);
6152 if (rank == 0) //single dimentional array
6153 aklass = mono_array_class_get (klass, 1);
6155 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6157 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6158 mono_error_raise_exception (&error);
6163 ICALL_EXPORT MonoReflectionType *
6164 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6167 MonoReflectionType *ret;
6170 klass = mono_class_from_mono_type (type->type);
6171 mono_class_init_checked (klass, &error);
6172 mono_error_raise_exception (&error);
6173 check_for_invalid_type (klass, &error);
6174 mono_error_raise_exception (&error);
6176 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6177 mono_error_raise_exception (&error);
6182 ICALL_EXPORT MonoReflectionType *
6183 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6186 MonoReflectionType *ret;
6187 MonoClass *klass, *pklass;
6189 klass = mono_class_from_mono_type (type->type);
6190 mono_class_init_checked (klass, &error);
6191 mono_error_raise_exception (&error);
6192 check_for_invalid_type (klass, &error);
6193 mono_error_raise_exception (&error);
6195 pklass = mono_ptr_class_get (type->type);
6197 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6198 mono_error_raise_exception (&error);
6203 ICALL_EXPORT MonoObject *
6204 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6205 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6208 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6209 MonoObject *delegate;
6211 MonoMethod *method = info->method;
6213 mono_class_init_checked (delegate_class, &error);
6214 mono_error_raise_exception (&error);
6216 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
6218 if (mono_security_core_clr_enabled ()) {
6219 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6223 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6224 mono_error_raise_exception (&error);
6226 if (method_is_dynamic (method)) {
6227 /* Creating a trampoline would leak memory */
6228 func = mono_compile_method (method);
6230 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6231 method = mono_object_get_virtual_method (target, method);
6232 func = mono_create_ftnptr (mono_domain_get (),
6233 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6236 mono_delegate_ctor_with_method (delegate, target, func, method);
6241 ICALL_EXPORT MonoMulticastDelegate *
6242 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6245 MonoMulticastDelegate *ret;
6247 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6249 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6250 mono_error_raise_exception (&error);
6251 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6256 ICALL_EXPORT MonoReflectionMethod*
6257 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6259 MonoReflectionMethod *ret = NULL;
6261 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6262 mono_error_raise_exception (&error);
6268 static inline gint32
6269 mono_array_get_byte_length (MonoArray *array)
6275 klass = array->obj.vtable->klass;
6277 if (array->bounds == NULL)
6278 length = array->max_length;
6281 for (i = 0; i < klass->rank; ++ i)
6282 length *= array->bounds [i].length;
6285 switch (klass->element_class->byval_arg.type) {
6288 case MONO_TYPE_BOOLEAN:
6292 case MONO_TYPE_CHAR:
6300 return length * sizeof (gpointer);
6311 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6313 return mono_array_get_byte_length (array);
6317 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6319 return mono_array_get (array, gint8, idx);
6323 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6325 mono_array_set (array, gint8, idx, value);
6328 ICALL_EXPORT MonoBoolean
6329 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6331 guint8 *src_buf, *dest_buf;
6334 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6338 g_assert (count >= 0);
6340 /* This is called directly from the class libraries without going through the managed wrapper */
6341 MONO_CHECK_ARG_NULL (src, FALSE);
6342 MONO_CHECK_ARG_NULL (dest, FALSE);
6344 /* watch out for integer overflow */
6345 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6348 src_buf = (guint8 *)src->vector + src_offset;
6349 dest_buf = (guint8 *)dest->vector + dest_offset;
6352 memcpy (dest_buf, src_buf, count);
6354 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6359 #ifndef DISABLE_REMOTING
6360 ICALL_EXPORT MonoObject *
6361 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6364 MonoDomain *domain = mono_object_domain (this_obj);
6366 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6367 MonoTransparentProxy *tp;
6371 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6372 mono_error_raise_exception (&error);
6373 tp = (MonoTransparentProxy*) res;
6375 MONO_OBJECT_SETREF (tp, rp, rp);
6376 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6377 klass = mono_class_from_mono_type (type);
6379 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6380 mono_class_setup_vtable (klass);
6381 if (mono_class_has_failure (klass)) {
6382 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6386 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
6387 tp->remote_class = mono_remote_class (domain, class_name, klass);
6389 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6393 ICALL_EXPORT MonoReflectionType *
6394 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6397 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6398 mono_error_raise_exception (&error);
6404 /* System.Environment */
6407 ves_icall_System_Environment_get_UserName (void)
6409 /* using glib is more portable */
6410 return mono_string_new (mono_domain_get (), g_get_user_name ());
6414 ICALL_EXPORT MonoString *
6415 ves_icall_System_Environment_get_MachineName (void)
6417 #if defined (HOST_WIN32)
6422 len = MAX_COMPUTERNAME_LENGTH + 1;
6423 buf = g_new (gunichar2, len);
6426 if (GetComputerName (buf, (PDWORD) &len)) {
6428 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6429 mono_error_raise_exception (&error);
6434 #elif !defined(DISABLE_SOCKETS)
6438 #if defined _SC_HOST_NAME_MAX
6439 n = sysconf (_SC_HOST_NAME_MAX);
6443 buf = g_malloc (n+1);
6445 if (gethostname (buf, n) == 0){
6447 result = mono_string_new (mono_domain_get (), buf);
6454 return mono_string_new (mono_domain_get (), "mono");
6459 ves_icall_System_Environment_get_Platform (void)
6461 #if defined (TARGET_WIN32)
6464 #elif defined(__MACH__)
6467 // Notice that the value is hidden from user code, and only exposed
6468 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6469 // define and making assumptions based on Unix/128/4 values before there
6470 // was a MacOS define. Lots of code would assume that not-Unix meant
6471 // Windows, but in this case, it would be OSX.
6480 ICALL_EXPORT MonoString *
6481 ves_icall_System_Environment_get_NewLine (void)
6483 #if defined (HOST_WIN32)
6484 return mono_string_new (mono_domain_get (), "\r\n");
6486 return mono_string_new (mono_domain_get (), "\n");
6490 ICALL_EXPORT MonoBoolean
6491 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6493 #if SIZEOF_VOID_P == 8
6497 gboolean isWow64Process = FALSE;
6498 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6499 return (MonoBoolean)isWow64Process;
6501 #elif defined(HAVE_SYS_UTSNAME_H)
6502 struct utsname name;
6504 if (uname (&name) >= 0) {
6505 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6512 ICALL_EXPORT MonoString *
6513 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6521 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6522 value = g_getenv (utf8_name);
6529 return mono_string_new (mono_domain_get (), value);
6533 * There is no standard way to get at environ.
6536 #ifndef __MINGW32_VERSION
6537 #if defined(__APPLE__)
6538 #if defined (TARGET_OSX)
6539 /* Apple defines this in crt_externs.h but doesn't provide that header for
6540 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6541 * in fact exist on all implementations (so far)
6543 gchar ***_NSGetEnviron(void);
6544 #define environ (*_NSGetEnviron())
6546 static char *mono_environ[1] = { NULL };
6547 #define environ mono_environ
6548 #endif /* defined (TARGET_OSX) */
6556 ICALL_EXPORT MonoArray *
6557 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6568 env_strings = GetEnvironmentStrings();
6571 env_string = env_strings;
6572 while (*env_string != '\0') {
6573 /* weird case that MS seems to skip */
6574 if (*env_string != '=')
6576 while (*env_string != '\0')
6582 domain = mono_domain_get ();
6583 names = mono_array_new (domain, mono_defaults.string_class, n);
6587 env_string = env_strings;
6588 while (*env_string != '\0') {
6589 /* weird case that MS seems to skip */
6590 if (*env_string != '=') {
6591 equal_str = wcschr(env_string, '=');
6592 g_assert(equal_str);
6594 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6595 mono_error_raise_exception (&error);
6596 mono_array_setref (names, n, str);
6599 while (*env_string != '\0')
6604 FreeEnvironmentStrings (env_strings);
6617 for (e = environ; *e != 0; ++ e)
6620 domain = mono_domain_get ();
6621 names = mono_array_new (domain, mono_defaults.string_class, n);
6624 for (e = environ; *e != 0; ++ e) {
6625 parts = g_strsplit (*e, "=", 2);
6627 str = mono_string_new (domain, *parts);
6628 mono_array_setref (names, n, str);
6641 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6643 #if !GLIB_CHECK_VERSION(2,4,0)
6644 #define g_setenv(a,b,c) setenv(a,b,c)
6645 #define g_unsetenv(a) unsetenv(a)
6649 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6652 gunichar2 *utf16_name, *utf16_value;
6654 gchar *utf8_name, *utf8_value;
6659 utf16_name = mono_string_to_utf16 (name);
6660 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6661 SetEnvironmentVariable (utf16_name, NULL);
6662 g_free (utf16_name);
6666 utf16_value = mono_string_to_utf16 (value);
6668 SetEnvironmentVariable (utf16_name, utf16_value);
6670 g_free (utf16_name);
6671 g_free (utf16_value);
6673 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6675 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6676 g_unsetenv (utf8_name);
6681 utf8_value = mono_string_to_utf8_checked (value, &error);
6682 if (!mono_error_ok (&error)) {
6684 mono_error_set_pending_exception (&error);
6687 g_setenv (utf8_name, utf8_value, TRUE);
6690 g_free (utf8_value);
6695 ves_icall_System_Environment_Exit (int result)
6697 mono_environment_exitcode_set (result);
6699 /* FIXME: There are some cleanup hangs that should be worked out, but
6700 * if the program is going to exit, everything will be cleaned up when
6701 * NaCl exits anyway.
6703 #ifndef __native_client__
6704 if (!mono_runtime_try_shutdown ())
6705 mono_thread_exit ();
6707 /* Suspend all managed threads since the runtime is going away */
6708 mono_thread_suspend_all_other_threads ();
6710 mono_runtime_quit ();
6713 /* we may need to do some cleanup here... */
6717 ICALL_EXPORT MonoString*
6718 ves_icall_System_Environment_GetGacPath (void)
6720 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6723 ICALL_EXPORT MonoString*
6724 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6726 #if defined (HOST_WIN32)
6727 #ifndef CSIDL_FLAG_CREATE
6728 #define CSIDL_FLAG_CREATE 0x8000
6731 WCHAR path [MAX_PATH];
6732 /* Create directory if no existing */
6733 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6738 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6739 mono_error_raise_exception (&error);
6743 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6745 return mono_string_new (mono_domain_get (), "");
6748 ICALL_EXPORT MonoArray *
6749 ves_icall_System_Environment_GetLogicalDrives (void)
6752 gunichar2 buf [256], *ptr, *dname;
6754 guint initial_size = 127, size = 128;
6757 MonoString *drivestr;
6758 MonoDomain *domain = mono_domain_get ();
6764 while (size > initial_size) {
6765 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6766 if (size > initial_size) {
6769 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6770 initial_size = size;
6784 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6789 while (*u16) { u16++; len ++; }
6790 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6791 mono_error_raise_exception (&error);
6792 mono_array_setref (result, ndrives++, drivestr);
6802 ICALL_EXPORT MonoString *
6803 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6805 gunichar2 volume_name [MAX_PATH + 1];
6807 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6809 return mono_string_from_utf16 (volume_name);
6812 ICALL_EXPORT MonoString *
6813 ves_icall_System_Environment_InternalGetHome (void)
6815 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6818 static const char *encodings [] = {
6820 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6821 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6822 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6824 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6825 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6826 "x_unicode_2_0_utf_7",
6828 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6829 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6831 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6834 "unicodefffe", "utf_16be",
6841 * Returns the internal codepage, if the value of "int_code_page" is
6842 * 1 at entry, and we can not compute a suitable code page number,
6843 * returns the code page as a string
6845 ICALL_EXPORT MonoString*
6846 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6851 char *codepage = NULL;
6853 int want_name = *int_code_page;
6856 *int_code_page = -1;
6858 g_get_charset (&cset);
6859 c = codepage = strdup (cset);
6860 for (c = codepage; *c; c++){
6861 if (isascii (*c) && isalpha (*c))
6866 /* g_print ("charset: %s\n", cset); */
6868 /* handle some common aliases */
6871 for (i = 0; p != 0; ){
6874 p = encodings [++i];
6877 if (strcmp (p, codepage) == 0){
6878 *int_code_page = code;
6881 p = encodings [++i];
6884 if (strstr (codepage, "utf_8") != NULL)
6885 *int_code_page |= 0x10000000;
6888 if (want_name && *int_code_page == -1)
6889 return mono_string_new (mono_domain_get (), cset);
6894 ICALL_EXPORT MonoBoolean
6895 ves_icall_System_Environment_get_HasShutdownStarted (void)
6897 if (mono_runtime_is_shutting_down ())
6900 if (mono_domain_is_unloading (mono_domain_get ()))
6907 ves_icall_System_Environment_BroadcastSettingChange (void)
6910 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6915 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6921 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6922 MonoReflectionMethod *method,
6923 MonoArray *out_args)
6925 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6928 #ifndef DISABLE_REMOTING
6929 ICALL_EXPORT MonoBoolean
6930 ves_icall_IsTransparentProxy (MonoObject *proxy)
6935 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6941 ICALL_EXPORT MonoReflectionMethod *
6942 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6943 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6945 MonoReflectionMethod *ret = NULL;
6950 MonoMethod **vtable;
6951 MonoMethod *res = NULL;
6953 MONO_CHECK_ARG_NULL (rtype, NULL);
6954 MONO_CHECK_ARG_NULL (rmethod, NULL);
6956 method = rmethod->method;
6957 klass = mono_class_from_mono_type (rtype->type);
6958 mono_class_init_checked (klass, &error);
6959 mono_error_raise_exception (&error);
6961 if (MONO_CLASS_IS_INTERFACE (klass))
6964 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6967 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6968 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6974 mono_class_setup_vtable (klass);
6975 vtable = klass->vtable;
6977 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6978 gboolean variance_used = FALSE;
6979 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6980 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6982 res = vtable [offs + method->slot];
6984 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6987 if (method->slot != -1)
6988 res = vtable [method->slot];
6994 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
6995 mono_error_raise_exception (&error);
7000 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7006 klass = mono_class_from_mono_type (type->type);
7007 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7008 if (!is_ok (&error)) {
7009 mono_error_set_pending_exception (&error);
7013 mono_vtable_set_is_remote (vtable, enable);
7016 #else /* DISABLE_REMOTING */
7019 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7021 g_assert_not_reached ();
7026 ICALL_EXPORT MonoObject *
7027 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7034 domain = mono_object_domain (type);
7035 klass = mono_class_from_mono_type (type->type);
7036 mono_class_init_checked (klass, &error);
7037 mono_error_raise_exception (&error);
7039 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7040 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7044 if (klass->rank >= 1) {
7045 g_assert (klass->rank == 1);
7046 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7048 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7049 if (!is_ok (&error)) {
7050 mono_error_set_pending_exception (&error);
7053 /* Bypass remoting object creation check */
7054 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7055 mono_error_set_pending_exception (&error);
7061 ICALL_EXPORT MonoString *
7062 ves_icall_System_IO_get_temp_path (void)
7064 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7067 #ifndef PLATFORM_NO_DRIVEINFO
7068 ICALL_EXPORT MonoBoolean
7069 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7070 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7074 ULARGE_INTEGER wapi_free_bytes_avail;
7075 ULARGE_INTEGER wapi_total_number_of_bytes;
7076 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7078 *error = ERROR_SUCCESS;
7079 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7080 &wapi_total_number_of_free_bytes);
7083 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7084 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7085 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7087 *free_bytes_avail = 0;
7088 *total_number_of_bytes = 0;
7089 *total_number_of_free_bytes = 0;
7090 *error = GetLastError ();
7096 ICALL_EXPORT guint32
7097 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7099 return GetDriveType (mono_string_chars (root_path_name));
7103 ICALL_EXPORT gpointer
7104 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7106 return mono_compile_method (method);
7109 ICALL_EXPORT MonoString *
7110 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7115 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7117 #if defined (HOST_WIN32)
7118 /* Avoid mixing '/' and '\\' */
7121 for (i = strlen (path) - 1; i >= 0; i--)
7122 if (path [i] == '/')
7126 mcpath = mono_string_new (mono_domain_get (), path);
7133 get_bundled_app_config (void)
7135 const gchar *app_config;
7138 gchar *config_file_name, *config_file_path;
7139 gsize len, config_file_path_length, config_ext_length;
7142 domain = mono_domain_get ();
7143 file = domain->setup->configuration_file;
7144 if (!file || file->length == 0)
7147 // Retrieve config file and remove the extension
7148 config_file_name = mono_string_to_utf8 (file);
7149 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7150 if (!config_file_path)
7151 config_file_path = config_file_name;
7153 config_file_path_length = strlen (config_file_path);
7154 config_ext_length = strlen (".config");
7155 if (config_file_path_length <= config_ext_length)
7158 len = config_file_path_length - config_ext_length;
7159 module = (gchar *)g_malloc0 (len + 1);
7160 memcpy (module, config_file_path, len);
7161 // Get the config file from the module name
7162 app_config = mono_config_string_for_assembly_file (module);
7165 if (config_file_name != config_file_path)
7166 g_free (config_file_name);
7167 g_free (config_file_path);
7172 return mono_string_new (mono_domain_get (), app_config);
7176 get_bundled_machine_config (void)
7178 const gchar *machine_config;
7180 machine_config = mono_get_machine_config ();
7182 if (!machine_config)
7185 return mono_string_new (mono_domain_get (), machine_config);
7188 ICALL_EXPORT MonoString *
7189 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7194 path = g_path_get_dirname (mono_get_config_dir ());
7196 #if defined (HOST_WIN32)
7197 /* Avoid mixing '/' and '\\' */
7200 for (i = strlen (path) - 1; i >= 0; i--)
7201 if (path [i] == '/')
7205 ipath = mono_string_new (mono_domain_get (), path);
7211 ICALL_EXPORT gboolean
7212 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7214 MonoPEResourceDataEntry *entry;
7217 if (!assembly || !result || !size)
7222 image = assembly->assembly->image;
7223 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7227 *result = mono_image_rva_map (image, entry->rde_data_offset);
7232 *size = entry->rde_size;
7237 ICALL_EXPORT MonoBoolean
7238 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7240 return mono_is_debugger_attached ();
7243 ICALL_EXPORT MonoBoolean
7244 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7246 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7247 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7253 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7255 if (mono_get_runtime_callbacks ()->debug_log)
7256 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7260 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7262 #if defined (HOST_WIN32)
7263 OutputDebugString (mono_string_chars (message));
7265 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7269 /* Only used for value types */
7270 ICALL_EXPORT MonoObject *
7271 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7278 domain = mono_object_domain (type);
7279 klass = mono_class_from_mono_type (type->type);
7280 mono_class_init_checked (klass, &error);
7281 mono_error_raise_exception (&error);
7283 if (mono_class_is_nullable (klass))
7284 /* No arguments -> null */
7287 result = mono_object_new_checked (domain, klass, &error);
7288 mono_error_raise_exception (&error);
7292 ICALL_EXPORT MonoReflectionMethod *
7293 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7295 MonoReflectionMethod *ret = NULL;
7298 MonoClass *klass, *parent;
7299 MonoGenericContext *generic_inst = NULL;
7300 MonoMethod *method = m->method;
7301 MonoMethod *result = NULL;
7304 if (method->klass == NULL)
7307 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7308 MONO_CLASS_IS_INTERFACE (method->klass) ||
7309 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7312 slot = mono_method_get_vtable_slot (method);
7316 klass = method->klass;
7317 if (klass->generic_class) {
7318 generic_inst = mono_class_get_context (klass);
7319 klass = klass->generic_class->container_class;
7323 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7324 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7325 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7326 or klass is the generic container class and generic_inst is the instantiation.
7328 when we go to the parent, if the parent is an open constructed type, we need to
7329 replace the type parameters by the definitions from the generic_inst, and then take it
7330 apart again into the klass and the generic_inst.
7332 For cases like this:
7333 class C<T> : B<T, int> {
7334 public override void Foo () { ... }
7336 class B<U,V> : A<HashMap<U,V>> {
7337 public override void Foo () { ... }
7340 public virtual void Foo () { ... }
7343 if at each iteration the parent isn't open, we can skip inflating it. if at some
7344 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7347 MonoGenericContext *parent_inst = NULL;
7348 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7350 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7351 if (!mono_error_ok (&error)) {
7352 mono_error_set_pending_exception (&error);
7356 if (parent->generic_class) {
7357 parent_inst = mono_class_get_context (parent);
7358 parent = parent->generic_class->container_class;
7361 mono_class_setup_vtable (parent);
7362 if (parent->vtable_size <= slot)
7365 generic_inst = parent_inst;
7368 klass = klass->parent;
7371 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7372 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7373 if (!mono_error_ok (&error)) {
7374 mono_error_set_pending_exception (&error);
7378 generic_inst = NULL;
7380 if (klass->generic_class) {
7381 generic_inst = mono_class_get_context (klass);
7382 klass = klass->generic_class->container_class;
7388 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7389 if (!mono_error_ok (&error)) {
7390 mono_error_set_pending_exception (&error);
7395 if (klass == method->klass)
7398 /*This is possible if definition == FALSE.
7399 * Do it here to be really sure we don't read invalid memory.
7401 if (slot >= klass->vtable_size)
7404 mono_class_setup_vtable (klass);
7406 result = klass->vtable [slot];
7407 if (result == NULL) {
7408 /* It is an abstract method */
7409 gpointer iter = NULL;
7410 while ((result = mono_class_get_methods (klass, &iter)))
7411 if (result->slot == slot)
7418 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7419 mono_error_raise_exception (&error);
7423 ICALL_EXPORT MonoString*
7424 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7426 MonoMethod *method = m->method;
7428 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7433 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7435 iter->sig = *(MonoMethodSignature**)argsp;
7437 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7438 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7441 /* FIXME: it's not documented what start is exactly... */
7445 iter->args = argsp + sizeof (gpointer);
7447 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7449 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7452 ICALL_EXPORT MonoTypedRef
7453 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7455 guint32 i, arg_size;
7459 i = iter->sig->sentinelpos + iter->next_arg;
7461 g_assert (i < iter->sig->param_count);
7463 res.type = iter->sig->params [i];
7464 res.klass = mono_class_from_mono_type (res.type);
7465 arg_size = mono_type_stack_size (res.type, &align);
7466 #if defined(__arm__) || defined(__mips__)
7467 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7469 res.value = iter->args;
7470 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7471 /* Values are stored as 8 byte register sized objects, but 'value'
7472 * is dereferenced as a pointer in other routines.
7474 res.value = (char*)res.value + 4;
7476 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7477 if (arg_size <= sizeof (gpointer)) {
7479 int padding = arg_size - mono_type_size (res.type, &dummy);
7480 res.value = (guint8*)res.value + padding;
7483 iter->args = (char*)iter->args + arg_size;
7486 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7491 ICALL_EXPORT MonoTypedRef
7492 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7494 guint32 i, arg_size;
7498 i = iter->sig->sentinelpos + iter->next_arg;
7500 g_assert (i < iter->sig->param_count);
7502 while (i < iter->sig->param_count) {
7503 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7505 res.type = iter->sig->params [i];
7506 res.klass = mono_class_from_mono_type (res.type);
7507 /* FIXME: endianess issue... */
7508 arg_size = mono_type_stack_size (res.type, &align);
7509 #if defined(__arm__) || defined(__mips__)
7510 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7512 res.value = iter->args;
7513 iter->args = (char*)iter->args + arg_size;
7515 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7518 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7526 ICALL_EXPORT MonoType*
7527 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7531 i = iter->sig->sentinelpos + iter->next_arg;
7533 g_assert (i < iter->sig->param_count);
7535 return iter->sig->params [i];
7538 ICALL_EXPORT MonoObject*
7539 mono_TypedReference_ToObject (MonoTypedRef* tref)
7541 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7542 MonoObject** objp = (MonoObject **)tref->value;
7546 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
7549 ICALL_EXPORT MonoTypedRef
7550 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7553 MonoReflectionField *f;
7555 MonoType *ftype = NULL;
7559 memset (&res, 0, sizeof (res));
7562 g_assert (mono_array_length (fields) > 0);
7564 klass = target->vtable->klass;
7566 for (i = 0; i < mono_array_length (fields); ++i) {
7567 f = mono_array_get (fields, MonoReflectionField*, i);
7569 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7572 if (f->field->parent != klass) {
7573 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7577 p = (guint8*)target + f->field->offset;
7579 p += f->field->offset - sizeof (MonoObject);
7580 klass = mono_class_from_mono_type (f->field->type);
7581 ftype = f->field->type;
7585 res.klass = mono_class_from_mono_type (ftype);
7592 prelink_method (MonoMethod *method, MonoError *error)
7594 const char *exc_class, *exc_arg;
7596 mono_error_init (error);
7597 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7599 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7601 mono_error_set_exception_instance (error,
7602 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7605 /* create the wrapper, too? */
7609 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7613 prelink_method (method->method, &error);
7614 mono_error_raise_exception (&error);
7618 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7621 MonoClass *klass = mono_class_from_mono_type (type->type);
7623 gpointer iter = NULL;
7625 mono_class_init_checked (klass, &error);
7626 mono_error_raise_exception (&error);
7628 while ((m = mono_class_get_methods (klass, &iter))) {
7629 prelink_method (m, &error);
7630 mono_error_raise_exception (&error);
7634 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7636 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7637 gint32 const **exponents,
7638 gunichar2 const **digitLowerTable,
7639 gunichar2 const **digitUpperTable,
7640 gint64 const **tenPowersList,
7641 gint32 const **decHexDigits)
7643 *mantissas = Formatter_MantissaBitsTable;
7644 *exponents = Formatter_TensExponentTable;
7645 *digitLowerTable = Formatter_DigitLowerTable;
7646 *digitUpperTable = Formatter_DigitUpperTable;
7647 *tenPowersList = Formatter_TenPowersList;
7648 *decHexDigits = Formatter_DecHexDigits;
7652 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7653 * and avoid useless allocations.
7656 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7658 MonoReflectionType *rt;
7662 mono_error_init (error);
7663 for (i = 0; i < type->num_mods; ++i) {
7664 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7669 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7671 for (i = 0; i < type->num_mods; ++i) {
7672 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7673 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7674 return_val_if_nok (error, NULL);
7676 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7677 return_val_if_nok (error, NULL);
7679 mono_array_setref (res, count, rt);
7686 ICALL_EXPORT MonoArray*
7687 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7690 MonoType *type = param->ClassImpl->type;
7691 MonoClass *member_class = mono_object_class (param->MemberImpl);
7692 MonoMethod *method = NULL;
7695 MonoMethodSignature *sig;
7698 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7699 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7700 method = rmethod->method;
7701 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7702 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7703 if (!(method = prop->property->get))
7704 method = prop->property->set;
7707 char *type_name = mono_type_get_full_name (member_class);
7708 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7709 MonoException *ex = mono_get_exception_not_supported (msg);
7712 mono_set_pending_exception (ex);
7716 image = method->klass->image;
7717 pos = param->PositionImpl;
7718 sig = mono_method_signature (method);
7722 type = sig->params [pos];
7724 res = type_array_from_modifiers (image, type, optional, &error);
7725 mono_error_raise_exception (&error);
7730 get_property_type (MonoProperty *prop)
7732 MonoMethodSignature *sig;
7734 sig = mono_method_signature (prop->get);
7736 } else if (prop->set) {
7737 sig = mono_method_signature (prop->set);
7738 return sig->params [sig->param_count - 1];
7743 ICALL_EXPORT MonoArray*
7744 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7747 MonoType *type = get_property_type (property->property);
7748 MonoImage *image = property->klass->image;
7753 res = type_array_from_modifiers (image, type, optional, &error);
7754 mono_error_raise_exception (&error);
7759 *Construct a MonoType suited to be used to decode a constant blob object.
7761 * @type is the target type which will be constructed
7762 * @blob_type is the blob type, for example, that comes from the constant table
7763 * @real_type is the expected constructed type.
7766 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7768 type->type = blob_type;
7769 type->data.klass = NULL;
7770 if (blob_type == MONO_TYPE_CLASS)
7771 type->data.klass = mono_defaults.object_class;
7772 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7773 /* For enums, we need to use the base type */
7774 type->type = MONO_TYPE_VALUETYPE;
7775 type->data.klass = mono_class_from_mono_type (real_type);
7777 type->data.klass = mono_class_from_mono_type (real_type);
7780 ICALL_EXPORT MonoObject*
7781 property_info_get_default_value (MonoReflectionProperty *property)
7785 MonoProperty *prop = property->property;
7786 MonoType *type = get_property_type (prop);
7787 MonoDomain *domain = mono_object_domain (property);
7788 MonoTypeEnum def_type;
7789 const char *def_value;
7792 mono_class_init (prop->parent);
7794 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7795 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7799 def_value = mono_class_get_property_default_value (prop, &def_type);
7801 mono_type_from_blob_type (&blob_type, def_type, type);
7802 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7804 mono_error_set_pending_exception (&error);
7808 ICALL_EXPORT MonoBoolean
7809 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7812 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7813 MonoCustomAttrInfo *cinfo;
7816 mono_class_init_checked (attr_class, &error);
7817 mono_error_raise_exception (&error);
7819 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7820 if (!is_ok (&error)) {
7821 mono_error_set_pending_exception (&error);
7826 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7828 mono_custom_attrs_free (cinfo);
7832 ICALL_EXPORT MonoArray*
7833 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7835 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7840 mono_class_init_checked (attr_class, &error);
7841 mono_error_raise_exception (&error);
7844 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7845 if (!mono_error_ok (&error)) {
7846 mono_error_set_pending_exception (&error);
7850 if (mono_loader_get_last_error ()) {
7851 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7858 ICALL_EXPORT MonoArray*
7859 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7863 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7864 mono_error_set_pending_exception (&error);
7869 ICALL_EXPORT MonoString*
7870 ves_icall_Mono_Runtime_GetDisplayName (void)
7873 MonoString *display_name;
7875 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7876 display_name = mono_string_new (mono_domain_get (), info);
7878 return display_name;
7881 ICALL_EXPORT MonoString*
7882 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7885 MonoString *message;
7889 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7890 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7893 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7895 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7896 mono_error_raise_exception (&error);
7903 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7906 char *path_str = mono_string_to_utf8 (path);
7908 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7916 ICALL_EXPORT gpointer
7917 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
7919 return GetCurrentProcess ();
7922 ICALL_EXPORT MonoBoolean
7923 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
7925 return GetExitCodeProcess (handle, (guint32*) exitcode);
7928 ICALL_EXPORT MonoBoolean
7929 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
7931 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
7932 return CloseHandle (handle);
7934 return CloseProcess (handle);
7938 ICALL_EXPORT MonoBoolean
7939 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
7941 return TerminateProcess (handle, exitcode);
7945 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
7947 return WaitForInputIdle (handle, milliseconds);
7950 ICALL_EXPORT MonoBoolean
7951 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
7953 return GetProcessWorkingSetSize (handle, min, max);
7956 ICALL_EXPORT MonoBoolean
7957 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
7959 return SetProcessWorkingSetSize (handle, min, max);
7962 ICALL_EXPORT MonoBoolean
7963 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
7965 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
7969 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
7971 return mono_process_current_pid ();
7975 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
7977 return GetPriorityClass (handle);
7980 ICALL_EXPORT MonoBoolean
7981 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
7983 return SetPriorityClass (handle, priorityClass);
7986 #ifndef DISABLE_ICALL_TABLES
7988 #define ICALL_TYPE(id,name,first)
7989 #define ICALL(id,name,func) Icall_ ## id,
7992 #include "metadata/icall-def.h"
7998 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7999 #define ICALL(id,name,func)
8001 #include "metadata/icall-def.h"
8007 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8008 #define ICALL(id,name,func)
8010 guint16 first_icall;
8013 static const IcallTypeDesc
8014 icall_type_descs [] = {
8015 #include "metadata/icall-def.h"
8019 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8022 #define ICALL_TYPE(id,name,first)
8025 #ifdef HAVE_ARRAY_ELEM_INIT
8026 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8027 #define MSGSTRFIELD1(line) str##line
8029 static const struct msgstrtn_t {
8030 #define ICALL(id,name,func)
8032 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8033 #include "metadata/icall-def.h"
8035 } icall_type_names_str = {
8036 #define ICALL_TYPE(id,name,first) (name),
8037 #include "metadata/icall-def.h"
8040 static const guint16 icall_type_names_idx [] = {
8041 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8042 #include "metadata/icall-def.h"
8045 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8047 static const struct msgstr_t {
8049 #define ICALL_TYPE(id,name,first)
8050 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8051 #include "metadata/icall-def.h"
8053 } icall_names_str = {
8054 #define ICALL(id,name,func) (name),
8055 #include "metadata/icall-def.h"
8058 static const guint16 icall_names_idx [] = {
8059 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8060 #include "metadata/icall-def.h"
8063 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8069 #define ICALL_TYPE(id,name,first) name,
8070 #define ICALL(id,name,func)
8071 static const char* const
8072 icall_type_names [] = {
8073 #include "metadata/icall-def.h"
8077 #define icall_type_name_get(id) (icall_type_names [(id)])
8081 #define ICALL_TYPE(id,name,first)
8082 #define ICALL(id,name,func) name,
8083 static const char* const
8085 #include "metadata/icall-def.h"
8088 #define icall_name_get(id) icall_names [(id)]
8090 #endif /* !HAVE_ARRAY_ELEM_INIT */
8094 #define ICALL_TYPE(id,name,first)
8095 #define ICALL(id,name,func) func,
8096 static const gconstpointer
8097 icall_functions [] = {
8098 #include "metadata/icall-def.h"
8102 #ifdef ENABLE_ICALL_SYMBOL_MAP
8105 #define ICALL_TYPE(id,name,first)
8106 #define ICALL(id,name,func) #func,
8107 static const gconstpointer
8108 icall_symbols [] = {
8109 #include "metadata/icall-def.h"
8114 #endif /* DISABLE_ICALL_TABLES */
8116 static mono_mutex_t icall_mutex;
8117 static GHashTable *icall_hash = NULL;
8118 static GHashTable *jit_icall_hash_name = NULL;
8119 static GHashTable *jit_icall_hash_addr = NULL;
8122 mono_icall_init (void)
8124 #ifndef DISABLE_ICALL_TABLES
8127 /* check that tables are sorted: disable in release */
8130 const char *prev_class = NULL;
8131 const char *prev_method;
8133 for (i = 0; i < Icall_type_num; ++i) {
8134 const IcallTypeDesc *desc;
8137 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8138 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8139 prev_class = icall_type_name_get (i);
8140 desc = &icall_type_descs [i];
8141 num_icalls = icall_desc_num_icalls (desc);
8142 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8143 for (j = 0; j < num_icalls; ++j) {
8144 const char *methodn = icall_name_get (desc->first_icall + j);
8145 if (prev_method && strcmp (prev_method, methodn) >= 0)
8146 g_print ("method %s should come before method %s\n", methodn, prev_method);
8147 prev_method = methodn;
8153 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8154 mono_os_mutex_init (&icall_mutex);
8158 mono_icall_lock (void)
8160 mono_locks_os_acquire (&icall_mutex, IcallLock);
8164 mono_icall_unlock (void)
8166 mono_locks_os_release (&icall_mutex, IcallLock);
8170 mono_icall_cleanup (void)
8172 g_hash_table_destroy (icall_hash);
8173 g_hash_table_destroy (jit_icall_hash_name);
8174 g_hash_table_destroy (jit_icall_hash_addr);
8175 mono_os_mutex_destroy (&icall_mutex);
8179 * mono_add_internal_call:
8180 * @name: method specification to surface to the managed world
8181 * @method: pointer to a C method to invoke when the method is called
8183 * This method surfaces the C function pointed by @method as a method
8184 * that has been surfaced in managed code with the method specified in
8185 * @name as an internal call.
8187 * Internal calls are surfaced to all app domains loaded and they are
8188 * accessibly by a type with the specified name.
8190 * You must provide a fully qualified type name, that is namespaces
8191 * and type name, followed by a colon and the method name, with an
8192 * optional signature to bind.
8194 * For example, the following are all valid declarations:
8196 * "MyApp.Services.ScriptService:Accelerate"
8197 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8199 * You use method parameters in cases where there might be more than
8200 * one surface method to managed code. That way you can register different
8201 * internal calls for different method overloads.
8203 * The internal calls are invoked with no marshalling. This means that .NET
8204 * types like System.String are exposed as `MonoString *` parameters. This is
8205 * different than the way that strings are surfaced in P/Invoke.
8207 * For more information on how the parameters are marshalled, see the
8208 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8211 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8212 * reference for more information on the format of method descriptions.
8215 mono_add_internal_call (const char *name, gconstpointer method)
8219 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8221 mono_icall_unlock ();
8224 #ifndef DISABLE_ICALL_TABLES
8226 #ifdef HAVE_ARRAY_ELEM_INIT
8228 compare_method_imap (const void *key, const void *elem)
8230 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8231 return strcmp (key, method_name);
8235 find_method_icall (const IcallTypeDesc *imap, const char *name)
8237 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);
8240 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8244 compare_class_imap (const void *key, const void *elem)
8246 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8247 return strcmp (key, class_name);
8250 static const IcallTypeDesc*
8251 find_class_icalls (const char *name)
8253 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);
8256 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8259 #else /* HAVE_ARRAY_ELEM_INIT */
8262 compare_method_imap (const void *key, const void *elem)
8264 const char** method_name = (const char**)elem;
8265 return strcmp (key, *method_name);
8269 find_method_icall (const IcallTypeDesc *imap, const char *name)
8271 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8274 return (gpointer)icall_functions [(nameslot - icall_names)];
8278 compare_class_imap (const void *key, const void *elem)
8280 const char** class_name = (const char**)elem;
8281 return strcmp (key, *class_name);
8284 static const IcallTypeDesc*
8285 find_class_icalls (const char *name)
8287 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8290 return &icall_type_descs [nameslot - icall_type_names];
8293 #endif /* HAVE_ARRAY_ELEM_INIT */
8295 #endif /* DISABLE_ICALL_TABLES */
8298 * we should probably export this as an helper (handle nested types).
8299 * Returns the number of chars written in buf.
8302 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8304 int nspacelen, cnamelen;
8305 nspacelen = strlen (klass->name_space);
8306 cnamelen = strlen (klass->name);
8307 if (nspacelen + cnamelen + 2 > bufsize)
8310 memcpy (buf, klass->name_space, nspacelen);
8311 buf [nspacelen ++] = '.';
8313 memcpy (buf + nspacelen, klass->name, cnamelen);
8314 buf [nspacelen + cnamelen] = 0;
8315 return nspacelen + cnamelen;
8318 #ifdef DISABLE_ICALL_TABLES
8320 no_icall_table (void)
8322 g_assert_not_reached ();
8327 mono_lookup_internal_call (MonoMethod *method)
8332 int typelen = 0, mlen, siglen;
8334 #ifndef DISABLE_ICALL_TABLES
8335 const IcallTypeDesc *imap = NULL;
8338 g_assert (method != NULL);
8340 if (method->is_inflated)
8341 method = ((MonoMethodInflated *) method)->declaring;
8343 if (method->klass->nested_in) {
8344 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8348 mname [pos++] = '/';
8351 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8357 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8362 #ifndef DISABLE_ICALL_TABLES
8363 imap = find_class_icalls (mname);
8366 mname [typelen] = ':';
8367 mname [typelen + 1] = ':';
8369 mlen = strlen (method->name);
8370 memcpy (mname + typelen + 2, method->name, mlen);
8371 sigstart = mname + typelen + 2 + mlen;
8374 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8375 siglen = strlen (tmpsig);
8376 if (typelen + mlen + siglen + 6 > sizeof (mname))
8379 memcpy (sigstart + 1, tmpsig, siglen);
8380 sigstart [siglen + 1] = ')';
8381 sigstart [siglen + 2] = 0;
8386 res = g_hash_table_lookup (icall_hash, mname);
8388 mono_icall_unlock ();;
8391 /* try without signature */
8393 res = g_hash_table_lookup (icall_hash, mname);
8395 mono_icall_unlock ();
8399 #ifdef DISABLE_ICALL_TABLES
8400 mono_icall_unlock ();
8401 /* Fail only when the result is actually used */
8402 /* mono_marshal_get_native_wrapper () depends on this */
8403 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8404 return ves_icall_System_String_ctor_RedirectToCreateString;
8406 return no_icall_table;
8408 /* it wasn't found in the static call tables */
8410 mono_icall_unlock ();
8413 res = find_method_icall (imap, sigstart - mlen);
8415 mono_icall_unlock ();
8418 /* try _with_ signature */
8420 res = find_method_icall (imap, sigstart - mlen);
8422 mono_icall_unlock ();
8426 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8427 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8428 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8429 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8430 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");
8431 g_print ("If you see other errors or faults after this message they are probably related\n");
8432 g_print ("and you need to fix your mono install first.\n");
8434 mono_icall_unlock ();
8440 #ifdef ENABLE_ICALL_SYMBOL_MAP
8442 func_cmp (gconstpointer key, gconstpointer p)
8444 return (gsize)key - (gsize)*(gsize*)p;
8449 * mono_lookup_icall_symbol:
8451 * Given the icall METHOD, returns its C symbol.
8454 mono_lookup_icall_symbol (MonoMethod *m)
8456 #ifdef DISABLE_ICALL_TABLES
8457 g_assert_not_reached ();
8460 #ifdef ENABLE_ICALL_SYMBOL_MAP
8464 static gconstpointer *functions_sorted;
8465 static const char**symbols_sorted;
8466 static gboolean inited;
8471 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8472 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8473 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8474 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8475 /* Bubble sort the two arrays */
8479 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8480 if (functions_sorted [i] > functions_sorted [i + 1]) {
8483 tmp = functions_sorted [i];
8484 functions_sorted [i] = functions_sorted [i + 1];
8485 functions_sorted [i + 1] = tmp;
8486 tmp = symbols_sorted [i];
8487 symbols_sorted [i] = symbols_sorted [i + 1];
8488 symbols_sorted [i + 1] = tmp;
8495 func = mono_lookup_internal_call (m);
8498 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8502 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8504 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8505 g_assert_not_reached ();
8512 type_from_typename (char *type_name)
8514 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8516 if (!strcmp (type_name, "int"))
8517 klass = mono_defaults.int_class;
8518 else if (!strcmp (type_name, "ptr"))
8519 klass = mono_defaults.int_class;
8520 else if (!strcmp (type_name, "void"))
8521 klass = mono_defaults.void_class;
8522 else if (!strcmp (type_name, "int32"))
8523 klass = mono_defaults.int32_class;
8524 else if (!strcmp (type_name, "uint32"))
8525 klass = mono_defaults.uint32_class;
8526 else if (!strcmp (type_name, "int8"))
8527 klass = mono_defaults.sbyte_class;
8528 else if (!strcmp (type_name, "uint8"))
8529 klass = mono_defaults.byte_class;
8530 else if (!strcmp (type_name, "int16"))
8531 klass = mono_defaults.int16_class;
8532 else if (!strcmp (type_name, "uint16"))
8533 klass = mono_defaults.uint16_class;
8534 else if (!strcmp (type_name, "long"))
8535 klass = mono_defaults.int64_class;
8536 else if (!strcmp (type_name, "ulong"))
8537 klass = mono_defaults.uint64_class;
8538 else if (!strcmp (type_name, "float"))
8539 klass = mono_defaults.single_class;
8540 else if (!strcmp (type_name, "double"))
8541 klass = mono_defaults.double_class;
8542 else if (!strcmp (type_name, "object"))
8543 klass = mono_defaults.object_class;
8544 else if (!strcmp (type_name, "obj"))
8545 klass = mono_defaults.object_class;
8546 else if (!strcmp (type_name, "string"))
8547 klass = mono_defaults.string_class;
8548 else if (!strcmp (type_name, "bool"))
8549 klass = mono_defaults.boolean_class;
8550 else if (!strcmp (type_name, "boolean"))
8551 klass = mono_defaults.boolean_class;
8553 g_error ("%s", type_name);
8554 g_assert_not_reached ();
8556 return &klass->byval_arg;
8560 * LOCKING: Take the corlib image lock.
8562 MonoMethodSignature*
8563 mono_create_icall_signature (const char *sigstr)
8568 MonoMethodSignature *res, *res2;
8569 MonoImage *corlib = mono_defaults.corlib;
8571 mono_image_lock (corlib);
8572 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8573 mono_image_unlock (corlib);
8578 parts = g_strsplit (sigstr, " ", 256);
8587 res = mono_metadata_signature_alloc (corlib, len - 1);
8592 * Under windows, the default pinvoke calling convention is STDCALL but
8595 res->call_convention = MONO_CALL_C;
8598 res->ret = type_from_typename (parts [0]);
8599 for (i = 1; i < len; ++i) {
8600 res->params [i - 1] = type_from_typename (parts [i]);
8605 mono_image_lock (corlib);
8606 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8608 res = res2; /*Value is allocated in the image pool*/
8610 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8611 mono_image_unlock (corlib);
8617 mono_find_jit_icall_by_name (const char *name)
8619 MonoJitICallInfo *info;
8620 g_assert (jit_icall_hash_name);
8623 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8624 mono_icall_unlock ();
8629 mono_find_jit_icall_by_addr (gconstpointer addr)
8631 MonoJitICallInfo *info;
8632 g_assert (jit_icall_hash_addr);
8635 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8636 mono_icall_unlock ();
8642 * mono_get_jit_icall_info:
8644 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8645 * caller should access it while holding the icall lock.
8648 mono_get_jit_icall_info (void)
8650 return jit_icall_hash_name;
8654 * mono_lookup_jit_icall_symbol:
8656 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8659 mono_lookup_jit_icall_symbol (const char *name)
8661 MonoJitICallInfo *info;
8662 const char *res = NULL;
8665 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8667 res = info->c_symbol;
8668 mono_icall_unlock ();
8673 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8676 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8677 mono_icall_unlock ();
8681 * 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
8682 * icalls without wrappers in some cases.
8685 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8687 MonoJitICallInfo *info;
8694 if (!jit_icall_hash_name) {
8695 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8696 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8699 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8700 g_warning ("jit icall already defined \"%s\"\n", name);
8701 g_assert_not_reached ();
8704 info = g_new0 (MonoJitICallInfo, 1);
8709 info->c_symbol = c_symbol;
8710 info->no_raise = no_raise;
8713 info->wrapper = func;
8715 info->wrapper = NULL;
8718 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8719 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8721 mono_icall_unlock ();
8726 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8728 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);