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)
990 MonoObject **values = NULL;
993 gint32 result = (int)(gsize)mono_defaults.int32_class;
994 MonoClassField* field;
997 klass = mono_object_class (this_obj);
999 if (mono_class_num_fields (klass) == 0)
1003 * Compute the starting value of the hashcode for fields of primitive
1004 * types, and return the remaining fields in an array to the managed side.
1005 * This way, we can avoid costly reflection operations in managed code.
1008 while ((field = mono_class_get_fields (klass, &iter))) {
1009 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1011 if (mono_field_is_deleted (field))
1013 /* FIXME: Add more types */
1014 switch (field->type->type) {
1016 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1018 case MONO_TYPE_STRING: {
1020 s = *(MonoString**)((guint8*)this_obj + field->offset);
1022 result ^= mono_string_hash (s);
1027 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1028 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1029 if (!is_ok (&error)) {
1030 mono_error_set_pending_exception (&error);
1033 values [count++] = o;
1039 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1040 for (i = 0; i < count; ++i)
1041 mono_array_setref (*fields, i, values [i]);
1048 ICALL_EXPORT MonoBoolean
1049 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1053 MonoObject **values = NULL;
1055 MonoClassField* field;
1059 MONO_CHECK_ARG_NULL (that, FALSE);
1061 if (this_obj->vtable != that->vtable)
1064 klass = mono_object_class (this_obj);
1066 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1067 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1070 * Do the comparison for fields of primitive type and return a result if
1071 * possible. Otherwise, return the remaining fields in an array to the
1072 * managed side. This way, we can avoid costly reflection operations in
1077 while ((field = mono_class_get_fields (klass, &iter))) {
1078 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1080 if (mono_field_is_deleted (field))
1082 /* FIXME: Add more types */
1083 switch (field->type->type) {
1086 case MONO_TYPE_BOOLEAN:
1087 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1092 case MONO_TYPE_CHAR:
1093 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1098 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1103 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1107 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1111 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1116 case MONO_TYPE_STRING: {
1117 MonoString *s1, *s2;
1118 guint32 s1len, s2len;
1119 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1120 s2 = *(MonoString**)((guint8*)that + field->offset);
1123 if ((s1 == NULL) || (s2 == NULL))
1125 s1len = mono_string_length (s1);
1126 s2len = mono_string_length (s2);
1130 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1136 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1137 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1138 if (!is_ok (&error)) {
1139 mono_error_set_pending_exception (&error);
1142 values [count++] = o;
1143 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1144 if (!is_ok (&error)) {
1145 mono_error_set_pending_exception (&error);
1148 values [count++] = o;
1151 if (klass->enumtype)
1152 /* enums only have one non-static field */
1158 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1159 for (i = 0; i < count; ++i)
1160 mono_array_setref_fast (*fields, i, values [i]);
1167 ICALL_EXPORT MonoReflectionType *
1168 ves_icall_System_Object_GetType (MonoObject *obj)
1171 MonoReflectionType *ret;
1172 #ifndef DISABLE_REMOTING
1173 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1174 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1177 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1179 mono_error_raise_exception (&error);
1185 ves_icall_MonoType_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1187 mtype->type = &obj->vtable->klass->byval_arg;
1188 g_assert (mtype->type->type);
1192 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1194 MONO_CHECK_ARG_NULL (obj, 0);
1197 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1198 mono_error_raise_exception (&error);
1203 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1204 MonoReflectionMethod *method,
1205 MonoArray *opt_param_types)
1207 MONO_CHECK_ARG_NULL (method, 0);
1210 gint32 result = mono_image_create_method_token (
1211 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1212 mono_error_raise_exception (&error);
1217 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1220 mono_image_create_pefile (mb, file, &error);
1221 mono_error_raise_exception (&error);
1225 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1228 if (!mono_image_build_metadata (mb, &error))
1229 mono_error_raise_exception (&error);
1233 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1235 mono_image_register_token (mb->dynamic_image, token, obj);
1238 ICALL_EXPORT MonoObject*
1239 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1243 mono_loader_lock ();
1244 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1245 mono_loader_unlock ();
1250 ICALL_EXPORT MonoReflectionModule*
1251 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1254 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1255 mono_error_set_pending_exception (&error);
1260 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1262 MonoMethod **dest = (MonoMethod **)data;
1264 /* skip unmanaged frames */
1280 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1282 MonoMethod **dest = (MonoMethod **)data;
1284 /* skip unmanaged frames */
1289 if (!strcmp (m->klass->name_space, "System.Reflection"))
1298 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1300 MonoMethod **dest = (MonoMethod **)data;
1302 /* skip unmanaged frames */
1306 if (m->wrapper_type != MONO_WRAPPER_NONE)
1309 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1323 static MonoReflectionType *
1324 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1326 MonoMethod *m, *dest;
1328 MonoType *type = NULL;
1329 MonoAssembly *assembly = NULL;
1330 gboolean type_resolve = FALSE;
1332 mono_error_init (error);
1335 * We must compute the calling assembly as type loading must happen under a metadata context.
1336 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1337 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1339 m = mono_method_get_last_managed ();
1342 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1347 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1348 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1349 * to crash. This only seems to happen in some strange remoting
1350 * scenarios and I was unable to figure out what's happening there.
1351 * Dec 10, 2005 - Martin.
1355 assembly = dest->klass->image->assembly;
1356 type_resolve = TRUE;
1358 g_warning (G_STRLOC);
1361 if (info->assembly.name)
1362 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1366 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1367 type = mono_reflection_get_type_checked (assembly->image, info, ignoreCase, &type_resolve, error);
1368 return_val_if_nok (error, NULL);
1371 if (!info->assembly.name && !type) {
1373 type = mono_reflection_get_type_checked (NULL, info, ignoreCase, &type_resolve, error);
1374 return_val_if_nok (error, NULL);
1376 if (assembly && !type && type_resolve) {
1377 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1378 type = mono_reflection_get_type_checked (assembly->image, info, ignoreCase, &type_resolve, error);
1379 return_val_if_nok (error, NULL);
1385 return mono_type_get_object_checked (mono_domain_get (), type, error);
1388 ICALL_EXPORT MonoReflectionType*
1389 ves_icall_System_Type_internal_from_name (MonoString *name,
1390 MonoBoolean throwOnError,
1391 MonoBoolean ignoreCase)
1394 char *str = mono_string_to_utf8 (name);
1395 MonoTypeNameParse info;
1396 MonoReflectionType *type;
1399 parsedOk = mono_reflection_parse_type (str, &info);
1401 /* mono_reflection_parse_type() mangles the string */
1403 mono_reflection_free_type_info (&info);
1406 mono_set_pending_exception (mono_get_exception_argument("typeName", "failed parse"));
1411 type = type_from_parsed_name (&info, ignoreCase, &error);
1413 mono_reflection_free_type_info (&info);
1416 if (!mono_error_ok (&error)) {
1418 mono_error_set_pending_exception (&error);
1420 mono_error_cleanup (&error);
1425 MonoException *e = NULL;
1428 e = mono_get_exception_type_load (name, NULL);
1430 mono_loader_clear_error ();
1432 mono_set_pending_exception (e);
1441 ICALL_EXPORT MonoReflectionType*
1442 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1445 MonoReflectionType *ret;
1446 MonoDomain *domain = mono_domain_get ();
1448 ret = mono_type_get_object_checked (domain, handle, &error);
1449 mono_error_raise_exception (&error);
1454 /* System.TypeCode */
1473 TYPECODE_STRING = 18
1476 ICALL_EXPORT guint32
1477 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1479 int t = type->type->type;
1481 if (type->type->byref)
1482 return TYPECODE_OBJECT;
1486 case MONO_TYPE_VOID:
1487 return TYPECODE_OBJECT;
1488 case MONO_TYPE_BOOLEAN:
1489 return TYPECODE_BOOLEAN;
1491 return TYPECODE_BYTE;
1493 return TYPECODE_SBYTE;
1495 return TYPECODE_UINT16;
1497 return TYPECODE_INT16;
1498 case MONO_TYPE_CHAR:
1499 return TYPECODE_CHAR;
1503 return TYPECODE_OBJECT;
1505 return TYPECODE_UINT32;
1507 return TYPECODE_INT32;
1509 return TYPECODE_UINT64;
1511 return TYPECODE_INT64;
1513 return TYPECODE_SINGLE;
1515 return TYPECODE_DOUBLE;
1516 case MONO_TYPE_VALUETYPE: {
1517 MonoClass *klass = type->type->data.klass;
1519 if (klass->enumtype) {
1520 t = mono_class_enum_basetype (klass)->type;
1522 } else if (mono_is_corlib_image (klass->image)) {
1523 if (strcmp (klass->name_space, "System") == 0) {
1524 if (strcmp (klass->name, "Decimal") == 0)
1525 return TYPECODE_DECIMAL;
1526 else if (strcmp (klass->name, "DateTime") == 0)
1527 return TYPECODE_DATETIME;
1530 return TYPECODE_OBJECT;
1532 case MONO_TYPE_STRING:
1533 return TYPECODE_STRING;
1534 case MONO_TYPE_SZARRAY:
1535 case MONO_TYPE_ARRAY:
1536 case MONO_TYPE_OBJECT:
1538 case MONO_TYPE_MVAR:
1539 case MONO_TYPE_TYPEDBYREF:
1540 return TYPECODE_OBJECT;
1541 case MONO_TYPE_CLASS:
1543 MonoClass *klass = type->type->data.klass;
1544 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1545 if (strcmp (klass->name, "DBNull") == 0)
1546 return TYPECODE_DBNULL;
1549 return TYPECODE_OBJECT;
1550 case MONO_TYPE_GENERICINST:
1551 return TYPECODE_OBJECT;
1553 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1559 mono_type_is_primitive (MonoType *type)
1561 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1562 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1566 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1568 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1569 return mono_class_enum_basetype (type->data.klass);
1570 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1571 return mono_class_enum_basetype (type->data.generic_class->container_class);
1575 ICALL_EXPORT guint32
1576 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1581 g_assert (type != NULL);
1583 klass = mono_class_from_mono_type (type->type);
1584 klassc = mono_class_from_mono_type (c->type);
1586 if (type->type->byref ^ c->type->byref)
1589 if (type->type->byref) {
1590 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1591 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1593 klass = mono_class_from_mono_type (t);
1594 klassc = mono_class_from_mono_type (ot);
1596 if (mono_type_is_primitive (t)) {
1597 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1598 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1599 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1600 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1601 return t->type == ot->type;
1603 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1606 if (klass->valuetype)
1607 return klass == klassc;
1608 return klass->valuetype == klassc->valuetype;
1611 return mono_class_is_assignable_from (klass, klassc);
1614 ICALL_EXPORT guint32
1615 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1618 MonoClass *klass = mono_class_from_mono_type (type->type);
1619 mono_class_init_checked (klass, &error);
1620 mono_error_raise_exception (&error);
1621 return mono_object_isinst (obj, klass) != NULL;
1624 ICALL_EXPORT guint32
1625 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1627 MonoClass *klass = mono_class_from_mono_type (type->type);
1628 return klass->flags;
1631 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1632 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1635 MonoClass *klass = field->field->parent;
1636 MonoMarshalType *info;
1640 if (klass->generic_container ||
1641 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1644 ftype = mono_field_get_type (field->field);
1645 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1648 info = mono_marshal_load_type_info (klass);
1650 for (i = 0; i < info->num_fields; ++i) {
1651 if (info->fields [i].field == field->field) {
1652 if (!info->fields [i].mspec)
1655 MonoReflectionMarshalAsAttribute* obj;
1656 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1657 if (!mono_error_ok (&error))
1658 mono_error_set_pending_exception (&error);
1667 ICALL_EXPORT MonoReflectionField*
1668 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1671 gboolean found = FALSE;
1678 klass = handle->parent;
1680 klass = mono_class_from_mono_type (type);
1682 /* Check that the field belongs to the class */
1683 for (k = klass; k; k = k->parent) {
1684 if (k == handle->parent) {
1691 /* The managed code will throw the exception */
1695 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1696 mono_error_raise_exception (&error);
1700 ICALL_EXPORT MonoArray*
1701 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1704 MonoType *type = mono_field_get_type_checked (field->field, &error);
1707 if (!mono_error_ok (&error)) {
1708 mono_error_set_pending_exception (&error);
1712 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1713 mono_error_raise_exception (&error);
1718 vell_icall_get_method_attributes (MonoMethod *method)
1720 return method->flags;
1724 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1727 MonoReflectionType *rt;
1728 MonoDomain *domain = mono_domain_get ();
1729 MonoMethodSignature* sig;
1731 sig = mono_method_signature_checked (method, &error);
1732 if (!mono_error_ok (&error)) {
1733 mono_error_set_pending_exception (&error);
1737 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1738 if (!mono_error_ok (&error)) {
1739 mono_error_set_pending_exception (&error);
1743 MONO_STRUCT_SETREF (info, parent, rt);
1745 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1746 if (!mono_error_ok (&error)) {
1747 mono_error_set_pending_exception (&error);
1751 MONO_STRUCT_SETREF (info, ret, rt);
1753 info->attrs = method->flags;
1754 info->implattrs = method->iflags;
1755 if (sig->call_convention == MONO_CALL_DEFAULT)
1756 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1758 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1763 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1766 ICALL_EXPORT MonoArray*
1767 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1770 MonoDomain *domain = mono_domain_get ();
1772 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1773 mono_error_set_pending_exception (&error);
1777 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1778 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1781 MonoDomain *domain = mono_domain_get ();
1782 MonoReflectionMarshalAsAttribute* res = NULL;
1783 MonoMarshalSpec **mspecs;
1786 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1787 mono_method_get_marshal_info (method, mspecs);
1790 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1791 if (!mono_error_ok (&error)) {
1792 mono_error_set_pending_exception (&error);
1797 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1799 mono_metadata_free_marshal_spec (mspecs [i]);
1806 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1808 MonoClass *parent = field->field->parent;
1809 if (!parent->size_inited)
1810 mono_class_init (parent);
1811 mono_class_setup_fields_locking (parent);
1813 return field->field->offset - sizeof (MonoObject);
1816 ICALL_EXPORT MonoReflectionType*
1817 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1820 MonoReflectionType *ret;
1823 parent = declaring? field->field->parent: field->klass;
1825 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1826 mono_error_raise_exception (&error);
1832 ICALL_EXPORT MonoObject *
1833 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1836 MonoClass *fklass = field->klass;
1837 MonoClassField *cf = field->field;
1838 MonoDomain *domain = mono_object_domain (field);
1840 if (fklass->image->assembly->ref_only) {
1841 mono_set_pending_exception (mono_get_exception_invalid_operation (
1842 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1846 if (mono_security_core_clr_enabled ())
1847 mono_security_core_clr_ensure_reflection_access_field (cf);
1849 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1850 mono_error_set_pending_exception (&error);
1855 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1858 MonoClassField *cf = field->field;
1862 if (field->klass->image->assembly->ref_only) {
1863 mono_set_pending_exception (mono_get_exception_invalid_operation (
1864 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1868 if (mono_security_core_clr_enabled ())
1869 mono_security_core_clr_ensure_reflection_access_field (cf);
1871 type = mono_field_get_type_checked (cf, &error);
1872 if (!mono_error_ok (&error)) {
1873 mono_error_set_pending_exception (&error);
1877 v = (gchar *) value;
1879 switch (type->type) {
1882 case MONO_TYPE_BOOLEAN:
1885 case MONO_TYPE_CHAR:
1894 case MONO_TYPE_VALUETYPE:
1897 v += sizeof (MonoObject);
1899 case MONO_TYPE_STRING:
1900 case MONO_TYPE_OBJECT:
1901 case MONO_TYPE_CLASS:
1902 case MONO_TYPE_ARRAY:
1903 case MONO_TYPE_SZARRAY:
1906 case MONO_TYPE_GENERICINST: {
1907 MonoGenericClass *gclass = type->data.generic_class;
1908 g_assert (!gclass->context.class_inst->is_open);
1910 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1911 MonoClass *nklass = mono_class_from_mono_type (type);
1912 MonoObject *nullable;
1915 * Convert the boxed vtype into a Nullable structure.
1916 * This is complicated by the fact that Nullables have
1917 * a variable structure.
1919 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1920 if (!mono_error_ok (&error)) {
1921 mono_error_set_pending_exception (&error);
1925 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1927 v = (gchar *)mono_object_unbox (nullable);
1930 if (gclass->container_class->valuetype && (v != NULL))
1931 v += sizeof (MonoObject);
1935 g_error ("type 0x%x not handled in "
1936 "ves_icall_FieldInfo_SetValueInternal", type->type);
1941 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1942 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
1943 if (!is_ok (&error)) {
1944 mono_error_set_pending_exception (&error);
1947 if (!vtable->initialized) {
1948 if (!mono_runtime_class_init_full (vtable, &error)) {
1949 mono_error_set_pending_exception (&error);
1953 mono_field_static_set_value (vtable, cf, v);
1955 mono_field_set_value (obj, cf, v);
1960 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1969 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1970 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1974 if (MONO_TYPE_IS_REFERENCE (f->type))
1975 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1977 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1980 ICALL_EXPORT MonoObject *
1981 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1983 MonoObject *o = NULL;
1984 MonoClassField *field = rfield->field;
1986 MonoDomain *domain = mono_object_domain (rfield);
1988 MonoTypeEnum def_type;
1989 const char *def_value;
1993 mono_class_init (field->parent);
1995 t = mono_field_get_type_checked (field, &error);
1996 if (!mono_error_ok (&error)) {
1997 mono_error_set_pending_exception (&error);
2001 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2002 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2006 if (image_is_dynamic (field->parent->image)) {
2007 MonoClass *klass = field->parent;
2008 int fidx = field - klass->fields;
2010 g_assert (fidx >= 0 && fidx < klass->field.count);
2011 g_assert (klass->ext);
2012 g_assert (klass->ext->field_def_values);
2013 def_type = klass->ext->field_def_values [fidx].def_type;
2014 def_value = klass->ext->field_def_values [fidx].data;
2015 if (def_type == MONO_TYPE_END) {
2016 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2020 def_value = mono_class_get_field_default_value (field, &def_type);
2021 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2023 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2028 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2032 case MONO_TYPE_BOOLEAN:
2035 case MONO_TYPE_CHAR:
2043 case MONO_TYPE_R8: {
2046 /* boxed value type */
2047 t = g_new0 (MonoType, 1);
2049 klass = mono_class_from_mono_type (t);
2051 o = mono_object_new_checked (domain, klass, &error);
2052 if (!mono_error_ok (&error)) {
2053 mono_error_set_pending_exception (&error);
2056 v = ((gchar *) o) + sizeof (MonoObject);
2057 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2060 case MONO_TYPE_STRING:
2061 case MONO_TYPE_CLASS:
2062 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2065 g_assert_not_reached ();
2071 ICALL_EXPORT MonoReflectionType*
2072 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2075 MonoReflectionType *ret;
2078 type = mono_field_get_type_checked (ref_field->field, &error);
2079 if (!mono_error_ok (&error)) {
2080 mono_error_set_pending_exception (&error);
2084 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2085 if (!mono_error_ok (&error)) {
2086 mono_error_set_pending_exception (&error);
2093 /* From MonoProperty.cs */
2095 PInfo_Attributes = 1,
2096 PInfo_GetMethod = 1 << 1,
2097 PInfo_SetMethod = 1 << 2,
2098 PInfo_ReflectedType = 1 << 3,
2099 PInfo_DeclaringType = 1 << 4,
2104 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2107 MonoReflectionType *rt;
2108 MonoReflectionMethod *rm;
2109 MonoDomain *domain = mono_object_domain (property);
2110 const MonoProperty *pproperty = property->property;
2112 if ((req_info & PInfo_ReflectedType) != 0) {
2113 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2114 mono_error_raise_exception (&error);
2116 MONO_STRUCT_SETREF (info, parent, rt);
2118 if ((req_info & PInfo_DeclaringType) != 0) {
2119 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2120 mono_error_raise_exception (&error);
2122 MONO_STRUCT_SETREF (info, declaring_type, rt);
2125 if ((req_info & PInfo_Name) != 0)
2126 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2128 if ((req_info & PInfo_Attributes) != 0)
2129 info->attrs = pproperty->attrs;
2131 if ((req_info & PInfo_GetMethod) != 0) {
2132 if (pproperty->get &&
2133 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2134 pproperty->get->klass == property->klass)) {
2135 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2136 mono_error_raise_exception (&error);
2141 MONO_STRUCT_SETREF (info, get, rm);
2143 if ((req_info & PInfo_SetMethod) != 0) {
2144 if (pproperty->set &&
2145 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2146 pproperty->set->klass == property->klass)) {
2147 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2148 mono_error_raise_exception (&error);
2153 MONO_STRUCT_SETREF (info, set, rm);
2156 * There may be other methods defined for properties, though, it seems they are not exposed
2157 * in the reflection API
2162 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2165 MonoReflectionType *rt;
2166 MonoReflectionMethod *rm;
2167 MonoDomain *domain = mono_object_domain (event);
2169 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2170 mono_error_raise_exception (&error);
2172 MONO_STRUCT_SETREF (info, reflected_type, rt);
2174 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2175 mono_error_raise_exception (&error);
2177 MONO_STRUCT_SETREF (info, declaring_type, rt);
2179 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2180 info->attrs = event->event->attrs;
2182 if (event->event->add) {
2183 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2184 mono_error_raise_exception (&error);
2189 MONO_STRUCT_SETREF (info, add_method, rm);
2191 if (event->event->remove) {
2192 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2193 mono_error_raise_exception (&error);
2198 MONO_STRUCT_SETREF (info, remove_method, rm);
2200 if (event->event->raise) {
2201 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2202 mono_error_raise_exception (&error);
2207 MONO_STRUCT_SETREF (info, raise_method, rm);
2209 #ifndef MONO_SMALL_CONFIG
2210 if (event->event->other) {
2212 while (event->event->other [n])
2214 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2216 for (i = 0; i < n; i++) {
2217 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2218 mono_error_raise_exception (&error);
2219 mono_array_setref (info->other_methods, i, rm);
2226 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2231 mono_class_setup_interfaces (klass, error);
2232 if (!mono_error_ok (error))
2235 for (i = 0; i < klass->interface_count; i++) {
2236 ic = klass->interfaces [i];
2237 g_hash_table_insert (ifaces, ic, ic);
2239 collect_interfaces (ic, ifaces, error);
2240 if (!mono_error_ok (error))
2246 MonoArray *iface_array;
2247 MonoGenericContext *context;
2251 } FillIfaceArrayData;
2254 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2256 MonoReflectionType *rt;
2257 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2258 MonoClass *ic = (MonoClass *)key;
2259 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2261 if (!mono_error_ok (data->error))
2264 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2265 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2266 if (!mono_error_ok (data->error))
2270 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2271 if (!mono_error_ok (data->error))
2274 mono_array_setref (data->iface_array, data->next_idx++, rt);
2277 mono_metadata_free_type (inflated);
2281 get_interfaces_hash (gconstpointer v1)
2283 MonoClass *k = (MonoClass*)v1;
2285 return k->type_token;
2288 ICALL_EXPORT MonoArray*
2289 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2292 MonoClass *klass = mono_class_from_mono_type (type->type);
2294 FillIfaceArrayData data = { 0 };
2297 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2299 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2300 data.context = mono_class_get_context (klass);
2301 klass = klass->generic_class->container_class;
2304 for (parent = klass; parent; parent = parent->parent) {
2305 mono_class_setup_interfaces (parent, &error);
2306 if (!mono_error_ok (&error))
2308 collect_interfaces (parent, iface_hash, &error);
2309 if (!mono_error_ok (&error))
2313 data.error = &error;
2314 data.domain = mono_object_domain (type);
2316 len = g_hash_table_size (iface_hash);
2318 g_hash_table_destroy (iface_hash);
2319 if (!data.domain->empty_types)
2320 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2321 return data.domain->empty_types;
2324 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2325 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2326 if (!mono_error_ok (&error))
2329 g_hash_table_destroy (iface_hash);
2330 return data.iface_array;
2333 g_hash_table_destroy (iface_hash);
2334 mono_error_set_pending_exception (&error);
2339 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2341 gboolean variance_used;
2342 MonoClass *klass = mono_class_from_mono_type (type->type);
2343 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2344 MonoReflectionMethod *member;
2347 int i = 0, len, ioffset;
2351 mono_class_init_checked (klass, &error);
2352 mono_error_raise_exception (&error);
2353 mono_class_init_checked (iclass, &error);
2354 mono_error_raise_exception (&error);
2356 mono_class_setup_vtable (klass);
2358 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2362 len = mono_class_num_methods (iclass);
2363 domain = mono_object_domain (type);
2364 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2365 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2367 while ((method = mono_class_get_methods (iclass, &iter))) {
2368 member = mono_method_get_object_checked (domain, method, iclass, &error);
2369 mono_error_raise_exception (&error);
2370 mono_array_setref (*methods, i, member);
2371 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2372 mono_error_raise_exception (&error);
2373 mono_array_setref (*targets, i, member);
2380 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2383 MonoClass *klass = mono_class_from_mono_type (type->type);
2385 mono_class_init_checked (klass, &error);
2386 mono_error_raise_exception (&error);
2388 if (image_is_dynamic (klass->image)) {
2389 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2390 *packing = tb->packing_size;
2391 *size = tb->class_size;
2393 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2397 ICALL_EXPORT MonoReflectionType*
2398 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2401 MonoReflectionType *ret;
2404 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2405 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2406 mono_error_raise_exception (&error);
2411 klass = mono_class_from_mono_type (type->type);
2412 mono_class_init_checked (klass, &error);
2413 mono_error_raise_exception (&error);
2415 // GetElementType should only return a type for:
2416 // Array Pointer PassedByRef
2417 if (type->type->byref)
2418 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2419 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2420 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2421 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2422 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2426 mono_error_raise_exception (&error);
2431 ICALL_EXPORT MonoReflectionType*
2432 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2435 MonoReflectionType *ret;
2437 if (type->type->byref)
2440 MonoClass *klass = mono_class_from_mono_type (type->type);
2444 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2445 mono_error_raise_exception (&error);
2450 ICALL_EXPORT MonoBoolean
2451 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2453 return type->type->type == MONO_TYPE_PTR;
2456 ICALL_EXPORT MonoBoolean
2457 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2459 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)));
2462 ICALL_EXPORT MonoBoolean
2463 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2465 return type->type->byref;
2468 ICALL_EXPORT MonoBoolean
2469 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2472 MonoClass *klass = mono_class_from_mono_type (type->type);
2473 mono_class_init_checked (klass, &error);
2474 mono_error_raise_exception (&error);
2476 return mono_class_is_com_object (klass);
2479 ICALL_EXPORT guint32
2480 ves_icall_reflection_get_token (MonoObject* obj)
2483 guint32 result = mono_reflection_get_token_checked (obj, &error);
2484 mono_error_set_pending_exception (&error);
2488 ICALL_EXPORT MonoReflectionModule*
2489 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2492 MonoReflectionModule *result = NULL;
2493 MonoClass *klass = mono_class_from_mono_type (type->type);
2494 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2495 if (!mono_error_ok (&error))
2496 mono_error_set_pending_exception (&error);
2500 ICALL_EXPORT MonoReflectionAssembly*
2501 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2504 MonoDomain *domain = mono_domain_get ();
2505 MonoClass *klass = mono_class_from_mono_type (type->type);
2506 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2508 mono_error_set_pending_exception (&error);
2512 ICALL_EXPORT MonoReflectionType*
2513 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2516 MonoReflectionType *ret;
2517 MonoDomain *domain = mono_domain_get ();
2520 if (type->type->byref)
2522 if (type->type->type == MONO_TYPE_VAR) {
2523 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2524 klass = param ? param->owner.klass : NULL;
2525 } else if (type->type->type == MONO_TYPE_MVAR) {
2526 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2527 klass = param ? param->owner.method->klass : NULL;
2529 klass = mono_class_from_mono_type (type->type)->nested_in;
2535 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2536 mono_error_raise_exception (&error);
2541 ICALL_EXPORT MonoString*
2542 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2544 MonoDomain *domain = mono_domain_get ();
2545 MonoClass *klass = mono_class_from_mono_type (type->type);
2547 if (type->type->byref) {
2548 char *n = g_strdup_printf ("%s&", klass->name);
2549 MonoString *res = mono_string_new (domain, n);
2555 return mono_string_new (domain, klass->name);
2559 ICALL_EXPORT MonoString*
2560 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2562 MonoDomain *domain = mono_domain_get ();
2563 MonoClass *klass = mono_class_from_mono_type (type->type);
2565 while (klass->nested_in)
2566 klass = klass->nested_in;
2568 if (klass->name_space [0] == '\0')
2571 return mono_string_new (domain, klass->name_space);
2575 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2579 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2580 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2584 klass = mono_class_from_mono_type (type->type);
2590 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2593 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2597 ICALL_EXPORT MonoArray*
2598 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2601 MonoReflectionType *rt;
2603 MonoClass *klass, *pklass;
2604 MonoDomain *domain = mono_object_domain (type);
2607 klass = mono_class_from_mono_type (type->type);
2609 if (klass->generic_container) {
2610 MonoGenericContainer *container = klass->generic_container;
2611 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2612 for (i = 0; i < container->type_argc; ++i) {
2613 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2615 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2616 mono_error_raise_exception (&error);
2618 mono_array_setref (res, i, rt);
2620 } else if (klass->generic_class) {
2621 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2622 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2623 for (i = 0; i < inst->type_argc; ++i) {
2624 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2625 mono_error_raise_exception (&error);
2627 mono_array_setref (res, i, rt);
2635 ICALL_EXPORT gboolean
2636 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2640 if (!IS_MONOTYPE (type))
2643 if (type->type->byref)
2646 klass = mono_class_from_mono_type (type->type);
2647 return klass->generic_container != NULL;
2650 ICALL_EXPORT MonoReflectionType*
2651 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2654 MonoReflectionType *ret;
2657 if (type->type->byref)
2660 klass = mono_class_from_mono_type (type->type);
2662 if (klass->generic_container) {
2663 return type; /* check this one */
2665 if (klass->generic_class) {
2666 MonoClass *generic_class = klass->generic_class->container_class;
2669 tb = mono_class_get_ref_info (generic_class);
2671 if (generic_class->wastypebuilder && tb)
2672 return (MonoReflectionType *)tb;
2674 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2675 mono_error_raise_exception (&error);
2683 ICALL_EXPORT MonoReflectionType*
2684 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2687 MonoReflectionType *ret;
2689 MonoType *geninst, **types;
2692 g_assert (IS_MONOTYPE (type));
2693 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2694 mono_error_raise_exception (&error);
2696 count = mono_array_length (type_array);
2697 types = g_new0 (MonoType *, count);
2699 for (i = 0; i < count; i++) {
2700 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2701 types [i] = t->type;
2704 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2707 mono_error_set_pending_exception (&error);
2711 klass = mono_class_from_mono_type (geninst);
2713 /*we might inflate to the GTD*/
2714 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2715 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2719 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2720 mono_error_raise_exception (&error);
2725 ICALL_EXPORT gboolean
2726 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2730 if (!IS_MONOTYPE (type))
2733 if (type->type->byref)
2736 klass = mono_class_from_mono_type (type->type);
2737 return klass->generic_class != NULL || klass->generic_container != NULL;
2741 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2743 if (!IS_MONOTYPE (type))
2746 if (is_generic_parameter (type->type))
2747 return mono_type_get_generic_param_num (type->type);
2751 ICALL_EXPORT GenericParameterAttributes
2752 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2754 g_assert (IS_MONOTYPE (type));
2755 g_assert (is_generic_parameter (type->type));
2756 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2759 ICALL_EXPORT MonoArray *
2760 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2763 MonoReflectionType *rt;
2764 MonoGenericParamInfo *param_info;
2770 g_assert (IS_MONOTYPE (type));
2772 domain = mono_object_domain (type);
2773 param_info = mono_generic_param_info (type->type->data.generic_param);
2774 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2777 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2778 for (i = 0; i < count; i++) {
2779 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2780 mono_error_raise_exception (&error);
2782 mono_array_setref (res, i, rt);
2789 ICALL_EXPORT MonoBoolean
2790 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2792 return is_generic_parameter (type->type);
2795 ICALL_EXPORT MonoBoolean
2796 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2798 return is_generic_parameter (tb->type.type);
2802 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2803 MonoReflectionType *t)
2805 enumtype->type = t->type;
2808 ICALL_EXPORT MonoReflectionMethod*
2809 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2810 MonoReflectionMethod* generic)
2817 MonoReflectionMethod *ret = NULL;
2819 domain = ((MonoObject *)type)->vtable->domain;
2821 klass = mono_class_from_mono_type (type->type);
2822 mono_class_init_checked (klass, &error);
2823 mono_error_raise_exception (&error);
2826 while ((method = mono_class_get_methods (klass, &iter))) {
2827 if (method->token == generic->method->token) {
2828 ret = mono_method_get_object_checked (domain, method, klass, &error);
2829 mono_error_raise_exception (&error);
2836 ICALL_EXPORT MonoReflectionMethod *
2837 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2840 MonoType *type = ref_type->type;
2842 MonoReflectionMethod *ret = NULL;
2844 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2845 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2848 if (type->type == MONO_TYPE_VAR)
2851 method = mono_type_get_generic_param_owner (type)->owner.method;
2854 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2855 if (!mono_error_ok (&error))
2856 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2860 ICALL_EXPORT MonoBoolean
2861 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2863 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2867 ICALL_EXPORT MonoBoolean
2868 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2870 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2875 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2877 MonoDomain *domain = mono_domain_get ();
2878 MonoImage *image = method->method->klass->image;
2879 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2880 MonoTableInfo *tables = image->tables;
2881 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2882 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2883 guint32 im_cols [MONO_IMPLMAP_SIZE];
2884 guint32 scope_token;
2885 const char *import = NULL;
2886 const char *scope = NULL;
2888 if (image_is_dynamic (image)) {
2889 MonoReflectionMethodAux *method_aux =
2890 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2892 import = method_aux->dllentry;
2893 scope = method_aux->dll;
2896 if (!import || !scope) {
2897 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2902 if (piinfo->implmap_idx) {
2903 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2905 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2906 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2907 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2908 scope = mono_metadata_string_heap (image, scope_token);
2912 *flags = piinfo->piflags;
2913 *entry_point = mono_string_new (domain, import);
2914 *dll_name = mono_string_new (domain, scope);
2917 ICALL_EXPORT MonoReflectionMethod *
2918 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2920 MonoMethodInflated *imethod;
2922 MonoReflectionMethod *ret = NULL;
2925 if (method->method->is_generic)
2928 if (!method->method->is_inflated)
2931 imethod = (MonoMethodInflated *) method->method;
2933 result = imethod->declaring;
2934 /* Not a generic method. */
2935 if (!result->is_generic)
2938 if (image_is_dynamic (method->method->klass->image)) {
2939 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2940 MonoReflectionMethod *res;
2943 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2944 * the dynamic case as well ?
2946 mono_image_lock ((MonoImage*)image);
2947 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2948 mono_image_unlock ((MonoImage*)image);
2954 if (imethod->context.class_inst) {
2955 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2956 /*Generic methods gets the context of the GTD.*/
2957 if (mono_class_get_context (klass)) {
2958 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2959 if (!mono_error_ok (&error))
2964 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2966 if (!mono_error_ok (&error))
2967 mono_error_set_pending_exception (&error);
2971 ICALL_EXPORT gboolean
2972 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2974 return mono_method_signature (method->method)->generic_param_count != 0;
2977 ICALL_EXPORT gboolean
2978 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2980 return method->method->is_generic;
2983 ICALL_EXPORT MonoArray*
2984 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2987 MonoReflectionType *rt;
2992 domain = mono_object_domain (method);
2994 if (method->method->is_inflated) {
2995 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2998 count = inst->type_argc;
2999 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3001 for (i = 0; i < count; i++) {
3002 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3003 mono_error_raise_exception (&error);
3005 mono_array_setref (res, i, rt);
3012 count = mono_method_signature (method->method)->generic_param_count;
3013 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3015 for (i = 0; i < count; i++) {
3016 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3017 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3018 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3020 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3021 mono_error_raise_exception (&error);
3023 mono_array_setref (res, i, rt);
3029 ICALL_EXPORT MonoObject *
3030 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3034 * Invoke from reflection is supposed to always be a virtual call (the API
3035 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3036 * greater flexibility.
3038 MonoMethod *m = method->method;
3039 MonoMethodSignature *sig = mono_method_signature (m);
3042 void *obj = this_arg;
3046 if (mono_security_core_clr_enabled ())
3047 mono_security_core_clr_ensure_reflection_access_method (m);
3049 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3050 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3051 mono_error_cleanup (&error); /* FIXME does this make sense? */
3052 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3057 if (!mono_object_isinst (this_arg, m->klass)) {
3058 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3059 char *target_name = mono_type_get_full_name (m->klass);
3060 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3061 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3063 g_free (target_name);
3067 m = mono_object_get_virtual_method (this_arg, m);
3068 /* must pass the pointer to the value for valuetype methods */
3069 if (m->klass->valuetype)
3070 obj = mono_object_unbox (this_arg);
3071 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3072 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3077 if (sig->ret->byref) {
3078 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"));
3082 pcount = params? mono_array_length (params): 0;
3083 if (pcount != sig->param_count) {
3084 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3088 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3089 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."));
3093 image = m->klass->image;
3094 if (image->assembly->ref_only) {
3095 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."));
3099 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3100 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3104 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3108 intptr_t *lower_bounds;
3109 pcount = mono_array_length (params);
3110 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3111 /* Note: the synthetized array .ctors have int32 as argument type */
3112 for (i = 0; i < pcount; ++i)
3113 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3115 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3116 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3117 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3118 if (!mono_error_ok (&error)) {
3119 mono_error_set_pending_exception (&error);
3123 for (i = 0; i < mono_array_length (arr); ++i) {
3124 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3125 if (!mono_error_ok (&error)) {
3126 mono_error_set_pending_exception (&error);
3129 mono_array_setref_fast (arr, i, subarray);
3131 return (MonoObject*)arr;
3134 if (m->klass->rank == pcount) {
3135 /* Only lengths provided. */
3136 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3137 if (!mono_error_ok (&error)) {
3138 mono_error_set_pending_exception (&error);
3142 return (MonoObject*)arr;
3144 g_assert (pcount == (m->klass->rank * 2));
3145 /* The arguments are lower-bound-length pairs */
3146 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3148 for (i = 0; i < pcount / 2; ++i) {
3149 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3150 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3153 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3154 if (!mono_error_ok (&error)) {
3155 mono_error_set_pending_exception (&error);
3159 return (MonoObject*)arr;
3162 return mono_runtime_invoke_array (m, obj, params, NULL);
3165 #ifndef DISABLE_REMOTING
3166 ICALL_EXPORT MonoObject *
3167 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3169 MonoDomain *domain = mono_object_domain (method);
3170 MonoMethod *m = method->method;
3171 MonoMethodSignature *sig = mono_method_signature (m);
3172 MonoArray *out_args;
3174 int i, j, outarg_count = 0;
3176 if (m->klass == mono_defaults.object_class) {
3177 if (!strcmp (m->name, "FieldGetter")) {
3178 MonoClass *k = this_arg->vtable->klass;
3182 /* If this is a proxy, then it must be a CBO */
3183 if (k == mono_defaults.transparent_proxy_class) {
3184 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3185 this_arg = tp->rp->unwrapped_server;
3186 g_assert (this_arg);
3187 k = this_arg->vtable->klass;
3190 name = mono_array_get (params, MonoString *, 1);
3191 str = mono_string_to_utf8 (name);
3194 MonoClassField* field = mono_class_get_field_from_name (k, str);
3196 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3197 if (field_klass->valuetype)
3198 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
3200 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3202 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3203 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3204 mono_array_setref (out_args, 0, result);
3212 g_assert_not_reached ();
3214 } else if (!strcmp (m->name, "FieldSetter")) {
3215 MonoClass *k = this_arg->vtable->klass;
3221 /* If this is a proxy, then it must be a CBO */
3222 if (k == mono_defaults.transparent_proxy_class) {
3223 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3224 this_arg = tp->rp->unwrapped_server;
3225 g_assert (this_arg);
3226 k = this_arg->vtable->klass;
3229 name = mono_array_get (params, MonoString *, 1);
3230 str = mono_string_to_utf8 (name);
3233 MonoClassField* field = mono_class_get_field_from_name (k, str);
3235 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3236 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3238 if (field_klass->valuetype) {
3239 size = mono_type_size (field->type, &align);
3240 g_assert (size == mono_class_value_size (field_klass, NULL));
3241 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3243 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3246 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3247 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3257 g_assert_not_reached ();
3262 for (i = 0; i < mono_array_length (params); i++) {
3263 if (sig->params [i]->byref)
3267 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3269 /* handle constructors only for objects already allocated */
3270 if (!strcmp (method->method->name, ".ctor"))
3271 g_assert (this_arg);
3273 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3274 g_assert (!method->method->klass->valuetype);
3275 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3277 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3278 if (sig->params [i]->byref) {
3280 arg = mono_array_get (params, gpointer, i);
3281 mono_array_setref (out_args, j, arg);
3286 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3293 read_enum_value (const char *mem, int type)
3296 case MONO_TYPE_BOOLEAN:
3298 return *(guint8*)mem;
3300 return *(gint8*)mem;
3301 case MONO_TYPE_CHAR:
3303 return read16 (mem);
3305 return (gint16) read16 (mem);
3307 return read32 (mem);
3309 return (gint32) read32 (mem);
3312 return read64 (mem);
3314 g_assert_not_reached ();
3320 write_enum_value (char *mem, int type, guint64 value)
3324 case MONO_TYPE_I1: {
3325 guint8 *p = (guint8*)mem;
3330 case MONO_TYPE_I2: {
3331 guint16 *p = (guint16 *)mem;
3336 case MONO_TYPE_I4: {
3337 guint32 *p = (guint32 *)mem;
3342 case MONO_TYPE_I8: {
3343 guint64 *p = (guint64 *)mem;
3348 g_assert_not_reached ();
3353 ICALL_EXPORT MonoObject *
3354 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3362 domain = mono_object_domain (enumType);
3363 enumc = mono_class_from_mono_type (enumType->type);
3365 mono_class_init_checked (enumc, &error);
3366 mono_error_raise_exception (&error);
3368 etype = mono_class_enum_basetype (enumc);
3370 res = mono_object_new_checked (domain, enumc, &error);
3371 mono_error_raise_exception (&error);
3372 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3377 ICALL_EXPORT MonoBoolean
3378 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3380 int size = mono_class_value_size (a->vtable->klass, NULL);
3381 guint64 a_val = 0, b_val = 0;
3383 memcpy (&a_val, mono_object_unbox (a), size);
3384 memcpy (&b_val, mono_object_unbox (b), size);
3386 return (a_val & b_val) == b_val;
3389 ICALL_EXPORT MonoObject *
3390 ves_icall_System_Enum_get_value (MonoObject *eobj)
3402 g_assert (eobj->vtable->klass->enumtype);
3404 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3405 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3406 mono_error_raise_exception (&error);
3407 dst = (char *)res + sizeof (MonoObject);
3408 src = (char *)eobj + sizeof (MonoObject);
3409 size = mono_class_value_size (enumc, NULL);
3411 memcpy (dst, src, size);
3416 ICALL_EXPORT MonoReflectionType *
3417 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3420 MonoReflectionType *ret;
3424 klass = mono_class_from_mono_type (type->type);
3425 mono_class_init_checked (klass, &error);
3426 mono_error_raise_exception (&error);
3428 etype = mono_class_enum_basetype (klass);
3430 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3434 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3435 mono_error_raise_exception (&error);
3441 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3443 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3444 gpointer odata = (char *)other + sizeof (MonoObject);
3445 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3446 g_assert (basetype);
3451 if (eobj->vtable->klass != other->vtable->klass)
3454 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3455 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3456 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3459 return me > other ? 1 : -1; \
3462 switch (basetype->type) {
3464 COMPARE_ENUM_VALUES (guint8);
3466 COMPARE_ENUM_VALUES (gint8);
3467 case MONO_TYPE_CHAR:
3469 COMPARE_ENUM_VALUES (guint16);
3471 COMPARE_ENUM_VALUES (gint16);
3473 COMPARE_ENUM_VALUES (guint32);
3475 COMPARE_ENUM_VALUES (gint32);
3477 COMPARE_ENUM_VALUES (guint64);
3479 COMPARE_ENUM_VALUES (gint64);
3483 #undef COMPARE_ENUM_VALUES
3484 /* indicates that the enum was of an unsupported unerlying type */
3489 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3491 gpointer data = (char *)eobj + sizeof (MonoObject);
3492 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3493 g_assert (basetype);
3495 switch (basetype->type) {
3496 case MONO_TYPE_I1: {
3497 gint8 value = *((gint8*)data);
3498 return ((int)value ^ (int)value << 8);
3501 return *((guint8*)data);
3502 case MONO_TYPE_CHAR:
3504 return *((guint16*)data);
3506 case MONO_TYPE_I2: {
3507 gint16 value = *((gint16*)data);
3508 return ((int)(guint16)value | (((int)value) << 16));
3511 return *((guint32*)data);
3513 return *((gint32*)data);
3515 case MONO_TYPE_I8: {
3516 gint64 value = *((gint64*)data);
3517 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3520 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3525 ICALL_EXPORT MonoBoolean
3526 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3529 MonoDomain *domain = mono_object_domain (type);
3530 MonoClass *enumc = mono_class_from_mono_type (type->type);
3531 guint j = 0, nvalues;
3533 MonoClassField *field;
3535 guint64 field_value, previous_value = 0;
3536 gboolean sorted = TRUE;
3538 mono_class_init_checked (enumc, &error);
3539 mono_error_raise_exception (&error);
3541 if (!enumc->enumtype) {
3542 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3546 base_type = mono_class_enum_basetype (enumc)->type;
3548 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3549 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3550 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3553 while ((field = mono_class_get_fields (enumc, &iter))) {
3555 MonoTypeEnum def_type;
3557 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3559 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3561 if (mono_field_is_deleted (field))
3563 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3565 p = mono_class_get_field_default_value (field, &def_type);
3566 /* len = */ mono_metadata_decode_blob_size (p, &p);
3568 field_value = read_enum_value (p, base_type);
3569 mono_array_set (*values, guint64, j, field_value);
3571 if (previous_value > field_value)
3574 previous_value = field_value;
3582 BFLAGS_IgnoreCase = 1,
3583 BFLAGS_DeclaredOnly = 2,
3584 BFLAGS_Instance = 4,
3586 BFLAGS_Public = 0x10,
3587 BFLAGS_NonPublic = 0x20,
3588 BFLAGS_FlattenHierarchy = 0x40,
3589 BFLAGS_InvokeMethod = 0x100,
3590 BFLAGS_CreateInstance = 0x200,
3591 BFLAGS_GetField = 0x400,
3592 BFLAGS_SetField = 0x800,
3593 BFLAGS_GetProperty = 0x1000,
3594 BFLAGS_SetProperty = 0x2000,
3595 BFLAGS_ExactBinding = 0x10000,
3596 BFLAGS_SuppressChangeType = 0x20000,
3597 BFLAGS_OptionalParamBinding = 0x40000
3600 ICALL_EXPORT MonoArray*
3601 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3605 MonoClass *startklass, *klass, *refklass;
3610 char *utf8_name = NULL;
3611 int (*compare_func) (const char *s1, const char *s2) = NULL;
3612 MonoClassField *field;
3613 MonoPtrArray tmp_array;
3615 domain = ((MonoObject *)type)->vtable->domain;
3616 if (type->type->byref)
3617 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3619 klass = startklass = mono_class_from_mono_type (type->type);
3620 refklass = mono_class_from_mono_type (reftype->type);
3622 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3625 if (mono_class_has_failure (klass)) {
3626 mono_ptr_array_destroy (tmp_array);
3627 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3632 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3633 guint32 flags = mono_field_get_flags (field);
3635 if (mono_field_is_deleted_with_flags (field, flags))
3637 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3638 if (bflags & BFLAGS_Public)
3640 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3641 if (bflags & BFLAGS_NonPublic) {
3648 if (flags & FIELD_ATTRIBUTE_STATIC) {
3649 if (bflags & BFLAGS_Static)
3650 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3653 if (bflags & BFLAGS_Instance)
3661 if (utf8_name == NULL) {
3662 utf8_name = mono_string_to_utf8 (name);
3663 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3666 if (compare_func (mono_field_get_name (field), utf8_name))
3670 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3671 if (!mono_error_ok (&error))
3673 mono_ptr_array_append (tmp_array, member);
3675 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3678 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3680 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3681 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3683 mono_ptr_array_destroy (tmp_array);
3685 if (utf8_name != NULL)
3690 mono_ptr_array_destroy (tmp_array);
3691 mono_error_raise_exception (&error);
3692 g_assert_not_reached ();
3696 method_nonpublic (MonoMethod* method, gboolean start_klass)
3698 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3699 case METHOD_ATTRIBUTE_ASSEM:
3700 return (start_klass || mono_defaults.generic_ilist_class);
3701 case METHOD_ATTRIBUTE_PRIVATE:
3703 case METHOD_ATTRIBUTE_PUBLIC:
3711 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3714 MonoClass *startklass;
3718 /*FIXME, use MonoBitSet*/
3719 guint32 method_slots_default [8];
3720 guint32 *method_slots = NULL;
3721 int (*compare_func) (const char *s1, const char *s2) = NULL;
3723 array = g_ptr_array_new ();
3728 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3730 /* An optimization for calls made from Delegate:CreateDelegate () */
3731 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3732 method = mono_get_delegate_invoke (klass);
3733 if (mono_loader_get_last_error ())
3736 g_ptr_array_add (array, method);
3740 mono_class_setup_methods (klass);
3741 mono_class_setup_vtable (klass);
3742 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3745 if (is_generic_parameter (&klass->byval_arg))
3746 nslots = mono_class_get_vtable_size (klass->parent);
3748 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3749 if (nslots >= sizeof (method_slots_default) * 8) {
3750 method_slots = g_new0 (guint32, nslots / 32 + 1);
3752 method_slots = method_slots_default;
3753 memset (method_slots, 0, sizeof (method_slots_default));
3756 mono_class_setup_methods (klass);
3757 mono_class_setup_vtable (klass);
3758 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3762 while ((method = mono_class_get_methods (klass, &iter))) {
3764 if (method->slot != -1) {
3765 g_assert (method->slot < nslots);
3766 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3768 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3769 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3772 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3774 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3775 if (bflags & BFLAGS_Public)
3777 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3783 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3784 if (bflags & BFLAGS_Static)
3785 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3788 if (bflags & BFLAGS_Instance)
3796 if (compare_func (name, method->name))
3801 g_ptr_array_add (array, method);
3803 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3805 if (method_slots != method_slots_default)
3806 g_free (method_slots);
3811 if (method_slots != method_slots_default)
3812 g_free (method_slots);
3813 g_ptr_array_free (array, TRUE);
3815 if (mono_class_has_failure (klass)) {
3816 *ex = mono_class_get_exception_for_failure (klass);
3818 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3819 mono_loader_clear_error ();
3824 ICALL_EXPORT MonoArray*
3825 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3827 static MonoClass *MethodInfo_array;
3831 MonoVTable *array_vtable;
3832 MonoException *ex = NULL;
3833 const char *mname = NULL;
3834 GPtrArray *method_array;
3835 MonoClass *klass, *refklass;
3838 mono_error_init (&error);
3840 if (!MethodInfo_array) {
3841 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3842 mono_memory_barrier ();
3843 MethodInfo_array = klass;
3846 klass = mono_class_from_mono_type (type->type);
3847 refklass = mono_class_from_mono_type (reftype->type);
3848 domain = ((MonoObject *)type)->vtable->domain;
3849 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3850 if (!is_ok (&error)) {
3851 mono_error_set_pending_exception (&error);
3854 if (type->type->byref) {
3855 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3856 mono_error_set_pending_exception (&error);
3862 mname = mono_string_to_utf8 (name);
3864 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3865 g_free ((char*)mname);
3867 mono_set_pending_exception (ex);
3871 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3872 if (!mono_error_ok (&error)) {
3873 mono_error_set_pending_exception (&error);
3877 for (i = 0; i < method_array->len; ++i) {
3878 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3879 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3880 if (!mono_error_ok (&error))
3882 mono_array_setref (res, i, rm);
3886 g_ptr_array_free (method_array, TRUE);
3887 if (!mono_error_ok (&error))
3888 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3892 ICALL_EXPORT MonoArray*
3893 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3896 MonoClass *startklass, *klass, *refklass;
3901 gpointer iter = NULL;
3902 MonoPtrArray tmp_array;
3905 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3907 domain = ((MonoObject *)type)->vtable->domain;
3908 if (type->type->byref)
3909 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3910 klass = startklass = mono_class_from_mono_type (type->type);
3911 refklass = mono_class_from_mono_type (reftype->type);
3913 mono_class_setup_methods (klass);
3914 if (mono_class_has_failure (klass)) {
3915 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3920 while ((method = mono_class_get_methods (klass, &iter))) {
3922 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3924 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3925 if (bflags & BFLAGS_Public)
3928 if (bflags & BFLAGS_NonPublic)
3934 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3935 if (bflags & BFLAGS_Static)
3936 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3939 if (bflags & BFLAGS_Instance)
3945 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3946 if (!mono_error_ok (&error)) {
3947 mono_error_set_pending_exception (&error);
3951 mono_ptr_array_append (tmp_array, member);
3954 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
3956 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3957 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3959 mono_ptr_array_destroy (tmp_array);
3965 property_hash (gconstpointer data)
3967 MonoProperty *prop = (MonoProperty*)data;
3969 return g_str_hash (prop->name);
3973 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3975 if (method1->is_inflated)
3976 method1 = ((MonoMethodInflated*) method1)->declaring;
3977 if (method2->is_inflated)
3978 method2 = ((MonoMethodInflated*) method2)->declaring;
3980 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3984 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3986 // Properties are hide-by-name-and-signature
3987 if (!g_str_equal (prop1->name, prop2->name))
3990 /* If we see a property in a generic method, we want to
3991 compare the generic signatures, not the inflated signatures
3992 because we might conflate two properties that were
3996 public T this[T t] { getter { return t; } } // method 1
3997 public U this[U u] { getter { return u; } } // method 2
4000 If we see int Foo<int,int>::Item[int] we need to know if
4001 the indexer came from method 1 or from method 2, and we
4002 shouldn't conflate them. (Bugzilla 36283)
4004 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
4007 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4014 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4019 return method_nonpublic (accessor, start_klass);
4022 ICALL_EXPORT MonoArray*
4023 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4027 MonoClass *startklass, *klass;
4033 gchar *propname = NULL;
4034 int (*compare_func) (const char *s1, const char *s2) = NULL;
4036 GHashTable *properties = NULL;
4037 MonoPtrArray tmp_array;
4039 mono_error_init (&error);
4041 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4043 domain = ((MonoObject *)type)->vtable->domain;
4044 if (type->type->byref)
4045 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
4046 klass = startklass = mono_class_from_mono_type (type->type);
4049 propname = mono_string_to_utf8 (name);
4050 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4053 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4055 mono_class_setup_methods (klass);
4056 mono_class_setup_vtable (klass);
4057 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4061 while ((prop = mono_class_get_properties (klass, &iter))) {
4067 flags = method->flags;
4070 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4071 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4072 if (bflags & BFLAGS_Public)
4074 } else if (bflags & BFLAGS_NonPublic) {
4075 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4076 property_accessor_nonpublic(prop->set, startklass == klass)) {
4083 if (flags & METHOD_ATTRIBUTE_STATIC) {
4084 if (bflags & BFLAGS_Static)
4085 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4088 if (bflags & BFLAGS_Instance)
4097 if (compare_func (propname, prop->name))
4101 if (g_hash_table_lookup (properties, prop))
4104 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4107 mono_ptr_array_append (tmp_array, pr);
4109 g_hash_table_insert (properties, prop, prop);
4111 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4114 g_hash_table_destroy (properties);
4117 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4118 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4119 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4121 mono_ptr_array_destroy (tmp_array);
4128 if (mono_class_has_failure (klass)) {
4129 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4131 mono_error_set_from_loader_error (&error);
4132 mono_loader_clear_error ();
4137 g_hash_table_destroy (properties);
4140 mono_ptr_array_destroy (tmp_array);
4142 mono_error_set_pending_exception (&error);
4148 event_hash (gconstpointer data)
4150 MonoEvent *event = (MonoEvent*)data;
4152 return g_str_hash (event->name);
4156 event_equal (MonoEvent *event1, MonoEvent *event2)
4158 // Events are hide-by-name
4159 return g_str_equal (event1->name, event2->name);
4162 ICALL_EXPORT MonoArray*
4163 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4167 MonoClass *startklass, *klass;
4173 char *utf8_name = NULL;
4174 int (*compare_func) (const char *s1, const char *s2) = NULL;
4175 GHashTable *events = NULL;
4176 MonoPtrArray tmp_array;
4178 mono_error_init (&error);
4180 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4182 domain = mono_object_domain (type);
4183 if (type->type->byref)
4184 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4185 klass = startklass = mono_class_from_mono_type (type->type);
4187 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4189 mono_class_setup_methods (klass);
4190 mono_class_setup_vtable (klass);
4191 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4195 while ((event = mono_class_get_events (klass, &iter))) {
4197 method = event->add;
4199 method = event->remove;
4201 method = event->raise;
4203 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4204 if (bflags & BFLAGS_Public)
4206 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4207 if (bflags & BFLAGS_NonPublic)
4212 if (bflags & BFLAGS_NonPublic)
4218 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4219 if (bflags & BFLAGS_Static)
4220 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4223 if (bflags & BFLAGS_Instance)
4228 if (bflags & BFLAGS_Instance)
4234 if (utf8_name == NULL) {
4235 utf8_name = mono_string_to_utf8 (name);
4236 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4239 if (compare_func (event->name, utf8_name))
4243 if (g_hash_table_lookup (events, event))
4246 MonoReflectionEvent *ev_obj;
4247 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4250 mono_ptr_array_append (tmp_array, ev_obj);
4252 g_hash_table_insert (events, event, event);
4254 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4257 g_hash_table_destroy (events);
4259 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4261 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4262 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4264 mono_ptr_array_destroy (tmp_array);
4266 if (utf8_name != NULL)
4272 if (mono_class_has_failure (klass)) {
4273 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4275 mono_error_set_from_loader_error (&error);
4276 mono_loader_clear_error ();
4282 g_hash_table_destroy (events);
4283 if (utf8_name != NULL)
4286 mono_ptr_array_destroy (tmp_array);
4288 mono_error_set_pending_exception (&error);
4292 ICALL_EXPORT MonoArray*
4293 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4296 MonoReflectionType *rt;
4304 MonoPtrArray tmp_array;
4306 domain = ((MonoObject *)type)->vtable->domain;
4307 if (type->type->byref)
4308 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4309 klass = mono_class_from_mono_type (type->type);
4312 * If a nested type is generic, return its generic type definition.
4313 * Note that this means that the return value is essentially the set
4314 * of nested types of the generic type definition of @klass.
4316 * A note in MSDN claims that a generic type definition can have
4317 * nested types that aren't generic. In any case, the container of that
4318 * nested type would be the generic type definition.
4320 if (klass->generic_class)
4321 klass = klass->generic_class->container_class;
4323 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4325 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4327 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4328 if (bflags & BFLAGS_Public)
4331 if (bflags & BFLAGS_NonPublic)
4339 str = mono_string_to_utf8 (name);
4340 mono_identifier_unescape_type_name_chars (str);
4343 if (strcmp (nested->name, str))
4347 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4348 mono_error_raise_exception (&error);
4350 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4353 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4355 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4356 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4358 mono_ptr_array_destroy (tmp_array);
4366 ICALL_EXPORT MonoReflectionType*
4367 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4370 MonoReflectionType *ret;
4372 MonoType *type = NULL;
4373 MonoTypeNameParse info;
4374 gboolean type_resolve;
4376 /* On MS.NET, this does not fire a TypeResolve event */
4377 type_resolve = TRUE;
4378 str = mono_string_to_utf8 (name);
4379 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4380 if (!mono_reflection_parse_type (str, &info)) {
4382 mono_reflection_free_type_info (&info);
4384 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4387 /*g_print ("failed parse\n");*/
4391 if (info.assembly.name) {
4393 mono_reflection_free_type_info (&info);
4395 /* 1.0 and 2.0 throw different exceptions */
4396 if (mono_defaults.generic_ilist_class)
4397 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4399 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4405 if (module != NULL) {
4406 if (module->image) {
4407 type = mono_reflection_get_type_checked (module->image, &info, ignoreCase, &type_resolve, &error);
4408 if (!is_ok (&error)) {
4410 mono_reflection_free_type_info (&info);
4411 mono_error_set_pending_exception (&error);
4418 if (assembly_is_dynamic (assembly->assembly)) {
4419 /* Enumerate all modules */
4420 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4424 if (abuilder->modules) {
4425 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4426 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4427 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4428 if (!is_ok (&error)) {
4430 mono_reflection_free_type_info (&info);
4431 mono_error_set_pending_exception (&error);
4439 if (!type && abuilder->loaded_modules) {
4440 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4441 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4442 type = mono_reflection_get_type_checked (mod->image, &info, ignoreCase, &type_resolve, &error);
4443 if (!is_ok (&error)) {
4445 mono_reflection_free_type_info (&info);
4446 mono_error_set_pending_exception (&error);
4455 type = mono_reflection_get_type_checked (assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4456 if (!is_ok (&error)) {
4458 mono_reflection_free_type_info (&info);
4459 mono_error_set_pending_exception (&error);
4464 mono_reflection_free_type_info (&info);
4466 MonoException *e = NULL;
4469 e = mono_get_exception_type_load (name, NULL);
4471 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4472 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4474 mono_loader_clear_error ();
4477 mono_set_pending_exception (e);
4479 } else if (mono_loader_get_last_error ()) {
4481 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4484 mono_loader_clear_error ();
4487 if (type->type == MONO_TYPE_CLASS) {
4488 MonoClass *klass = mono_type_get_class (type);
4490 /* need to report exceptions ? */
4491 if (throwOnError && mono_class_has_failure (klass)) {
4492 /* report SecurityException (or others) that occured when loading the assembly */
4493 MonoException *exc = mono_class_get_exception_for_failure (klass);
4494 mono_loader_clear_error ();
4495 mono_set_pending_exception (exc);
4500 /* g_print ("got it\n"); */
4501 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4502 mono_error_set_pending_exception (&error);
4508 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4511 gchar *shadow_ini_file;
4514 /* Check for shadow-copied assembly */
4515 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4516 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4518 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4519 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4525 g_free (shadow_ini_file);
4526 if (content != NULL) {
4529 *filename = content;
4536 ICALL_EXPORT MonoString *
4537 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4539 MonoDomain *domain = mono_object_domain (assembly);
4540 MonoAssembly *mass = assembly->assembly;
4541 MonoString *res = NULL;
4546 if (g_path_is_absolute (mass->image->name)) {
4547 absolute = g_strdup (mass->image->name);
4548 dirname = g_path_get_dirname (absolute);
4550 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4551 dirname = g_strdup (mass->basedir);
4554 replace_shadow_path (domain, dirname, &absolute);
4559 for (i = strlen (absolute) - 1; i >= 0; i--)
4560 if (absolute [i] == '\\')
4565 uri = g_filename_to_uri (absolute, NULL, NULL);
4567 const char *prepend = "file://";
4569 if (*absolute == '/' && *(absolute + 1) == '/') {
4572 prepend = "file:///";
4575 uri = g_strconcat (prepend, absolute, NULL);
4579 res = mono_string_new (domain, uri);
4586 ICALL_EXPORT MonoBoolean
4587 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4589 MonoAssembly *mass = assembly->assembly;
4591 return mass->in_gac;
4594 ICALL_EXPORT MonoReflectionAssembly*
4595 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4600 MonoImageOpenStatus status;
4601 MonoReflectionAssembly* result = NULL;
4603 name = mono_string_to_utf8 (mname);
4604 res = mono_assembly_load_with_partial_name (name, &status);
4610 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4612 mono_error_set_pending_exception (&error);
4616 ICALL_EXPORT MonoString *
4617 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4619 MonoDomain *domain = mono_object_domain (assembly);
4622 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4627 ICALL_EXPORT MonoBoolean
4628 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4630 return assembly->assembly->ref_only;
4633 ICALL_EXPORT MonoString *
4634 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4636 MonoDomain *domain = mono_object_domain (assembly);
4638 return mono_string_new (domain, assembly->assembly->image->version);
4641 ICALL_EXPORT MonoReflectionMethod*
4642 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4645 MonoReflectionMethod *res = NULL;
4648 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4652 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4653 if (!mono_error_ok (&error))
4656 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4659 if (!mono_error_ok (&error))
4660 mono_error_set_pending_exception (&error);
4664 ICALL_EXPORT MonoReflectionModule*
4665 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4668 MonoReflectionModule *result = NULL;
4669 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4670 if (!mono_error_ok (&error))
4671 mono_error_set_pending_exception (&error);
4675 ICALL_EXPORT MonoArray*
4676 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4678 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4679 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4683 for (i = 0; i < table->rows; ++i) {
4684 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4685 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4691 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4693 static MonoMethod *create_version = NULL;
4697 mono_error_init (error);
4700 if (!create_version) {
4701 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4702 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4703 g_assert (create_version);
4704 mono_method_desc_free (desc);
4710 args [3] = &revision;
4711 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4712 return_val_if_nok (error, NULL);
4714 mono_runtime_invoke_checked (create_version, result, args, error);
4715 return_val_if_nok (error, NULL);
4720 ICALL_EXPORT MonoArray*
4721 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4725 MonoDomain *domain = mono_object_domain (assembly);
4727 static MonoMethod *create_culture = NULL;
4728 MonoImage *image = assembly->assembly->image;
4732 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4735 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4737 if (count > 0 && !create_culture) {
4738 MonoMethodDesc *desc = mono_method_desc_new (
4739 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4740 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4741 g_assert (create_culture);
4742 mono_method_desc_free (desc);
4745 for (i = 0; i < count; i++) {
4746 MonoObject *version;
4747 MonoReflectionAssemblyName *aname;
4748 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4750 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4752 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4753 domain, mono_class_get_assembly_name_class (), &error);
4754 mono_error_raise_exception (&error);
4756 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4758 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4759 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4760 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4761 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4762 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4763 aname->versioncompat = 1; /* SameMachine (default) */
4764 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4766 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4767 mono_error_raise_exception (&error);
4769 MONO_OBJECT_SETREF (aname, version, version);
4771 if (create_culture) {
4773 MonoBoolean assembly_ref = 1;
4774 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4775 args [1] = &assembly_ref;
4777 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4778 mono_error_raise_exception (&error);
4780 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4783 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4784 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4785 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4787 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4788 /* public key token isn't copied - the class library will
4789 automatically generate it from the public key if required */
4790 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4791 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4793 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4794 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4797 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4800 /* note: this function doesn't return the codebase on purpose (i.e. it can
4801 be used under partial trust as path information isn't present). */
4803 mono_array_setref (result, i, aname);
4808 /* move this in some file in mono/util/ */
4810 g_concat_dir_and_file (const char *dir, const char *file)
4812 g_return_val_if_fail (dir != NULL, NULL);
4813 g_return_val_if_fail (file != NULL, NULL);
4816 * If the directory name doesn't have a / on the end, we need
4817 * to add one so we get a proper path to the file
4819 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4820 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4822 return g_strconcat (dir, file, NULL);
4826 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4829 char *n = mono_string_to_utf8 (name);
4830 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4832 guint32 cols [MONO_MANIFEST_SIZE];
4833 guint32 impl, file_idx;
4837 for (i = 0; i < table->rows; ++i) {
4838 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4839 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4840 if (strcmp (val, n) == 0)
4844 if (i == table->rows)
4847 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4850 * this code should only be called after obtaining the
4851 * ResourceInfo and handling the other cases.
4853 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4854 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4856 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4861 module = assembly->assembly->image;
4864 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4865 mono_error_raise_exception (&error);
4866 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4868 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4871 ICALL_EXPORT gboolean
4872 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4875 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4877 guint32 cols [MONO_MANIFEST_SIZE];
4878 guint32 file_cols [MONO_FILE_SIZE];
4882 n = mono_string_to_utf8 (name);
4883 for (i = 0; i < table->rows; ++i) {
4884 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4885 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4886 if (strcmp (val, n) == 0)
4890 if (i == table->rows)
4893 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4894 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4897 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4898 case MONO_IMPLEMENTATION_FILE:
4899 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4900 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4901 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4902 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4903 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4904 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4907 info->location = RESOURCE_LOCATION_EMBEDDED;
4910 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4911 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4912 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4913 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4914 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4915 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4917 mono_set_pending_exception (ex);
4920 MonoReflectionAssembly *assm_obj;
4921 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4923 mono_error_set_pending_exception (&error);
4926 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4928 /* Obtain info recursively */
4929 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4930 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4933 case MONO_IMPLEMENTATION_EXP_TYPE:
4934 g_assert_not_reached ();
4942 ICALL_EXPORT MonoObject*
4943 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4945 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4946 MonoArray *result = NULL;
4951 /* check hash if needed */
4953 n = mono_string_to_utf8 (name);
4954 for (i = 0; i < table->rows; ++i) {
4955 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4956 if (strcmp (val, n) == 0) {
4959 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4960 fn = mono_string_new (mono_object_domain (assembly), n);
4962 return (MonoObject*)fn;
4970 for (i = 0; i < table->rows; ++i) {
4971 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4975 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4978 for (i = 0; i < table->rows; ++i) {
4979 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4980 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4981 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4982 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4987 return (MonoObject*)result;
4990 ICALL_EXPORT MonoArray*
4991 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4994 MonoDomain *domain = mono_domain_get();
4997 int i, j, file_count = 0;
4998 MonoImage **modules;
4999 guint32 module_count, real_module_count;
5000 MonoTableInfo *table;
5001 guint32 cols [MONO_FILE_SIZE];
5002 MonoImage *image = assembly->assembly->image;
5004 g_assert (image != NULL);
5005 g_assert (!assembly_is_dynamic (assembly->assembly));
5007 table = &image->tables [MONO_TABLE_FILE];
5008 file_count = table->rows;
5010 modules = image->modules;
5011 module_count = image->module_count;
5013 real_module_count = 0;
5014 for (i = 0; i < module_count; ++i)
5016 real_module_count ++;
5018 klass = mono_class_get_module_class ();
5019 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
5021 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5022 mono_error_raise_exception (&error);
5023 mono_array_setref (res, 0, image_obj);
5025 for (i = 0; i < module_count; ++i)
5027 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5028 mono_error_raise_exception (&error);
5029 mono_array_setref (res, j, rm);
5033 for (i = 0; i < file_count; ++i, ++j) {
5034 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5035 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5036 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5037 mono_error_raise_exception (&error);
5038 mono_array_setref (res, j, rm);
5041 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5043 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5044 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5047 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5048 mono_error_raise_exception (&error);
5049 mono_array_setref (res, j, rm);
5056 ICALL_EXPORT MonoReflectionMethod*
5057 ves_icall_GetCurrentMethod (void)
5059 MonoReflectionMethod *res = NULL;
5062 MonoMethod *m = mono_method_get_last_managed ();
5065 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5069 while (m->is_inflated)
5070 m = ((MonoMethodInflated*)m)->declaring;
5072 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5073 mono_error_raise_exception (&error);
5079 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5082 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5085 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5086 //method is inflated, we should inflate it on the other class
5087 MonoGenericContext ctx;
5088 ctx.method_inst = inflated->context.method_inst;
5089 ctx.class_inst = inflated->context.class_inst;
5090 if (klass->generic_class)
5091 ctx.class_inst = klass->generic_class->context.class_inst;
5092 else if (klass->generic_container)
5093 ctx.class_inst = klass->generic_container->context.class_inst;
5094 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5095 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5099 mono_class_setup_methods (method->klass);
5100 if (mono_class_has_failure (method->klass))
5102 for (i = 0; i < method->klass->method.count; ++i) {
5103 if (method->klass->methods [i] == method) {
5108 mono_class_setup_methods (klass);
5109 if (mono_class_has_failure (klass))
5111 g_assert (offset >= 0 && offset < klass->method.count);
5112 return klass->methods [offset];
5115 ICALL_EXPORT MonoReflectionMethod*
5116 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5118 MonoReflectionMethod *res = NULL;
5122 klass = mono_class_from_mono_type (type);
5123 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5125 if (method->klass != klass) {
5126 method = mono_method_get_equivalent_method (method, klass);
5131 klass = method->klass;
5132 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5133 mono_error_raise_exception (&error);
5137 ICALL_EXPORT MonoReflectionMethodBody*
5138 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5141 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5142 mono_error_set_pending_exception (&error);
5146 ICALL_EXPORT MonoReflectionAssembly*
5147 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5150 MonoReflectionAssembly *result;
5151 MonoMethod *dest = NULL;
5153 mono_stack_walk_no_il (get_executing, &dest);
5155 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5157 mono_error_set_pending_exception (&error);
5162 ICALL_EXPORT MonoReflectionAssembly*
5163 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5166 MonoReflectionAssembly *result;
5167 MonoDomain* domain = mono_domain_get ();
5169 if (!domain->entry_assembly)
5172 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5174 mono_error_set_pending_exception (&error);
5178 ICALL_EXPORT MonoReflectionAssembly*
5179 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5184 MonoReflectionAssembly *result;
5187 mono_stack_walk_no_il (get_executing, &dest);
5189 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5193 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5196 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5198 mono_error_set_pending_exception (&error);
5202 ICALL_EXPORT MonoString *
5203 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5204 gboolean assembly_qualified)
5206 MonoDomain *domain = mono_object_domain (object);
5207 MonoTypeNameFormat format;
5212 format = assembly_qualified ?
5213 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5214 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5216 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5218 name = mono_type_get_name_full (object->type, format);
5222 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5227 res = mono_string_new (domain, name);
5234 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5237 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5239 mono_class_init_checked (klass, &error);
5240 mono_error_raise_exception (&error);
5241 return mono_security_core_clr_class_level (klass);
5245 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5247 MonoClassField *field = rfield->field;
5248 return mono_security_core_clr_field_level (field, TRUE);
5252 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5254 MonoMethod *method = rfield->method;
5255 return mono_security_core_clr_method_level (method, TRUE);
5259 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)
5261 static MonoMethod *create_culture = NULL;
5265 const char *pkey_ptr;
5267 MonoBoolean assembly_ref = 0;
5269 mono_error_init (error);
5271 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5272 aname->major = name->major;
5273 aname->minor = name->minor;
5274 aname->build = name->build;
5275 aname->flags = name->flags;
5276 aname->revision = name->revision;
5277 aname->hashalg = name->hash_alg;
5278 aname->versioncompat = 1; /* SameMachine (default) */
5279 aname->processor_architecture = name->arch;
5281 if (by_default_version) {
5282 MonoObject *version;
5284 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5285 return_if_nok (error);
5287 MONO_OBJECT_SETREF (aname, version, version);
5291 if (absolute != NULL && *absolute != '\0') {
5292 const gchar *prepend = "file://";
5295 codebase = g_strdup (absolute);
5300 for (i = strlen (codebase) - 1; i >= 0; i--)
5301 if (codebase [i] == '\\')
5304 if (*codebase == '/' && *(codebase + 1) == '/') {
5307 prepend = "file:///";
5311 result = g_strconcat (prepend, codebase, NULL);
5317 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5321 if (!create_culture) {
5322 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5323 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5324 g_assert (create_culture);
5325 mono_method_desc_free (desc);
5328 if (name->culture) {
5329 args [0] = mono_string_new (domain, name->culture);
5330 args [1] = &assembly_ref;
5332 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5333 return_if_nok (error);
5335 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5338 if (name->public_key) {
5339 pkey_ptr = (char*)name->public_key;
5340 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5342 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5343 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5344 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5345 } else if (default_publickey) {
5346 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5347 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5350 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5351 if (name->public_key_token [0]) {
5355 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5356 p = mono_array_addr (aname->keyToken, char, 0);
5358 for (i = 0, j = 0; i < 8; i++) {
5359 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5360 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5363 } else if (default_token) {
5364 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5368 ICALL_EXPORT MonoString *
5369 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5371 MonoDomain *domain = mono_object_domain (assembly);
5372 MonoAssembly *mass = assembly->assembly;
5376 name = mono_stringify_assembly_name (&mass->aname);
5377 res = mono_string_new (domain, name);
5384 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5388 MonoAssembly *mass = assembly->assembly;
5390 if (g_path_is_absolute (mass->image->name)) {
5391 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5392 mono_error_set_pending_exception (&error);
5395 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5397 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5398 mono_error_set_pending_exception (&error);
5404 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5408 MonoImageOpenStatus status = MONO_IMAGE_OK;
5411 MonoAssemblyName name;
5414 filename = mono_string_to_utf8 (fname);
5416 dirname = g_path_get_dirname (filename);
5417 replace_shadow_path (mono_domain_get (), dirname, &filename);
5420 image = mono_image_open (filename, &status);
5426 if (status == MONO_IMAGE_IMAGE_INVALID)
5427 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5429 exc = mono_get_exception_file_not_found2 (NULL, fname);
5430 mono_set_pending_exception (exc);
5434 res = mono_assembly_fill_assembly_name (image, &name);
5436 mono_image_close (image);
5438 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5442 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5443 mono_error_set_pending_exception (&error);
5445 mono_image_close (image);
5449 ICALL_EXPORT MonoBoolean
5450 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5451 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5453 MonoBoolean result = FALSE;
5454 MonoDeclSecurityEntry entry;
5456 /* SecurityAction.RequestMinimum */
5457 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5458 *minimum = entry.blob;
5459 *minLength = entry.size;
5462 /* SecurityAction.RequestOptional */
5463 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5464 *optional = entry.blob;
5465 *optLength = entry.size;
5468 /* SecurityAction.RequestRefuse */
5469 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5470 *refused = entry.blob;
5471 *refLength = entry.size;
5479 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5481 guint32 attrs, visibility;
5483 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5484 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5485 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5488 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5494 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5496 MonoReflectionType *rt;
5499 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5502 mono_error_init (error);
5504 /* we start the count from 1 because we skip the special type <Module> */
5507 for (i = 1; i < tdef->rows; ++i) {
5508 if (mono_module_type_is_visible (tdef, image, i + 1))
5512 count = tdef->rows - 1;
5514 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5515 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5517 for (i = 1; i < tdef->rows; ++i) {
5518 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5519 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5520 mono_loader_assert_no_error (); /* Plug any leaks */
5521 mono_error_assert_ok (error);
5524 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5525 return_val_if_nok (error, NULL);
5527 mono_array_setref (res, count, rt);
5529 MonoException *ex = mono_error_convert_to_exception (error);
5530 mono_array_setref (*exceptions, count, ex);
5539 ICALL_EXPORT MonoArray*
5540 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5543 MonoArray *res = NULL;
5544 MonoArray *exceptions = NULL;
5545 MonoImage *image = NULL;
5546 MonoTableInfo *table = NULL;
5549 int i, len, ex_count;
5551 domain = mono_object_domain (assembly);
5553 g_assert (!assembly_is_dynamic (assembly->assembly));
5554 image = assembly->assembly->image;
5555 table = &image->tables [MONO_TABLE_FILE];
5556 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5557 mono_error_raise_exception (&error);
5559 /* Append data from all modules in the assembly */
5560 for (i = 0; i < table->rows; ++i) {
5561 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5562 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5567 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5568 mono_error_raise_exception (&error);
5570 /* Append the new types to the end of the array */
5571 if (mono_array_length (res2) > 0) {
5573 MonoArray *res3, *ex3;
5575 len1 = mono_array_length (res);
5576 len2 = mono_array_length (res2);
5578 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5579 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5580 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5583 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5584 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5585 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5592 /* the ReflectionTypeLoadException must have all the types (Types property),
5593 * NULL replacing types which throws an exception. The LoaderException must
5594 * contain all exceptions for NULL items.
5597 len = mono_array_length (res);
5600 for (i = 0; i < len; i++) {
5601 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5605 klass = mono_type_get_class (t->type);
5606 if ((klass != NULL) && mono_class_has_failure (klass)) {
5607 /* keep the class in the list */
5608 list = g_list_append (list, klass);
5609 /* and replace Type with NULL */
5610 mono_array_setref (res, i, NULL);
5617 if (list || ex_count) {
5619 MonoException *exc = NULL;
5620 MonoArray *exl = NULL;
5621 int j, length = g_list_length (list) + ex_count;
5623 mono_loader_clear_error ();
5625 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5626 /* Types for which mono_class_get_checked () succeeded */
5627 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5628 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5629 mono_array_setref (exl, i, exc);
5631 /* Types for which it don't */
5632 for (j = 0; j < mono_array_length (exceptions); ++j) {
5633 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5635 g_assert (i < length);
5636 mono_array_setref (exl, i, exc);
5643 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5644 if (!is_ok (&error)) {
5645 mono_error_set_pending_exception (&error);
5648 mono_loader_clear_error ();
5649 mono_set_pending_exception (exc);
5656 ICALL_EXPORT gboolean
5657 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5660 MonoAssemblyName aname;
5661 MonoDomain *domain = mono_object_domain (name);
5663 gboolean is_version_defined;
5664 gboolean is_token_defined;
5666 aname.public_key = NULL;
5667 val = mono_string_to_utf8 (assname);
5668 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5669 g_free ((guint8*) aname.public_key);
5674 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5675 mono_error_set_pending_exception (&error);
5677 mono_assembly_name_free (&aname);
5678 g_free ((guint8*) aname.public_key);
5684 ICALL_EXPORT MonoReflectionType*
5685 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5688 MonoReflectionType *ret;
5689 MonoDomain *domain = mono_object_domain (module);
5692 g_assert (module->image);
5694 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5695 /* These images do not have a global type */
5698 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5699 if (!mono_error_ok (&error)) {
5700 mono_error_set_pending_exception (&error);
5704 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5705 if (!mono_error_ok (&error)) {
5706 mono_error_set_pending_exception (&error);
5714 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5716 /*if (module->image)
5717 mono_image_close (module->image);*/
5720 ICALL_EXPORT MonoString*
5721 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5723 MonoDomain *domain = mono_object_domain (module);
5725 g_assert (module->image);
5726 return mono_string_new (domain, module->image->guid);
5729 ICALL_EXPORT gpointer
5730 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5733 if (module->image && module->image->is_module_handle)
5734 return module->image->raw_data;
5737 return (gpointer) (-1);
5741 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5743 if (image_is_dynamic (image)) {
5744 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5745 *pe_kind = dyn->pe_kind;
5746 *machine = dyn->machine;
5749 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5750 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5755 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5757 return (image->md_version_major << 16) | (image->md_version_minor);
5760 ICALL_EXPORT MonoArray*
5761 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5764 MonoArray *exceptions;
5768 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5772 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5773 mono_error_raise_exception (&error);
5775 for (i = 0; i < mono_array_length (exceptions); ++i) {
5776 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5778 mono_set_pending_exception (ex);
5787 mono_memberref_is_method (MonoImage *image, guint32 token)
5789 if (!image_is_dynamic (image)) {
5790 guint32 cols [MONO_MEMBERREF_SIZE];
5792 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5793 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5794 mono_metadata_decode_blob_size (sig, &sig);
5795 return (*sig != 0x6);
5797 MonoClass *handle_class;
5799 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5802 return mono_defaults.methodhandle_class == handle_class;
5807 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5810 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5811 mono_array_addr (type_args, MonoType*, 0));
5813 context->class_inst = NULL;
5815 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5816 mono_array_addr (method_args, MonoType*, 0));
5818 context->method_inst = NULL;
5821 ICALL_EXPORT MonoType*
5822 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5825 int table = mono_metadata_token_table (token);
5826 int index = mono_metadata_token_index (token);
5827 MonoGenericContext context;
5830 *resolve_error = ResolveTokenError_Other;
5832 /* Validate token */
5833 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5834 (table != MONO_TABLE_TYPESPEC)) {
5835 *resolve_error = ResolveTokenError_BadTable;
5839 if (image_is_dynamic (image)) {
5840 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5841 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5842 return klass ? &klass->byval_arg : NULL;
5845 init_generic_context_from_args (&context, type_args, method_args);
5846 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5847 return klass ? &klass->byval_arg : NULL;
5850 if ((index <= 0) || (index > image->tables [table].rows)) {
5851 *resolve_error = ResolveTokenError_OutOfRange;
5855 init_generic_context_from_args (&context, type_args, method_args);
5856 klass = mono_class_get_checked (image, token, &error);
5858 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5859 if (!mono_error_ok (&error)) {
5860 mono_error_set_pending_exception (&error);
5865 return &klass->byval_arg;
5870 ICALL_EXPORT MonoMethod*
5871 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5874 int table = mono_metadata_token_table (token);
5875 int index = mono_metadata_token_index (token);
5876 MonoGenericContext context;
5879 *resolve_error = ResolveTokenError_Other;
5881 /* Validate token */
5882 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5883 (table != MONO_TABLE_MEMBERREF)) {
5884 *resolve_error = ResolveTokenError_BadTable;
5888 if (image_is_dynamic (image)) {
5889 if (table == MONO_TABLE_METHOD)
5890 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5892 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5893 *resolve_error = ResolveTokenError_BadTable;
5897 init_generic_context_from_args (&context, type_args, method_args);
5898 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5901 if ((index <= 0) || (index > image->tables [table].rows)) {
5902 *resolve_error = ResolveTokenError_OutOfRange;
5905 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5906 *resolve_error = ResolveTokenError_BadTable;
5910 init_generic_context_from_args (&context, type_args, method_args);
5911 method = mono_get_method_checked (image, token, NULL, &context, &error);
5912 mono_error_set_pending_exception (&error);
5917 ICALL_EXPORT MonoString*
5918 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5920 int index = mono_metadata_token_index (token);
5922 *error = ResolveTokenError_Other;
5924 /* Validate token */
5925 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5926 *error = ResolveTokenError_BadTable;
5930 if (image_is_dynamic (image))
5931 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5933 if ((index <= 0) || (index >= image->heap_us.size)) {
5934 *error = ResolveTokenError_OutOfRange;
5938 /* FIXME: What to do if the index points into the middle of a string ? */
5940 return mono_ldstr (mono_domain_get (), image, index);
5943 ICALL_EXPORT MonoClassField*
5944 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5948 int table = mono_metadata_token_table (token);
5949 int index = mono_metadata_token_index (token);
5950 MonoGenericContext context;
5951 MonoClassField *field;
5953 *resolve_error = ResolveTokenError_Other;
5955 /* Validate token */
5956 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5957 *resolve_error = ResolveTokenError_BadTable;
5961 if (image_is_dynamic (image)) {
5962 if (table == MONO_TABLE_FIELD)
5963 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5965 if (mono_memberref_is_method (image, token)) {
5966 *resolve_error = ResolveTokenError_BadTable;
5970 init_generic_context_from_args (&context, type_args, method_args);
5971 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5974 if ((index <= 0) || (index > image->tables [table].rows)) {
5975 *resolve_error = ResolveTokenError_OutOfRange;
5978 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5979 *resolve_error = ResolveTokenError_BadTable;
5983 init_generic_context_from_args (&context, type_args, method_args);
5984 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5985 mono_error_set_pending_exception (&error);
5991 ICALL_EXPORT MonoObject*
5992 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5996 int table = mono_metadata_token_table (token);
5998 *error = ResolveTokenError_Other;
6001 case MONO_TABLE_TYPEDEF:
6002 case MONO_TABLE_TYPEREF:
6003 case MONO_TABLE_TYPESPEC: {
6004 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6006 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6007 mono_error_raise_exception (&merror);
6014 case MONO_TABLE_METHOD:
6015 case MONO_TABLE_METHODSPEC: {
6016 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6018 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6019 mono_error_raise_exception (&merror);
6025 case MONO_TABLE_FIELD: {
6026 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6028 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6029 mono_error_raise_exception (&merror);
6035 case MONO_TABLE_MEMBERREF:
6036 if (mono_memberref_is_method (image, token)) {
6037 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6039 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6040 mono_error_raise_exception (&merror);
6047 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6049 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6050 mono_error_raise_exception (&merror);
6059 *error = ResolveTokenError_BadTable;
6065 ICALL_EXPORT MonoArray*
6066 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
6068 int table = mono_metadata_token_table (token);
6069 int idx = mono_metadata_token_index (token);
6070 MonoTableInfo *tables = image->tables;
6075 *error = ResolveTokenError_OutOfRange;
6077 /* FIXME: Support other tables ? */
6078 if (table != MONO_TABLE_STANDALONESIG)
6081 if (image_is_dynamic (image))
6084 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6087 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6089 ptr = mono_metadata_blob_heap (image, sig);
6090 len = mono_metadata_decode_blob_size (ptr, &ptr);
6092 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
6093 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6097 ICALL_EXPORT MonoReflectionType*
6098 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6101 MonoReflectionType *ret;
6103 int isbyref = 0, rank;
6104 char *str = mono_string_to_utf8 (smodifiers);
6107 klass = mono_class_from_mono_type (tb->type.type);
6109 /* logic taken from mono_reflection_parse_type(): keep in sync */
6113 if (isbyref) { /* only one level allowed by the spec */
6122 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6123 mono_error_raise_exception (&error);
6127 klass = mono_ptr_class_get (&klass->byval_arg);
6128 mono_class_init (klass);
6139 else if (*p != '*') { /* '*' means unknown lower bound */
6150 klass = mono_array_class_get (klass, rank);
6151 mono_class_init (klass);
6160 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6161 mono_error_raise_exception (&error);
6166 ICALL_EXPORT MonoBoolean
6167 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6173 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6179 check_for_invalid_type (MonoClass *klass, MonoError *error)
6184 mono_error_init (error);
6186 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6189 name = mono_type_get_full_name (klass);
6190 str = mono_string_new (mono_domain_get (), name);
6192 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6195 ICALL_EXPORT MonoReflectionType *
6196 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6199 MonoReflectionType *ret;
6200 MonoClass *klass, *aklass;
6202 klass = mono_class_from_mono_type (type->type);
6203 check_for_invalid_type (klass, &error);
6204 mono_error_raise_exception (&error);
6206 if (rank == 0) //single dimentional array
6207 aklass = mono_array_class_get (klass, 1);
6209 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6211 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6212 mono_error_raise_exception (&error);
6217 ICALL_EXPORT MonoReflectionType *
6218 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6221 MonoReflectionType *ret;
6224 klass = mono_class_from_mono_type (type->type);
6225 mono_class_init_checked (klass, &error);
6226 mono_error_raise_exception (&error);
6227 check_for_invalid_type (klass, &error);
6228 mono_error_raise_exception (&error);
6230 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6231 mono_error_raise_exception (&error);
6236 ICALL_EXPORT MonoReflectionType *
6237 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6240 MonoReflectionType *ret;
6241 MonoClass *klass, *pklass;
6243 klass = mono_class_from_mono_type (type->type);
6244 mono_class_init_checked (klass, &error);
6245 mono_error_raise_exception (&error);
6246 check_for_invalid_type (klass, &error);
6247 mono_error_raise_exception (&error);
6249 pklass = mono_ptr_class_get (type->type);
6251 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6252 mono_error_raise_exception (&error);
6257 ICALL_EXPORT MonoObject *
6258 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6259 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6262 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6263 MonoObject *delegate;
6265 MonoMethod *method = info->method;
6267 mono_class_init_checked (delegate_class, &error);
6268 mono_error_raise_exception (&error);
6270 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
6272 if (mono_security_core_clr_enabled ()) {
6273 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6277 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6278 mono_error_raise_exception (&error);
6280 if (method_is_dynamic (method)) {
6281 /* Creating a trampoline would leak memory */
6282 func = mono_compile_method (method);
6284 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6285 method = mono_object_get_virtual_method (target, method);
6286 func = mono_create_ftnptr (mono_domain_get (),
6287 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6290 mono_delegate_ctor_with_method (delegate, target, func, method);
6295 ICALL_EXPORT MonoMulticastDelegate *
6296 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6299 MonoMulticastDelegate *ret;
6301 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6303 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6304 mono_error_raise_exception (&error);
6305 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6310 ICALL_EXPORT MonoReflectionMethod*
6311 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6313 MonoReflectionMethod *ret = NULL;
6315 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6316 mono_error_raise_exception (&error);
6322 static inline gint32
6323 mono_array_get_byte_length (MonoArray *array)
6329 klass = array->obj.vtable->klass;
6331 if (array->bounds == NULL)
6332 length = array->max_length;
6335 for (i = 0; i < klass->rank; ++ i)
6336 length *= array->bounds [i].length;
6339 switch (klass->element_class->byval_arg.type) {
6342 case MONO_TYPE_BOOLEAN:
6346 case MONO_TYPE_CHAR:
6354 return length * sizeof (gpointer);
6365 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6367 return mono_array_get_byte_length (array);
6371 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6373 return mono_array_get (array, gint8, idx);
6377 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6379 mono_array_set (array, gint8, idx, value);
6382 ICALL_EXPORT MonoBoolean
6383 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6385 guint8 *src_buf, *dest_buf;
6388 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6392 g_assert (count >= 0);
6394 /* This is called directly from the class libraries without going through the managed wrapper */
6395 MONO_CHECK_ARG_NULL (src, FALSE);
6396 MONO_CHECK_ARG_NULL (dest, FALSE);
6398 /* watch out for integer overflow */
6399 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6402 src_buf = (guint8 *)src->vector + src_offset;
6403 dest_buf = (guint8 *)dest->vector + dest_offset;
6406 memcpy (dest_buf, src_buf, count);
6408 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6413 #ifndef DISABLE_REMOTING
6414 ICALL_EXPORT MonoObject *
6415 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6418 MonoDomain *domain = mono_object_domain (this_obj);
6420 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6421 MonoTransparentProxy *tp;
6425 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6426 mono_error_raise_exception (&error);
6427 tp = (MonoTransparentProxy*) res;
6429 MONO_OBJECT_SETREF (tp, rp, rp);
6430 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6431 klass = mono_class_from_mono_type (type);
6433 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6434 mono_class_setup_vtable (klass);
6435 if (mono_class_has_failure (klass)) {
6436 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6440 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
6441 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6442 if (!is_ok (&error)) {
6443 mono_error_set_pending_exception (&error);
6447 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6451 ICALL_EXPORT MonoReflectionType *
6452 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6455 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6456 mono_error_raise_exception (&error);
6462 /* System.Environment */
6465 ves_icall_System_Environment_get_UserName (void)
6467 /* using glib is more portable */
6468 return mono_string_new (mono_domain_get (), g_get_user_name ());
6472 ICALL_EXPORT MonoString *
6473 ves_icall_System_Environment_get_MachineName (void)
6475 #if defined (HOST_WIN32)
6480 len = MAX_COMPUTERNAME_LENGTH + 1;
6481 buf = g_new (gunichar2, len);
6484 if (GetComputerName (buf, (PDWORD) &len)) {
6486 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6487 mono_error_raise_exception (&error);
6492 #elif !defined(DISABLE_SOCKETS)
6496 #if defined _SC_HOST_NAME_MAX
6497 n = sysconf (_SC_HOST_NAME_MAX);
6501 buf = g_malloc (n+1);
6503 if (gethostname (buf, n) == 0){
6505 result = mono_string_new (mono_domain_get (), buf);
6512 return mono_string_new (mono_domain_get (), "mono");
6517 ves_icall_System_Environment_get_Platform (void)
6519 #if defined (TARGET_WIN32)
6522 #elif defined(__MACH__)
6525 // Notice that the value is hidden from user code, and only exposed
6526 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6527 // define and making assumptions based on Unix/128/4 values before there
6528 // was a MacOS define. Lots of code would assume that not-Unix meant
6529 // Windows, but in this case, it would be OSX.
6538 ICALL_EXPORT MonoString *
6539 ves_icall_System_Environment_get_NewLine (void)
6541 #if defined (HOST_WIN32)
6542 return mono_string_new (mono_domain_get (), "\r\n");
6544 return mono_string_new (mono_domain_get (), "\n");
6548 ICALL_EXPORT MonoBoolean
6549 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6551 #if SIZEOF_VOID_P == 8
6555 gboolean isWow64Process = FALSE;
6556 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6557 return (MonoBoolean)isWow64Process;
6559 #elif defined(HAVE_SYS_UTSNAME_H)
6560 struct utsname name;
6562 if (uname (&name) >= 0) {
6563 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6570 ICALL_EXPORT MonoString *
6571 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6579 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6580 value = g_getenv (utf8_name);
6587 return mono_string_new (mono_domain_get (), value);
6591 * There is no standard way to get at environ.
6594 #ifndef __MINGW32_VERSION
6595 #if defined(__APPLE__)
6596 #if defined (TARGET_OSX)
6597 /* Apple defines this in crt_externs.h but doesn't provide that header for
6598 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6599 * in fact exist on all implementations (so far)
6601 gchar ***_NSGetEnviron(void);
6602 #define environ (*_NSGetEnviron())
6604 static char *mono_environ[1] = { NULL };
6605 #define environ mono_environ
6606 #endif /* defined (TARGET_OSX) */
6614 ICALL_EXPORT MonoArray *
6615 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6626 env_strings = GetEnvironmentStrings();
6629 env_string = env_strings;
6630 while (*env_string != '\0') {
6631 /* weird case that MS seems to skip */
6632 if (*env_string != '=')
6634 while (*env_string != '\0')
6640 domain = mono_domain_get ();
6641 names = mono_array_new (domain, mono_defaults.string_class, n);
6645 env_string = env_strings;
6646 while (*env_string != '\0') {
6647 /* weird case that MS seems to skip */
6648 if (*env_string != '=') {
6649 equal_str = wcschr(env_string, '=');
6650 g_assert(equal_str);
6652 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6653 mono_error_raise_exception (&error);
6654 mono_array_setref (names, n, str);
6657 while (*env_string != '\0')
6662 FreeEnvironmentStrings (env_strings);
6675 for (e = environ; *e != 0; ++ e)
6678 domain = mono_domain_get ();
6679 names = mono_array_new (domain, mono_defaults.string_class, n);
6682 for (e = environ; *e != 0; ++ e) {
6683 parts = g_strsplit (*e, "=", 2);
6685 str = mono_string_new (domain, *parts);
6686 mono_array_setref (names, n, str);
6699 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6701 #if !GLIB_CHECK_VERSION(2,4,0)
6702 #define g_setenv(a,b,c) setenv(a,b,c)
6703 #define g_unsetenv(a) unsetenv(a)
6707 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6710 gunichar2 *utf16_name, *utf16_value;
6712 gchar *utf8_name, *utf8_value;
6717 utf16_name = mono_string_to_utf16 (name);
6718 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6719 SetEnvironmentVariable (utf16_name, NULL);
6720 g_free (utf16_name);
6724 utf16_value = mono_string_to_utf16 (value);
6726 SetEnvironmentVariable (utf16_name, utf16_value);
6728 g_free (utf16_name);
6729 g_free (utf16_value);
6731 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6733 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6734 g_unsetenv (utf8_name);
6739 utf8_value = mono_string_to_utf8_checked (value, &error);
6740 if (!mono_error_ok (&error)) {
6742 mono_error_set_pending_exception (&error);
6745 g_setenv (utf8_name, utf8_value, TRUE);
6748 g_free (utf8_value);
6753 ves_icall_System_Environment_Exit (int result)
6755 mono_environment_exitcode_set (result);
6757 /* FIXME: There are some cleanup hangs that should be worked out, but
6758 * if the program is going to exit, everything will be cleaned up when
6759 * NaCl exits anyway.
6761 #ifndef __native_client__
6762 if (!mono_runtime_try_shutdown ())
6763 mono_thread_exit ();
6765 /* Suspend all managed threads since the runtime is going away */
6766 mono_thread_suspend_all_other_threads ();
6768 mono_runtime_quit ();
6771 /* we may need to do some cleanup here... */
6775 ICALL_EXPORT MonoString*
6776 ves_icall_System_Environment_GetGacPath (void)
6778 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6781 ICALL_EXPORT MonoString*
6782 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6784 #if defined (HOST_WIN32)
6785 #ifndef CSIDL_FLAG_CREATE
6786 #define CSIDL_FLAG_CREATE 0x8000
6789 WCHAR path [MAX_PATH];
6790 /* Create directory if no existing */
6791 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6796 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6797 mono_error_raise_exception (&error);
6801 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6803 return mono_string_new (mono_domain_get (), "");
6806 ICALL_EXPORT MonoArray *
6807 ves_icall_System_Environment_GetLogicalDrives (void)
6810 gunichar2 buf [256], *ptr, *dname;
6812 guint initial_size = 127, size = 128;
6815 MonoString *drivestr;
6816 MonoDomain *domain = mono_domain_get ();
6822 while (size > initial_size) {
6823 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6824 if (size > initial_size) {
6827 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6828 initial_size = size;
6842 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6847 while (*u16) { u16++; len ++; }
6848 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6849 mono_error_raise_exception (&error);
6850 mono_array_setref (result, ndrives++, drivestr);
6860 ICALL_EXPORT MonoString *
6861 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6863 gunichar2 volume_name [MAX_PATH + 1];
6865 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6867 return mono_string_from_utf16 (volume_name);
6870 ICALL_EXPORT MonoString *
6871 ves_icall_System_Environment_InternalGetHome (void)
6873 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6876 static const char *encodings [] = {
6878 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6879 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6880 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6882 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6883 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6884 "x_unicode_2_0_utf_7",
6886 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6887 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6889 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6892 "unicodefffe", "utf_16be",
6899 * Returns the internal codepage, if the value of "int_code_page" is
6900 * 1 at entry, and we can not compute a suitable code page number,
6901 * returns the code page as a string
6903 ICALL_EXPORT MonoString*
6904 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6909 char *codepage = NULL;
6911 int want_name = *int_code_page;
6914 *int_code_page = -1;
6916 g_get_charset (&cset);
6917 c = codepage = strdup (cset);
6918 for (c = codepage; *c; c++){
6919 if (isascii (*c) && isalpha (*c))
6924 /* g_print ("charset: %s\n", cset); */
6926 /* handle some common aliases */
6929 for (i = 0; p != 0; ){
6932 p = encodings [++i];
6935 if (strcmp (p, codepage) == 0){
6936 *int_code_page = code;
6939 p = encodings [++i];
6942 if (strstr (codepage, "utf_8") != NULL)
6943 *int_code_page |= 0x10000000;
6946 if (want_name && *int_code_page == -1)
6947 return mono_string_new (mono_domain_get (), cset);
6952 ICALL_EXPORT MonoBoolean
6953 ves_icall_System_Environment_get_HasShutdownStarted (void)
6955 if (mono_runtime_is_shutting_down ())
6958 if (mono_domain_is_unloading (mono_domain_get ()))
6965 ves_icall_System_Environment_BroadcastSettingChange (void)
6968 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6973 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6979 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6980 MonoReflectionMethod *method,
6981 MonoArray *out_args)
6983 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6986 #ifndef DISABLE_REMOTING
6987 ICALL_EXPORT MonoBoolean
6988 ves_icall_IsTransparentProxy (MonoObject *proxy)
6993 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6999 ICALL_EXPORT MonoReflectionMethod *
7000 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7001 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7003 MonoReflectionMethod *ret = NULL;
7008 MonoMethod **vtable;
7009 MonoMethod *res = NULL;
7011 MONO_CHECK_ARG_NULL (rtype, NULL);
7012 MONO_CHECK_ARG_NULL (rmethod, NULL);
7014 method = rmethod->method;
7015 klass = mono_class_from_mono_type (rtype->type);
7016 mono_class_init_checked (klass, &error);
7017 mono_error_raise_exception (&error);
7019 if (MONO_CLASS_IS_INTERFACE (klass))
7022 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7025 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7026 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7032 mono_class_setup_vtable (klass);
7033 vtable = klass->vtable;
7035 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7036 gboolean variance_used = FALSE;
7037 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7038 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7040 res = vtable [offs + method->slot];
7042 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7045 if (method->slot != -1)
7046 res = vtable [method->slot];
7052 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7053 mono_error_raise_exception (&error);
7058 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7064 klass = mono_class_from_mono_type (type->type);
7065 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7066 if (!is_ok (&error)) {
7067 mono_error_set_pending_exception (&error);
7071 mono_vtable_set_is_remote (vtable, enable);
7074 #else /* DISABLE_REMOTING */
7077 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7079 g_assert_not_reached ();
7084 ICALL_EXPORT MonoObject *
7085 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7092 domain = mono_object_domain (type);
7093 klass = mono_class_from_mono_type (type->type);
7094 mono_class_init_checked (klass, &error);
7095 mono_error_raise_exception (&error);
7097 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7098 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7102 if (klass->rank >= 1) {
7103 g_assert (klass->rank == 1);
7104 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7106 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7107 if (!is_ok (&error)) {
7108 mono_error_set_pending_exception (&error);
7111 /* Bypass remoting object creation check */
7112 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7113 mono_error_set_pending_exception (&error);
7119 ICALL_EXPORT MonoString *
7120 ves_icall_System_IO_get_temp_path (void)
7122 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7125 #ifndef PLATFORM_NO_DRIVEINFO
7126 ICALL_EXPORT MonoBoolean
7127 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7128 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7132 ULARGE_INTEGER wapi_free_bytes_avail;
7133 ULARGE_INTEGER wapi_total_number_of_bytes;
7134 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7136 *error = ERROR_SUCCESS;
7137 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7138 &wapi_total_number_of_free_bytes);
7141 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7142 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7143 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7145 *free_bytes_avail = 0;
7146 *total_number_of_bytes = 0;
7147 *total_number_of_free_bytes = 0;
7148 *error = GetLastError ();
7154 ICALL_EXPORT guint32
7155 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7157 return GetDriveType (mono_string_chars (root_path_name));
7161 ICALL_EXPORT gpointer
7162 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7164 return mono_compile_method (method);
7167 ICALL_EXPORT MonoString *
7168 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7173 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7175 #if defined (HOST_WIN32)
7176 /* Avoid mixing '/' and '\\' */
7179 for (i = strlen (path) - 1; i >= 0; i--)
7180 if (path [i] == '/')
7184 mcpath = mono_string_new (mono_domain_get (), path);
7191 get_bundled_app_config (void)
7193 const gchar *app_config;
7196 gchar *config_file_name, *config_file_path;
7197 gsize len, config_file_path_length, config_ext_length;
7200 domain = mono_domain_get ();
7201 file = domain->setup->configuration_file;
7202 if (!file || file->length == 0)
7205 // Retrieve config file and remove the extension
7206 config_file_name = mono_string_to_utf8 (file);
7207 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7208 if (!config_file_path)
7209 config_file_path = config_file_name;
7211 config_file_path_length = strlen (config_file_path);
7212 config_ext_length = strlen (".config");
7213 if (config_file_path_length <= config_ext_length)
7216 len = config_file_path_length - config_ext_length;
7217 module = (gchar *)g_malloc0 (len + 1);
7218 memcpy (module, config_file_path, len);
7219 // Get the config file from the module name
7220 app_config = mono_config_string_for_assembly_file (module);
7223 if (config_file_name != config_file_path)
7224 g_free (config_file_name);
7225 g_free (config_file_path);
7230 return mono_string_new (mono_domain_get (), app_config);
7234 get_bundled_machine_config (void)
7236 const gchar *machine_config;
7238 machine_config = mono_get_machine_config ();
7240 if (!machine_config)
7243 return mono_string_new (mono_domain_get (), machine_config);
7246 ICALL_EXPORT MonoString *
7247 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7252 path = g_path_get_dirname (mono_get_config_dir ());
7254 #if defined (HOST_WIN32)
7255 /* Avoid mixing '/' and '\\' */
7258 for (i = strlen (path) - 1; i >= 0; i--)
7259 if (path [i] == '/')
7263 ipath = mono_string_new (mono_domain_get (), path);
7269 ICALL_EXPORT gboolean
7270 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7272 MonoPEResourceDataEntry *entry;
7275 if (!assembly || !result || !size)
7280 image = assembly->assembly->image;
7281 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7285 *result = mono_image_rva_map (image, entry->rde_data_offset);
7290 *size = entry->rde_size;
7295 ICALL_EXPORT MonoBoolean
7296 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7298 return mono_is_debugger_attached ();
7301 ICALL_EXPORT MonoBoolean
7302 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7304 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7305 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7311 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7313 if (mono_get_runtime_callbacks ()->debug_log)
7314 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7318 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7320 #if defined (HOST_WIN32)
7321 OutputDebugString (mono_string_chars (message));
7323 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7327 /* Only used for value types */
7328 ICALL_EXPORT MonoObject *
7329 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7336 domain = mono_object_domain (type);
7337 klass = mono_class_from_mono_type (type->type);
7338 mono_class_init_checked (klass, &error);
7339 mono_error_raise_exception (&error);
7341 if (mono_class_is_nullable (klass))
7342 /* No arguments -> null */
7345 result = mono_object_new_checked (domain, klass, &error);
7346 mono_error_raise_exception (&error);
7350 ICALL_EXPORT MonoReflectionMethod *
7351 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7353 MonoReflectionMethod *ret = NULL;
7356 MonoClass *klass, *parent;
7357 MonoGenericContext *generic_inst = NULL;
7358 MonoMethod *method = m->method;
7359 MonoMethod *result = NULL;
7362 if (method->klass == NULL)
7365 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7366 MONO_CLASS_IS_INTERFACE (method->klass) ||
7367 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7370 slot = mono_method_get_vtable_slot (method);
7374 klass = method->klass;
7375 if (klass->generic_class) {
7376 generic_inst = mono_class_get_context (klass);
7377 klass = klass->generic_class->container_class;
7381 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7382 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7383 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7384 or klass is the generic container class and generic_inst is the instantiation.
7386 when we go to the parent, if the parent is an open constructed type, we need to
7387 replace the type parameters by the definitions from the generic_inst, and then take it
7388 apart again into the klass and the generic_inst.
7390 For cases like this:
7391 class C<T> : B<T, int> {
7392 public override void Foo () { ... }
7394 class B<U,V> : A<HashMap<U,V>> {
7395 public override void Foo () { ... }
7398 public virtual void Foo () { ... }
7401 if at each iteration the parent isn't open, we can skip inflating it. if at some
7402 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7405 MonoGenericContext *parent_inst = NULL;
7406 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7408 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7409 if (!mono_error_ok (&error)) {
7410 mono_error_set_pending_exception (&error);
7414 if (parent->generic_class) {
7415 parent_inst = mono_class_get_context (parent);
7416 parent = parent->generic_class->container_class;
7419 mono_class_setup_vtable (parent);
7420 if (parent->vtable_size <= slot)
7423 generic_inst = parent_inst;
7426 klass = klass->parent;
7429 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7430 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7431 if (!mono_error_ok (&error)) {
7432 mono_error_set_pending_exception (&error);
7436 generic_inst = NULL;
7438 if (klass->generic_class) {
7439 generic_inst = mono_class_get_context (klass);
7440 klass = klass->generic_class->container_class;
7446 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7447 if (!mono_error_ok (&error)) {
7448 mono_error_set_pending_exception (&error);
7453 if (klass == method->klass)
7456 /*This is possible if definition == FALSE.
7457 * Do it here to be really sure we don't read invalid memory.
7459 if (slot >= klass->vtable_size)
7462 mono_class_setup_vtable (klass);
7464 result = klass->vtable [slot];
7465 if (result == NULL) {
7466 /* It is an abstract method */
7467 gpointer iter = NULL;
7468 while ((result = mono_class_get_methods (klass, &iter)))
7469 if (result->slot == slot)
7476 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7477 mono_error_raise_exception (&error);
7481 ICALL_EXPORT MonoString*
7482 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7484 MonoMethod *method = m->method;
7486 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7491 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7493 iter->sig = *(MonoMethodSignature**)argsp;
7495 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7496 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7499 /* FIXME: it's not documented what start is exactly... */
7503 iter->args = argsp + sizeof (gpointer);
7505 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7507 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7510 ICALL_EXPORT MonoTypedRef
7511 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7513 guint32 i, arg_size;
7517 i = iter->sig->sentinelpos + iter->next_arg;
7519 g_assert (i < iter->sig->param_count);
7521 res.type = iter->sig->params [i];
7522 res.klass = mono_class_from_mono_type (res.type);
7523 arg_size = mono_type_stack_size (res.type, &align);
7524 #if defined(__arm__) || defined(__mips__)
7525 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7527 res.value = iter->args;
7528 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7529 /* Values are stored as 8 byte register sized objects, but 'value'
7530 * is dereferenced as a pointer in other routines.
7532 res.value = (char*)res.value + 4;
7534 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7535 if (arg_size <= sizeof (gpointer)) {
7537 int padding = arg_size - mono_type_size (res.type, &dummy);
7538 res.value = (guint8*)res.value + padding;
7541 iter->args = (char*)iter->args + arg_size;
7544 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7549 ICALL_EXPORT MonoTypedRef
7550 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7552 guint32 i, arg_size;
7556 i = iter->sig->sentinelpos + iter->next_arg;
7558 g_assert (i < iter->sig->param_count);
7560 while (i < iter->sig->param_count) {
7561 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7563 res.type = iter->sig->params [i];
7564 res.klass = mono_class_from_mono_type (res.type);
7565 /* FIXME: endianess issue... */
7566 arg_size = mono_type_stack_size (res.type, &align);
7567 #if defined(__arm__) || defined(__mips__)
7568 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7570 res.value = iter->args;
7571 iter->args = (char*)iter->args + arg_size;
7573 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7576 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7584 ICALL_EXPORT MonoType*
7585 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7589 i = iter->sig->sentinelpos + iter->next_arg;
7591 g_assert (i < iter->sig->param_count);
7593 return iter->sig->params [i];
7596 ICALL_EXPORT MonoObject*
7597 mono_TypedReference_ToObject (MonoTypedRef* tref)
7599 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7600 MonoObject** objp = (MonoObject **)tref->value;
7604 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
7607 ICALL_EXPORT MonoTypedRef
7608 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7611 MonoReflectionField *f;
7613 MonoType *ftype = NULL;
7617 memset (&res, 0, sizeof (res));
7620 g_assert (mono_array_length (fields) > 0);
7622 klass = target->vtable->klass;
7624 for (i = 0; i < mono_array_length (fields); ++i) {
7625 f = mono_array_get (fields, MonoReflectionField*, i);
7627 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7630 if (f->field->parent != klass) {
7631 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7635 p = (guint8*)target + f->field->offset;
7637 p += f->field->offset - sizeof (MonoObject);
7638 klass = mono_class_from_mono_type (f->field->type);
7639 ftype = f->field->type;
7643 res.klass = mono_class_from_mono_type (ftype);
7650 prelink_method (MonoMethod *method, MonoError *error)
7652 const char *exc_class, *exc_arg;
7654 mono_error_init (error);
7655 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7657 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7659 mono_error_set_exception_instance (error,
7660 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7663 /* create the wrapper, too? */
7667 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7671 prelink_method (method->method, &error);
7672 mono_error_raise_exception (&error);
7676 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7679 MonoClass *klass = mono_class_from_mono_type (type->type);
7681 gpointer iter = NULL;
7683 mono_class_init_checked (klass, &error);
7684 mono_error_raise_exception (&error);
7686 while ((m = mono_class_get_methods (klass, &iter))) {
7687 prelink_method (m, &error);
7688 mono_error_raise_exception (&error);
7692 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7694 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7695 gint32 const **exponents,
7696 gunichar2 const **digitLowerTable,
7697 gunichar2 const **digitUpperTable,
7698 gint64 const **tenPowersList,
7699 gint32 const **decHexDigits)
7701 *mantissas = Formatter_MantissaBitsTable;
7702 *exponents = Formatter_TensExponentTable;
7703 *digitLowerTable = Formatter_DigitLowerTable;
7704 *digitUpperTable = Formatter_DigitUpperTable;
7705 *tenPowersList = Formatter_TenPowersList;
7706 *decHexDigits = Formatter_DecHexDigits;
7710 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7711 * and avoid useless allocations.
7714 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7716 MonoReflectionType *rt;
7720 mono_error_init (error);
7721 for (i = 0; i < type->num_mods; ++i) {
7722 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7727 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7729 for (i = 0; i < type->num_mods; ++i) {
7730 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7731 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7732 return_val_if_nok (error, NULL);
7734 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7735 return_val_if_nok (error, NULL);
7737 mono_array_setref (res, count, rt);
7744 ICALL_EXPORT MonoArray*
7745 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7748 MonoType *type = param->ClassImpl->type;
7749 MonoClass *member_class = mono_object_class (param->MemberImpl);
7750 MonoMethod *method = NULL;
7753 MonoMethodSignature *sig;
7756 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7757 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7758 method = rmethod->method;
7759 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7760 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7761 if (!(method = prop->property->get))
7762 method = prop->property->set;
7765 char *type_name = mono_type_get_full_name (member_class);
7766 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7767 MonoException *ex = mono_get_exception_not_supported (msg);
7770 mono_set_pending_exception (ex);
7774 image = method->klass->image;
7775 pos = param->PositionImpl;
7776 sig = mono_method_signature (method);
7780 type = sig->params [pos];
7782 res = type_array_from_modifiers (image, type, optional, &error);
7783 mono_error_raise_exception (&error);
7788 get_property_type (MonoProperty *prop)
7790 MonoMethodSignature *sig;
7792 sig = mono_method_signature (prop->get);
7794 } else if (prop->set) {
7795 sig = mono_method_signature (prop->set);
7796 return sig->params [sig->param_count - 1];
7801 ICALL_EXPORT MonoArray*
7802 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7805 MonoType *type = get_property_type (property->property);
7806 MonoImage *image = property->klass->image;
7811 res = type_array_from_modifiers (image, type, optional, &error);
7812 mono_error_raise_exception (&error);
7817 *Construct a MonoType suited to be used to decode a constant blob object.
7819 * @type is the target type which will be constructed
7820 * @blob_type is the blob type, for example, that comes from the constant table
7821 * @real_type is the expected constructed type.
7824 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7826 type->type = blob_type;
7827 type->data.klass = NULL;
7828 if (blob_type == MONO_TYPE_CLASS)
7829 type->data.klass = mono_defaults.object_class;
7830 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7831 /* For enums, we need to use the base type */
7832 type->type = MONO_TYPE_VALUETYPE;
7833 type->data.klass = mono_class_from_mono_type (real_type);
7835 type->data.klass = mono_class_from_mono_type (real_type);
7838 ICALL_EXPORT MonoObject*
7839 property_info_get_default_value (MonoReflectionProperty *property)
7843 MonoProperty *prop = property->property;
7844 MonoType *type = get_property_type (prop);
7845 MonoDomain *domain = mono_object_domain (property);
7846 MonoTypeEnum def_type;
7847 const char *def_value;
7850 mono_class_init (prop->parent);
7852 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7853 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7857 def_value = mono_class_get_property_default_value (prop, &def_type);
7859 mono_type_from_blob_type (&blob_type, def_type, type);
7860 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7862 mono_error_set_pending_exception (&error);
7866 ICALL_EXPORT MonoBoolean
7867 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7870 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7871 MonoCustomAttrInfo *cinfo;
7874 mono_class_init_checked (attr_class, &error);
7875 mono_error_raise_exception (&error);
7877 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7878 if (!is_ok (&error)) {
7879 mono_error_set_pending_exception (&error);
7884 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7886 mono_custom_attrs_free (cinfo);
7890 ICALL_EXPORT MonoArray*
7891 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7893 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7898 mono_class_init_checked (attr_class, &error);
7899 mono_error_raise_exception (&error);
7902 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7903 if (!mono_error_ok (&error)) {
7904 mono_error_set_pending_exception (&error);
7908 if (mono_loader_get_last_error ()) {
7909 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7916 ICALL_EXPORT MonoArray*
7917 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7921 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7922 mono_error_set_pending_exception (&error);
7927 ICALL_EXPORT MonoString*
7928 ves_icall_Mono_Runtime_GetDisplayName (void)
7931 MonoString *display_name;
7933 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7934 display_name = mono_string_new (mono_domain_get (), info);
7936 return display_name;
7939 ICALL_EXPORT MonoString*
7940 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7943 MonoString *message;
7947 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7948 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7951 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7953 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7954 mono_error_raise_exception (&error);
7961 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7964 char *path_str = mono_string_to_utf8 (path);
7966 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7974 ICALL_EXPORT gpointer
7975 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
7977 return GetCurrentProcess ();
7980 ICALL_EXPORT MonoBoolean
7981 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
7983 return GetExitCodeProcess (handle, (guint32*) exitcode);
7986 ICALL_EXPORT MonoBoolean
7987 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
7989 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
7990 return CloseHandle (handle);
7992 return CloseProcess (handle);
7996 ICALL_EXPORT MonoBoolean
7997 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
7999 return TerminateProcess (handle, exitcode);
8003 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8005 return WaitForInputIdle (handle, milliseconds);
8008 ICALL_EXPORT MonoBoolean
8009 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8011 return GetProcessWorkingSetSize (handle, min, max);
8014 ICALL_EXPORT MonoBoolean
8015 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8017 return SetProcessWorkingSetSize (handle, min, max);
8020 ICALL_EXPORT MonoBoolean
8021 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8023 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8027 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8029 return mono_process_current_pid ();
8033 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8035 return GetPriorityClass (handle);
8038 ICALL_EXPORT MonoBoolean
8039 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8041 return SetPriorityClass (handle, priorityClass);
8044 #ifndef DISABLE_ICALL_TABLES
8046 #define ICALL_TYPE(id,name,first)
8047 #define ICALL(id,name,func) Icall_ ## id,
8050 #include "metadata/icall-def.h"
8056 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8057 #define ICALL(id,name,func)
8059 #include "metadata/icall-def.h"
8065 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8066 #define ICALL(id,name,func)
8068 guint16 first_icall;
8071 static const IcallTypeDesc
8072 icall_type_descs [] = {
8073 #include "metadata/icall-def.h"
8077 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8080 #define ICALL_TYPE(id,name,first)
8083 #ifdef HAVE_ARRAY_ELEM_INIT
8084 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8085 #define MSGSTRFIELD1(line) str##line
8087 static const struct msgstrtn_t {
8088 #define ICALL(id,name,func)
8090 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8091 #include "metadata/icall-def.h"
8093 } icall_type_names_str = {
8094 #define ICALL_TYPE(id,name,first) (name),
8095 #include "metadata/icall-def.h"
8098 static const guint16 icall_type_names_idx [] = {
8099 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8100 #include "metadata/icall-def.h"
8103 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8105 static const struct msgstr_t {
8107 #define ICALL_TYPE(id,name,first)
8108 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8109 #include "metadata/icall-def.h"
8111 } icall_names_str = {
8112 #define ICALL(id,name,func) (name),
8113 #include "metadata/icall-def.h"
8116 static const guint16 icall_names_idx [] = {
8117 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8118 #include "metadata/icall-def.h"
8121 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8127 #define ICALL_TYPE(id,name,first) name,
8128 #define ICALL(id,name,func)
8129 static const char* const
8130 icall_type_names [] = {
8131 #include "metadata/icall-def.h"
8135 #define icall_type_name_get(id) (icall_type_names [(id)])
8139 #define ICALL_TYPE(id,name,first)
8140 #define ICALL(id,name,func) name,
8141 static const char* const
8143 #include "metadata/icall-def.h"
8146 #define icall_name_get(id) icall_names [(id)]
8148 #endif /* !HAVE_ARRAY_ELEM_INIT */
8152 #define ICALL_TYPE(id,name,first)
8153 #define ICALL(id,name,func) func,
8154 static const gconstpointer
8155 icall_functions [] = {
8156 #include "metadata/icall-def.h"
8160 #ifdef ENABLE_ICALL_SYMBOL_MAP
8163 #define ICALL_TYPE(id,name,first)
8164 #define ICALL(id,name,func) #func,
8165 static const gconstpointer
8166 icall_symbols [] = {
8167 #include "metadata/icall-def.h"
8172 #endif /* DISABLE_ICALL_TABLES */
8174 static mono_mutex_t icall_mutex;
8175 static GHashTable *icall_hash = NULL;
8176 static GHashTable *jit_icall_hash_name = NULL;
8177 static GHashTable *jit_icall_hash_addr = NULL;
8180 mono_icall_init (void)
8182 #ifndef DISABLE_ICALL_TABLES
8185 /* check that tables are sorted: disable in release */
8188 const char *prev_class = NULL;
8189 const char *prev_method;
8191 for (i = 0; i < Icall_type_num; ++i) {
8192 const IcallTypeDesc *desc;
8195 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8196 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8197 prev_class = icall_type_name_get (i);
8198 desc = &icall_type_descs [i];
8199 num_icalls = icall_desc_num_icalls (desc);
8200 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8201 for (j = 0; j < num_icalls; ++j) {
8202 const char *methodn = icall_name_get (desc->first_icall + j);
8203 if (prev_method && strcmp (prev_method, methodn) >= 0)
8204 g_print ("method %s should come before method %s\n", methodn, prev_method);
8205 prev_method = methodn;
8211 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8212 mono_os_mutex_init (&icall_mutex);
8216 mono_icall_lock (void)
8218 mono_locks_os_acquire (&icall_mutex, IcallLock);
8222 mono_icall_unlock (void)
8224 mono_locks_os_release (&icall_mutex, IcallLock);
8228 mono_icall_cleanup (void)
8230 g_hash_table_destroy (icall_hash);
8231 g_hash_table_destroy (jit_icall_hash_name);
8232 g_hash_table_destroy (jit_icall_hash_addr);
8233 mono_os_mutex_destroy (&icall_mutex);
8237 * mono_add_internal_call:
8238 * @name: method specification to surface to the managed world
8239 * @method: pointer to a C method to invoke when the method is called
8241 * This method surfaces the C function pointed by @method as a method
8242 * that has been surfaced in managed code with the method specified in
8243 * @name as an internal call.
8245 * Internal calls are surfaced to all app domains loaded and they are
8246 * accessibly by a type with the specified name.
8248 * You must provide a fully qualified type name, that is namespaces
8249 * and type name, followed by a colon and the method name, with an
8250 * optional signature to bind.
8252 * For example, the following are all valid declarations:
8254 * "MyApp.Services.ScriptService:Accelerate"
8255 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8257 * You use method parameters in cases where there might be more than
8258 * one surface method to managed code. That way you can register different
8259 * internal calls for different method overloads.
8261 * The internal calls are invoked with no marshalling. This means that .NET
8262 * types like System.String are exposed as `MonoString *` parameters. This is
8263 * different than the way that strings are surfaced in P/Invoke.
8265 * For more information on how the parameters are marshalled, see the
8266 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8269 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8270 * reference for more information on the format of method descriptions.
8273 mono_add_internal_call (const char *name, gconstpointer method)
8277 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8279 mono_icall_unlock ();
8282 #ifndef DISABLE_ICALL_TABLES
8284 #ifdef HAVE_ARRAY_ELEM_INIT
8286 compare_method_imap (const void *key, const void *elem)
8288 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8289 return strcmp (key, method_name);
8293 find_method_icall (const IcallTypeDesc *imap, const char *name)
8295 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);
8298 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8302 compare_class_imap (const void *key, const void *elem)
8304 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8305 return strcmp (key, class_name);
8308 static const IcallTypeDesc*
8309 find_class_icalls (const char *name)
8311 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);
8314 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8317 #else /* HAVE_ARRAY_ELEM_INIT */
8320 compare_method_imap (const void *key, const void *elem)
8322 const char** method_name = (const char**)elem;
8323 return strcmp (key, *method_name);
8327 find_method_icall (const IcallTypeDesc *imap, const char *name)
8329 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8332 return (gpointer)icall_functions [(nameslot - icall_names)];
8336 compare_class_imap (const void *key, const void *elem)
8338 const char** class_name = (const char**)elem;
8339 return strcmp (key, *class_name);
8342 static const IcallTypeDesc*
8343 find_class_icalls (const char *name)
8345 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8348 return &icall_type_descs [nameslot - icall_type_names];
8351 #endif /* HAVE_ARRAY_ELEM_INIT */
8353 #endif /* DISABLE_ICALL_TABLES */
8356 * we should probably export this as an helper (handle nested types).
8357 * Returns the number of chars written in buf.
8360 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8362 int nspacelen, cnamelen;
8363 nspacelen = strlen (klass->name_space);
8364 cnamelen = strlen (klass->name);
8365 if (nspacelen + cnamelen + 2 > bufsize)
8368 memcpy (buf, klass->name_space, nspacelen);
8369 buf [nspacelen ++] = '.';
8371 memcpy (buf + nspacelen, klass->name, cnamelen);
8372 buf [nspacelen + cnamelen] = 0;
8373 return nspacelen + cnamelen;
8376 #ifdef DISABLE_ICALL_TABLES
8378 no_icall_table (void)
8380 g_assert_not_reached ();
8385 mono_lookup_internal_call (MonoMethod *method)
8390 int typelen = 0, mlen, siglen;
8392 #ifndef DISABLE_ICALL_TABLES
8393 const IcallTypeDesc *imap = NULL;
8396 g_assert (method != NULL);
8398 if (method->is_inflated)
8399 method = ((MonoMethodInflated *) method)->declaring;
8401 if (method->klass->nested_in) {
8402 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8406 mname [pos++] = '/';
8409 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8415 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8420 #ifndef DISABLE_ICALL_TABLES
8421 imap = find_class_icalls (mname);
8424 mname [typelen] = ':';
8425 mname [typelen + 1] = ':';
8427 mlen = strlen (method->name);
8428 memcpy (mname + typelen + 2, method->name, mlen);
8429 sigstart = mname + typelen + 2 + mlen;
8432 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8433 siglen = strlen (tmpsig);
8434 if (typelen + mlen + siglen + 6 > sizeof (mname))
8437 memcpy (sigstart + 1, tmpsig, siglen);
8438 sigstart [siglen + 1] = ')';
8439 sigstart [siglen + 2] = 0;
8444 res = g_hash_table_lookup (icall_hash, mname);
8446 mono_icall_unlock ();;
8449 /* try without signature */
8451 res = g_hash_table_lookup (icall_hash, mname);
8453 mono_icall_unlock ();
8457 #ifdef DISABLE_ICALL_TABLES
8458 mono_icall_unlock ();
8459 /* Fail only when the result is actually used */
8460 /* mono_marshal_get_native_wrapper () depends on this */
8461 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8462 return ves_icall_System_String_ctor_RedirectToCreateString;
8464 return no_icall_table;
8466 /* it wasn't found in the static call tables */
8468 mono_icall_unlock ();
8471 res = find_method_icall (imap, sigstart - mlen);
8473 mono_icall_unlock ();
8476 /* try _with_ signature */
8478 res = find_method_icall (imap, sigstart - mlen);
8480 mono_icall_unlock ();
8484 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8485 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8486 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8487 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8488 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");
8489 g_print ("If you see other errors or faults after this message they are probably related\n");
8490 g_print ("and you need to fix your mono install first.\n");
8492 mono_icall_unlock ();
8498 #ifdef ENABLE_ICALL_SYMBOL_MAP
8500 func_cmp (gconstpointer key, gconstpointer p)
8502 return (gsize)key - (gsize)*(gsize*)p;
8507 * mono_lookup_icall_symbol:
8509 * Given the icall METHOD, returns its C symbol.
8512 mono_lookup_icall_symbol (MonoMethod *m)
8514 #ifdef DISABLE_ICALL_TABLES
8515 g_assert_not_reached ();
8518 #ifdef ENABLE_ICALL_SYMBOL_MAP
8522 static gconstpointer *functions_sorted;
8523 static const char**symbols_sorted;
8524 static gboolean inited;
8529 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8530 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8531 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8532 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8533 /* Bubble sort the two arrays */
8537 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8538 if (functions_sorted [i] > functions_sorted [i + 1]) {
8541 tmp = functions_sorted [i];
8542 functions_sorted [i] = functions_sorted [i + 1];
8543 functions_sorted [i + 1] = tmp;
8544 tmp = symbols_sorted [i];
8545 symbols_sorted [i] = symbols_sorted [i + 1];
8546 symbols_sorted [i + 1] = tmp;
8553 func = mono_lookup_internal_call (m);
8556 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8560 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8562 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8563 g_assert_not_reached ();
8570 type_from_typename (char *type_name)
8572 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8574 if (!strcmp (type_name, "int"))
8575 klass = mono_defaults.int_class;
8576 else if (!strcmp (type_name, "ptr"))
8577 klass = mono_defaults.int_class;
8578 else if (!strcmp (type_name, "void"))
8579 klass = mono_defaults.void_class;
8580 else if (!strcmp (type_name, "int32"))
8581 klass = mono_defaults.int32_class;
8582 else if (!strcmp (type_name, "uint32"))
8583 klass = mono_defaults.uint32_class;
8584 else if (!strcmp (type_name, "int8"))
8585 klass = mono_defaults.sbyte_class;
8586 else if (!strcmp (type_name, "uint8"))
8587 klass = mono_defaults.byte_class;
8588 else if (!strcmp (type_name, "int16"))
8589 klass = mono_defaults.int16_class;
8590 else if (!strcmp (type_name, "uint16"))
8591 klass = mono_defaults.uint16_class;
8592 else if (!strcmp (type_name, "long"))
8593 klass = mono_defaults.int64_class;
8594 else if (!strcmp (type_name, "ulong"))
8595 klass = mono_defaults.uint64_class;
8596 else if (!strcmp (type_name, "float"))
8597 klass = mono_defaults.single_class;
8598 else if (!strcmp (type_name, "double"))
8599 klass = mono_defaults.double_class;
8600 else if (!strcmp (type_name, "object"))
8601 klass = mono_defaults.object_class;
8602 else if (!strcmp (type_name, "obj"))
8603 klass = mono_defaults.object_class;
8604 else if (!strcmp (type_name, "string"))
8605 klass = mono_defaults.string_class;
8606 else if (!strcmp (type_name, "bool"))
8607 klass = mono_defaults.boolean_class;
8608 else if (!strcmp (type_name, "boolean"))
8609 klass = mono_defaults.boolean_class;
8611 g_error ("%s", type_name);
8612 g_assert_not_reached ();
8614 return &klass->byval_arg;
8618 * LOCKING: Take the corlib image lock.
8620 MonoMethodSignature*
8621 mono_create_icall_signature (const char *sigstr)
8626 MonoMethodSignature *res, *res2;
8627 MonoImage *corlib = mono_defaults.corlib;
8629 mono_image_lock (corlib);
8630 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8631 mono_image_unlock (corlib);
8636 parts = g_strsplit (sigstr, " ", 256);
8645 res = mono_metadata_signature_alloc (corlib, len - 1);
8650 * Under windows, the default pinvoke calling convention is STDCALL but
8653 res->call_convention = MONO_CALL_C;
8656 res->ret = type_from_typename (parts [0]);
8657 for (i = 1; i < len; ++i) {
8658 res->params [i - 1] = type_from_typename (parts [i]);
8663 mono_image_lock (corlib);
8664 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8666 res = res2; /*Value is allocated in the image pool*/
8668 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8669 mono_image_unlock (corlib);
8675 mono_find_jit_icall_by_name (const char *name)
8677 MonoJitICallInfo *info;
8678 g_assert (jit_icall_hash_name);
8681 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8682 mono_icall_unlock ();
8687 mono_find_jit_icall_by_addr (gconstpointer addr)
8689 MonoJitICallInfo *info;
8690 g_assert (jit_icall_hash_addr);
8693 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8694 mono_icall_unlock ();
8700 * mono_get_jit_icall_info:
8702 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8703 * caller should access it while holding the icall lock.
8706 mono_get_jit_icall_info (void)
8708 return jit_icall_hash_name;
8712 * mono_lookup_jit_icall_symbol:
8714 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8717 mono_lookup_jit_icall_symbol (const char *name)
8719 MonoJitICallInfo *info;
8720 const char *res = NULL;
8723 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8725 res = info->c_symbol;
8726 mono_icall_unlock ();
8731 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8734 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8735 mono_icall_unlock ();
8739 * 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
8740 * icalls without wrappers in some cases.
8743 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8745 MonoJitICallInfo *info;
8752 if (!jit_icall_hash_name) {
8753 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8754 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8757 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8758 g_warning ("jit icall already defined \"%s\"\n", name);
8759 g_assert_not_reached ();
8762 info = g_new0 (MonoJitICallInfo, 1);
8767 info->c_symbol = c_symbol;
8768 info->no_raise = no_raise;
8771 info->wrapper = func;
8773 info->wrapper = NULL;
8776 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8777 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8779 mono_icall_unlock ();
8784 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8786 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);